1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | #include <errno(*__errno_location ()).h> |
27 | #include <stdlib.h> |
28 | #include <stdio.h> |
29 | #include <string.h> |
30 | #include <inttypes.h> |
31 | #include <png.h> |
32 | |
33 | #define min(x,y)(((x) < (y)) ? (x) : (y)) (((x) < (y)) ? (x) : (y)) |
34 | #define max(x,y)(((x) > (y)) ? (x) : (y)) (((x) > (y)) ? (x) : (y)) |
35 | |
36 | #ifndef png_jmpbuf |
37 | # define png_jmpbuf(png_ptr)(*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) ((png_ptr)->jmpbuf) |
38 | #endif |
39 | |
40 | |
41 | const char *program; |
42 | |
43 | |
44 | static inline void |
45 | write_le16(uint8_t *ptr, uint16_t v) |
46 | { |
47 | #if defined(__i386__) || defined(__x86_64__1) |
48 | *(uint16_t *)ptr = v; |
49 | #else |
50 | ptr[0] = (v & 0xff); |
51 | ptr[1] = (v >> 8) & 0xff; |
52 | #endif |
53 | } |
54 | |
55 | static inline void |
56 | write_le32(uint8_t *ptr, uint32_t v) |
57 | { |
58 | #if defined(__i386__) || defined(__x86_64__1) |
59 | *(uint32_t *)ptr = v; |
60 | #else |
61 | ptr[0] = (v & 0xff); |
62 | ptr[1] = (v >> 8) & 0xff; |
63 | ptr[2] = (v >> 16) & 0xff; |
64 | ptr[3] = (v >> 24) & 0xff; |
65 | #endif |
66 | } |
67 | |
68 | struct ico_common { |
69 | uint8_t resv[2]; |
70 | uint8_t type[2]; |
71 | uint8_t count[2]; |
72 | }; |
73 | |
74 | struct ico_hdr { |
75 | uint8_t width; |
76 | uint8_t height; |
77 | uint8_t colorcount; |
78 | uint8_t resv; |
79 | uint8_t planes[2]; |
80 | uint8_t bitcount[2]; |
81 | uint8_t sizeinbytes[4]; |
82 | uint8_t fileoffset[4]; |
83 | }; |
84 | |
85 | struct ico_info { |
86 | uint8_t headersize[4]; |
87 | uint8_t width[4]; |
88 | uint8_t height[4]; |
89 | uint8_t planes[2]; |
90 | uint8_t bitcount[2]; |
91 | uint8_t unused[6*4]; |
92 | }; |
93 | |
94 | struct ico_color { |
95 | uint8_t b, g, r; |
96 | uint8_t resv; |
97 | }; |
98 | |
99 | struct ico_fragment { |
100 | struct ico_fragment *next; |
101 | uint32_t offset; |
102 | |
103 | struct ico_hdr hdr; |
104 | struct ico_info info; |
105 | struct ico_color *pal; |
106 | uint32_t pal_size; |
107 | uint8_t *data; |
108 | uint32_t data_size; |
109 | uint8_t *alpha; |
110 | uint32_t alpha_size; |
111 | }; |
112 | |
113 | void * |
114 | xmalloc(size_t s) |
115 | { |
116 | void *p = malloc(s); |
| 28 | | Call to 'malloc' has an allocation size of 0 bytes |
|
117 | if ( !p ) { |
118 | perror(program); |
119 | exit(1); |
120 | } |
121 | |
122 | return p; |
123 | } |
124 | |
125 | void * |
126 | zalloc(size_t s) |
127 | { |
128 | void *p = xmalloc(s); |
| 26 | | Passing the value 0 via 1st parameter 's' | |
|
| |
129 | memset(p, 0, s); |
130 | return p; |
131 | } |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | static struct ico_fragment * |
138 | read_png(const char *file) |
139 | { |
140 | struct ico_fragment *frag; |
141 | struct ico_hdr *hdr; |
142 | struct ico_info *info; |
143 | struct ico_color *pal = NULL((void*)0); |
144 | uint8_t *data = NULL((void*)0); |
145 | uint8_t *alpha = NULL((void*)0); |
146 | FILE *fp = NULL((void*)0); |
147 | png_structp png_ptr = NULL((void*)0); |
148 | png_infop info_ptr = NULL((void*)0), end_info = NULL((void*)0); |
149 | png_uint_32 width, height; |
150 | int dwidth, awidth, bit_depth, color_type; |
151 | png_colorp palette; |
152 | int num_palette, max_colors; |
153 | png_bytep trans; |
154 | int num_trans; |
155 | uint8_t **row_pointers; |
156 | uint8_t *dbyte, *abyte; |
157 | int dshift, ashift, pixelshift; |
158 | unsigned int x, y; |
159 | int i; |
160 | int datasize, alphasize; |
161 | |
162 | frag = zalloc(sizeof(*frag)); |
163 | |
164 | hdr = &frag->hdr; |
165 | info = &frag->info; |
166 | |
167 | write_le32(info->headersize, sizeof(*info)); |
168 | write_le16(hdr->planes, 1); |
169 | write_le16(info->planes, 1); |
170 | |
171 | fp = fopen(file, "rb"); |
172 | if ( !fp ) { |
| 1 | Assuming 'fp' is non-null | |
|
| |
173 | goto perrexit; |
174 | } |
175 | |
176 | png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING"1.6.12", |
177 | NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
178 | if ( !png_ptr ) { |
| 3 | | Assuming 'png_ptr' is non-null | |
|
| |
179 | errno(*__errno_location ()) = ENOMEM12; |
180 | goto perrexit; |
181 | } |
182 | |
183 | info_ptr = png_create_info_struct(png_ptr); |
184 | if ( !info_ptr ) { |
| 5 | | Assuming 'info_ptr' is non-null | |
|
| |
185 | errno(*__errno_location ()) = ENOMEM12; |
186 | goto perrexit; |
187 | } |
188 | |
189 | end_info = png_create_info_struct(png_ptr); |
190 | if ( !end_info ) { |
| 7 | | Assuming 'end_info' is non-null | |
|
| |
191 | errno(*__errno_location ()) = ENOMEM12; |
192 | goto perrexit; |
193 | } |
194 | |
195 | if ( setjmp(png_jmpbuf(png_ptr))_setjmp ((*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf ))))) ) { |
| |
196 | fprintf(stderrstderr, "%s: PNG format error\n", file); |
197 | goto errexit; |
198 | } |
199 | |
200 | png_init_io(png_ptr, fp); |
201 | png_read_info(png_ptr, info_ptr); |
202 | |
203 | |
204 | png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, |
205 | NULL((void*)0), NULL((void*)0), NULL((void*)0)); |
206 | |
207 | if ( height > 255 || width > 255 ) { |
| 10 | | Assuming 'height' is <= 255 | |
|
| 11 | | Assuming 'width' is <= 255 | |
|
| |
208 | fprintf(stderrstderr, "%s: Image too large\n", file); |
209 | goto errexit; |
210 | } |
211 | |
212 | if ( color_type != PNG_COLOR_TYPE_PALETTE(2 | 1) ) { |
| |
213 | fprintf(stderrstderr, "%s: Not a palettized image\n", file); |
214 | goto errexit; |
215 | } |
216 | |
217 | if ( bit_depth > 8 ) { |
| 14 | | Assuming 'bit_depth' is <= 8 | |
|
| |
218 | fprintf(stderrstderr, "%s: Too many colors used\n", file); |
219 | goto errexit; |
220 | } |
221 | |
222 | if ( !png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) ) { |
| |
223 | fprintf(stderrstderr, "%s: Palette data missing\n", file); |
224 | goto errexit; |
225 | } |
226 | if ( !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, 0) ) { |
| |
227 | num_trans = 0; |
228 | } |
229 | |
230 | |
231 | if ( bit_depth < 8 ) |
| 18 | | Assuming 'bit_depth' is >= 8 | |
|
| |
232 | png_set_packing(png_ptr); |
233 | |
234 | |
235 | png_read_update_info(png_ptr, info_ptr); |
236 | |
237 | row_pointers = xmalloc(sizeof(uint8_t *) * height); |
238 | for ( y = 0 ; y < height ; y++ ) { |
| 20 | | Assuming 'y' is >= 'height' | |
|
| 21 | | Loop condition is false. Execution continues on line 242 | |
|
239 | row_pointers[y] = xmalloc(width); |
240 | } |
241 | |
242 | png_read_image(png_ptr, row_pointers); |
243 | |
244 | |
245 | |
246 | |
247 | hdr->width = width; write_le32(info->width, width); |
248 | hdr->height = height; write_le32(info->height, 2*height); |
249 | |
250 | if ( num_palette <= 2 ) { |
| 22 | | Assuming 'num_palette' is <= 2 | |
|
| |
251 | |
252 | dwidth = ((width+31) & ~31) >> 3; |
253 | pixelshift = 1; |
254 | } else if ( num_palette <= 16 ) { |
255 | |
256 | dwidth = ((width+7) & ~7) >> 1; |
257 | pixelshift = 4; |
258 | } else { |
259 | |
260 | dwidth = (width+3) & ~3; |
261 | pixelshift = 8; |
262 | } |
263 | max_colors = 1 << pixelshift; |
264 | awidth = ((width+31) & ~31) >> 3; |
265 | |
266 | write_le16(hdr->bitcount, pixelshift); |
267 | write_le16(info->bitcount, pixelshift); |
268 | |
269 | frag->data = data = zalloc(datasize = dwidth*height); |
| 24 | | Passing the value 0 via 1st parameter 's' | |
|
| |
270 | frag->data_size = datasize; |
271 | frag->alpha = alpha = zalloc(alphasize = awidth*height); |
272 | frag->alpha_size = alphasize; |
273 | |
274 | hdr->colorcount = max_colors & 0xff; |
275 | frag->pal = pal = zalloc(max_colors * sizeof(*pal)); |
276 | frag->pal_size = max_colors * sizeof(*pal); |
277 | |
278 | write_le32(hdr->sizeinbytes, |
279 | sizeof(*info)+frag->pal_size+datasize+alphasize); |
280 | |
281 | for ( i = 0 ; i < min(num_palette, max_colors)(((num_palette) < (max_colors)) ? (num_palette) : (max_colors )) ; i++ ) { |
282 | pal[i].r = palette[i].red; |
283 | pal[i].g = palette[i].green; |
284 | pal[i].b = palette[i].blue; |
285 | } |
286 | |
287 | for ( y = 0 ; y < height ; y++ ) { |
288 | dbyte = data + (height-y-1)*dwidth; |
289 | abyte = alpha + (height-y-1)*awidth; |
290 | dshift = 8-pixelshift; ashift = 7; |
291 | |
292 | for ( x = 0 ; x < width ; x++ ) { |
293 | uint8_t index = row_pointers[y][x]; |
294 | uint8_t pixel = index; |
295 | uint8_t ptran = (index < num_trans) ? trans[index] : 255; |
296 | |
297 | if ( ptran == 0 ) { |
298 | pixel = 0; |
299 | } else if ( ptran != 255 ) { |
300 | fprintf(stderrstderr, "%s: Warning: partial transparency (%d/255) ignored\n", |
301 | file, ptran); |
302 | } |
303 | |
304 | *dbyte |= pixel << dshift; |
305 | dshift -= pixelshift; |
306 | if ( dshift < 0 ) { |
307 | dshift += 8; |
308 | dbyte++; |
309 | } |
310 | |
311 | *abyte |= (ptran ? 0 : 1) << ashift; |
312 | ashift--; |
313 | if ( ashift < 0 ) { |
314 | ashift += 8; |
315 | abyte++; |
316 | } |
317 | } |
318 | |
319 | |
320 | free(row_pointers[y]); |
321 | } |
322 | free(row_pointers); |
323 | |
324 | |
325 | |
326 | png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); |
327 | fclose(fp); |
328 | return frag; |
329 | |
330 | perrexit: |
331 | perror(file); |
332 | errexit: |
333 | if ( png_ptr ) { |
334 | png_destroy_read_struct(png_ptr ? &png_ptr : NULL((void*)0), |
335 | info_ptr ? &info_ptr : NULL((void*)0), |
336 | end_info ? &end_info : NULL((void*)0)); |
337 | } |
338 | if ( fp ) fclose(fp); |
339 | if ( pal ) free(pal); |
340 | if ( data ) free(data); |
341 | if ( alpha ) free(alpha); |
342 | free(frag); |
343 | return NULL((void*)0); |
344 | } |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | int main(int argc, char *argv[]) |
351 | { |
352 | struct ico_fragment *frag; |
353 | struct ico_fragment *list = NULL((void*)0); |
354 | struct ico_fragment **tail = &list; |
355 | struct ico_common common; |
356 | int count = 0; |
357 | int i; |
358 | uint32_t offset; |
359 | |
360 | for ( i = 1 ; i < argc ; i++ ) { |
361 | if ( !(frag = read_png(argv[i])) ) |
362 | return 1; |
363 | |
364 | count++; |
365 | *tail = frag; |
366 | tail = &frag->next; |
367 | } |
368 | |
369 | memset(&common, 0, sizeof(common)); |
370 | write_le16(common.type, 1); |
371 | write_le16(common.count, count); |
372 | |
373 | |
374 | fwrite(&common, sizeof(common), 1, stdoutstdout); |
375 | |
376 | offset = sizeof(common) + count*sizeof(struct ico_hdr); |
377 | |
378 | for ( frag = list ; frag ; frag = frag->next ) { |
379 | write_le32(frag->hdr.fileoffset, offset); |
380 | fwrite(&frag->hdr, sizeof(struct ico_hdr), 1, stdoutstdout); |
381 | |
382 | offset += sizeof(struct ico_info) + frag->pal_size + frag->data_size + frag->alpha_size; |
383 | } |
384 | |
385 | for ( frag = list ; frag ; frag = frag->next ) { |
386 | fwrite(&frag->info, sizeof(struct ico_info), 1, stdoutstdout); |
387 | fwrite(frag->pal, 1, frag->pal_size, stdoutstdout); |
388 | fwrite(frag->data, 1, frag->data_size, stdoutstdout); |
389 | fwrite(frag->alpha, 1, frag->alpha_size, stdoutstdout); |
390 | } |
391 | |
392 | return 0; |
393 | } |
394 | |