Mercurial > libavformat.hg
comparison png.c @ 44:7c5da7e7239a libavformat
added basic png handling
author | bellard |
---|---|
date | Sat, 01 Feb 2003 20:53:57 +0000 |
parents | |
children | bde449e6b743 |
comparison
equal
deleted
inserted
replaced
43:a23fb606308a | 44:7c5da7e7239a |
---|---|
1 /* | |
2 * PNG image format | |
3 * Copyright (c) 2003 Fabrice Bellard. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avformat.h" | |
20 | |
21 #include "libpng/png.h" | |
22 | |
23 extern const uint8_t png_sig[]; | |
24 | |
25 static int png_probe(AVProbeData *pd) | |
26 { | |
27 if (pd->buf_size >= 8 && | |
28 memcmp(pd->buf, png_sig, 8) == 0) | |
29 return AVPROBE_SCORE_MAX; | |
30 else | |
31 return 0; | |
32 } | |
33 | |
34 png_voidp PNGAPI | |
35 png_memset_check (png_structp png_ptr, png_voidp s1, int value, | |
36 png_uint_32 length) | |
37 { | |
38 png_size_t size; | |
39 | |
40 size = (png_size_t)length; | |
41 if ((png_uint_32)size != length) | |
42 png_error(png_ptr,"Overflow in png_memset_check."); | |
43 | |
44 return (png_memset (s1, value, size)); | |
45 | |
46 } | |
47 | |
48 png_voidp PNGAPI | |
49 png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2, | |
50 png_uint_32 length) | |
51 { | |
52 png_size_t size; | |
53 | |
54 size = (png_size_t)length; | |
55 if ((png_uint_32)size != length) | |
56 png_error(png_ptr,"Overflow in png_memcpy_check."); | |
57 | |
58 return(png_memcpy (s1, s2, size)); | |
59 } | |
60 | |
61 void png_error (png_struct *png_ptr, const char *message) | |
62 { | |
63 longjmp(png_ptr->jmpbuf, 0); | |
64 } | |
65 | |
66 void png_warning (png_struct *png_ptr, const char *message) | |
67 { | |
68 } | |
69 | |
70 void PNGAPI | |
71 png_chunk_error(png_structp png_ptr, png_const_charp error_message) | |
72 { | |
73 char msg[18+64]; | |
74 // png_format_buffer(png_ptr, msg, error_message); | |
75 png_error(png_ptr, msg); | |
76 } | |
77 | |
78 void PNGAPI | |
79 png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) | |
80 { | |
81 char msg[18+64]; | |
82 // png_format_buffer(png_ptr, msg, warning_message); | |
83 png_warning(png_ptr, msg); | |
84 } | |
85 | |
86 void png_read_data (png_struct *png_ptr, png_byte *data, png_uint_32 length) | |
87 { | |
88 int ret; | |
89 | |
90 ret = get_buffer(png_ptr->io_ptr, data, length); | |
91 if (ret != length) | |
92 png_error (png_ptr, "Read Error"); | |
93 } | |
94 | |
95 void *png_malloc (png_struct *png_ptr, png_uint_32 size) | |
96 { | |
97 return av_malloc(size); | |
98 } | |
99 | |
100 void png_free (png_struct *png_ptr, void *ptr) | |
101 { | |
102 return av_free(ptr); | |
103 } | |
104 | |
105 static int png_read(ByteIOContext *f, | |
106 int (*alloc_cb)(void *opaque, AVImageInfo *info), void *opaque) | |
107 { | |
108 png_struct png_struct1, *png_ptr; | |
109 png_info png_info1, png_info2, *info_ptr, *end_info; | |
110 AVImageInfo info1, *info = &info1; | |
111 int y, height, ret, row_size; | |
112 uint8_t *ptr; | |
113 | |
114 png_ptr = &png_struct1; | |
115 png_read_init(png_ptr); | |
116 | |
117 info_ptr = &png_info1; | |
118 end_info = &png_info2; | |
119 | |
120 png_info_init(info_ptr); | |
121 png_info_init(end_info); | |
122 | |
123 png_ptr->io_ptr = f; | |
124 | |
125 if (setjmp(png_jmpbuf(png_ptr))) { | |
126 png_read_destroy (png_ptr, info_ptr, NULL); | |
127 return -1; | |
128 } | |
129 | |
130 png_read_info (png_ptr, info_ptr); | |
131 | |
132 /* init image info */ | |
133 info->width = info_ptr->width; | |
134 info->height = info_ptr->height; | |
135 | |
136 if (info_ptr->bit_depth == 8 && | |
137 info_ptr->color_type == PNG_COLOR_TYPE_RGB) { | |
138 info->pix_fmt = PIX_FMT_RGB24; | |
139 row_size = info_ptr->width * 3; | |
140 } else if (info_ptr->bit_depth == 8 && | |
141 info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { | |
142 info->pix_fmt = PIX_FMT_GRAY8; | |
143 row_size = info_ptr->width; | |
144 } else if (info_ptr->bit_depth == 1 && | |
145 info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { | |
146 info->pix_fmt = PIX_FMT_MONOBLACK; | |
147 row_size = (info_ptr->width + 7) >> 3; | |
148 } else { | |
149 png_read_destroy (png_ptr, info_ptr, NULL); | |
150 return -1; | |
151 } | |
152 ret = alloc_cb(opaque, info); | |
153 if (ret) { | |
154 png_read_destroy (png_ptr, info_ptr, NULL); | |
155 return ret; | |
156 } | |
157 | |
158 /* now read the whole image */ | |
159 png_start_read_image (png_ptr); | |
160 | |
161 height = info->height; | |
162 ptr = info->pict.data[0]; | |
163 for (y = 0; y < height; y++) { | |
164 png_read_row (png_ptr, NULL, NULL); | |
165 memcpy(ptr, png_ptr->row_buf + 1, row_size); | |
166 ptr += info->pict.linesize[0]; | |
167 } | |
168 | |
169 png_read_destroy (png_ptr, info_ptr, NULL); | |
170 return 0; | |
171 } | |
172 | |
173 void | |
174 png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) | |
175 { | |
176 put_buffer(png_ptr->io_ptr, data, length); | |
177 } | |
178 | |
179 static int png_write(ByteIOContext *pb, AVImageInfo *info) | |
180 { | |
181 png_struct png_struct1, *png_ptr; | |
182 png_info png_info1, *info_ptr; | |
183 int w, h, y; | |
184 uint8_t *ptr; | |
185 | |
186 png_ptr = &png_struct1; | |
187 info_ptr = &png_info1; | |
188 | |
189 png_write_init(png_ptr); | |
190 png_info_init(info_ptr); | |
191 | |
192 png_ptr->io_ptr = pb; | |
193 | |
194 if (setjmp(png_ptr->jmpbuf)) { | |
195 png_write_destroy(png_ptr); | |
196 return -1; | |
197 } | |
198 | |
199 w = info->width; | |
200 h = info->height; | |
201 | |
202 info_ptr->width = w; | |
203 info_ptr->height = h; | |
204 switch(info->pix_fmt) { | |
205 case PIX_FMT_RGB24: | |
206 info_ptr->bit_depth = 8; | |
207 info_ptr->color_type = PNG_COLOR_TYPE_RGB; | |
208 break; | |
209 case PIX_FMT_GRAY8: | |
210 info_ptr->bit_depth = 8; | |
211 info_ptr->color_type = PNG_COLOR_TYPE_GRAY; | |
212 break; | |
213 case PIX_FMT_MONOBLACK: | |
214 info_ptr->bit_depth = 1; | |
215 info_ptr->color_type = PNG_COLOR_TYPE_GRAY; | |
216 break; | |
217 default: | |
218 return -1; | |
219 } | |
220 png_write_info(png_ptr, info_ptr); | |
221 | |
222 ptr = info->pict.data[0]; | |
223 for(y=0;y<h;y++) { | |
224 png_write_row(png_ptr, ptr); | |
225 ptr += info->pict.linesize[0]; | |
226 } | |
227 png_write_end(png_ptr, info_ptr); | |
228 png_write_destroy(png_ptr); | |
229 put_flush_packet(pb); | |
230 return 0; | |
231 } | |
232 | |
233 AVImageFormat png_image_format = { | |
234 "png", | |
235 "png", | |
236 png_probe, | |
237 png_read, | |
238 (1 << PIX_FMT_RGB24) | (1 << PIX_FMT_GRAY8) | (1 << PIX_FMT_MONOBLACK), | |
239 png_write, | |
240 }; |