pngdefry 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ enum
2
+ {
3
+ TDEFL_WRITE_ZLIB_HEADER = 0x01000,
4
+ TDEFL_COMPUTE_ADLER32 = 0x02000,
5
+ TDEFL_GREEDY_PARSING_FLAG = 0x04000,
6
+ TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
7
+ TDEFL_RLE_MATCHES = 0x10000,
8
+ TDEFL_FILTER_MATCHES = 0x20000,
9
+ TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
10
+ TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
11
+ };
12
+
13
+ enum
14
+ {
15
+ TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
16
+ TINFL_FLAG_HAS_MORE_INPUT = 2,
17
+ TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
18
+ TINFL_FLAG_COMPUTE_ADLER32 = 8
19
+ };
20
+
21
+ size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
22
+ size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
@@ -0,0 +1,1286 @@
1
+ /* pngdefry.c v1.1 - public domain PNG reading/writing/modification, PNG writing
2
+ See "unlicense" statement at the end of this file.
3
+
4
+ [Jongware], 21-Jan-2012
5
+
6
+ Attempts to repair -iphone "optimized" PNG images by removing the invalid chunk "CgBI",
7
+ swapping pixel order from BGR(A) to RGB(A), and removing pre-multiplied alpha.
8
+
9
+ Use with care. No guarantees.
10
+
11
+ This program uses miniz.c (http://code.google.com/p/miniz/) by Rich Geldreich
12
+ (Rich Geldreich <richgel99@gmail.com>, last updated May 27, 2011)
13
+ Version used is included in the original file package.
14
+
15
+ No-License Agreement
16
+ ====================
17
+ This program is hereby put into the public domain, no limitations at all. Do with this code
18
+ whatever you want, I don't care. (Well, replacing my name with yours and leaving everything
19
+ else unchanged would be pretty lame.)
20
+ */
21
+
22
+ #include <stdio.h>
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+ #include <strings.h>
26
+ #include <sys/types.h>
27
+
28
+ #include "miniz.h"
29
+
30
+
31
+ /** Global flags, set on the command line **/
32
+ int flag_Verbose = 0;
33
+ int flag_Process_Anyway = 0;
34
+ int flag_List_Chunks = 0;
35
+ int flag_Debug = 0;
36
+ int flag_UpdateAlpha = 1;
37
+ int repack_IDAT_size = 524288; /* 512K -- seems a bit much to me, axually, but have seen this used */
38
+
39
+ int flag_Rewrite = 0;
40
+
41
+ char *suffix = NULL;
42
+ char *outputPath = NULL;
43
+
44
+ unsigned char png_magic_bytes[] = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
45
+
46
+ /** Chunk data comes here **/
47
+
48
+ struct chunk_t {
49
+ unsigned int length;
50
+ unsigned int id;
51
+ unsigned char *data;
52
+ unsigned int crc32;
53
+ };
54
+
55
+ int num_chunks = 0;
56
+ int max_chunks = 0;
57
+
58
+ struct chunk_t *pngChunks = NULL;
59
+
60
+
61
+ /** CRC32 generator for a block of data, thanks to Marc Autret
62
+ (he wrote this original code in Javascript for use in InDesign!) **/
63
+
64
+ unsigned int CRC_256[] = {
65
+ 0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
66
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
67
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
68
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
69
+ 0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,
70
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
71
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
72
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
73
+ 0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,
74
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
75
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
76
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
77
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,
78
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
79
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
80
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
81
+ };
82
+
83
+ int crc32s (unsigned char *buf, int buf_length)
84
+ {
85
+ unsigned int c = 0xffffffff;
86
+ int i;
87
+ for (i=0; i < buf_length; i++ )
88
+ c = CRC_256[(c ^ buf[i]) & 0xff] ^ (c >> 8);
89
+
90
+ return (c ^ 0xffffffff);
91
+ };
92
+
93
+ int get_long (FILE *f)
94
+ {
95
+ return (fgetc(f)<<24) + (fgetc(f)<<16) + (fgetc(f)<<8) + fgetc(f);
96
+ }
97
+
98
+ int get_short (FILE *f)
99
+ {
100
+ return (fgetc(f)<<8) + fgetc(f);
101
+ }
102
+
103
+ int read_long (void *src)
104
+ {
105
+ return (((unsigned char *)src)[0]<<24) + (((unsigned char *)src)[1]<<16) + (((unsigned char *)src)[2]<<8) + ((unsigned char *)src)[3];
106
+ }
107
+
108
+
109
+ int init_chunk (FILE *f, unsigned int filelength)
110
+ {
111
+ struct chunk_t one_chunk;
112
+ unsigned char buf[8];
113
+
114
+ if (fread (buf, 1,4, f) != 4)
115
+ {
116
+ if (feof(f))
117
+ return 0;
118
+ if (flag_Debug)
119
+ printf (" informational : failed to read chunk length\n");
120
+ return -3;
121
+ }
122
+
123
+ one_chunk.length = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
124
+
125
+ if (one_chunk.length > filelength-4)
126
+ {
127
+ if (flag_Debug)
128
+ printf (" informational : chunk length %u larger than file\n", one_chunk.length);
129
+ return -1;
130
+ }
131
+
132
+ one_chunk.data = (unsigned char *)malloc (one_chunk.length+4);
133
+ if (one_chunk.data == NULL)
134
+ {
135
+ if (flag_Debug)
136
+ printf (" informational : no memory for chunk length %u\n", one_chunk.length);
137
+ return -2;
138
+ }
139
+ if (fread (one_chunk.data, 1, one_chunk.length+4, f) != one_chunk.length+4)
140
+ {
141
+ if (flag_Debug)
142
+ printf (" informational : failed to read chunk length %u\n", one_chunk.length);
143
+ return -3;
144
+ }
145
+ one_chunk.id = (one_chunk.data[0] << 24) + (one_chunk.data[1] << 16) + (one_chunk.data[2] << 8) + one_chunk.data[3];
146
+
147
+ if (fread (buf, 1,4, f) != 4)
148
+ {
149
+ if (flag_Debug)
150
+ printf (" informational : failed to read chunk crc32\n");
151
+ return -3;
152
+ }
153
+ one_chunk.crc32 = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
154
+
155
+ if (num_chunks >= max_chunks)
156
+ {
157
+ max_chunks += 8;
158
+ if (pngChunks == NULL)
159
+ pngChunks = (struct chunk_t *)malloc (max_chunks * sizeof(struct chunk_t));
160
+ else
161
+ pngChunks = (struct chunk_t *)realloc (pngChunks, max_chunks * sizeof(struct chunk_t));
162
+ }
163
+ pngChunks[num_chunks].id = one_chunk.id;
164
+ pngChunks[num_chunks].length = one_chunk.length;
165
+ pngChunks[num_chunks].data = one_chunk.data;
166
+ pngChunks[num_chunks].crc32 = one_chunk.crc32;
167
+ num_chunks++;
168
+
169
+ return 0;
170
+ }
171
+
172
+ void reset_chunks (void)
173
+ {
174
+ int i;
175
+
176
+ for (i=0; i<num_chunks; i++)
177
+ {
178
+ if (pngChunks[i].length && pngChunks[i].data)
179
+ {
180
+ free (pngChunks[i].data);
181
+ pngChunks[i].data = NULL;
182
+ }
183
+ }
184
+ num_chunks = 0;
185
+ }
186
+
187
+ void demultiplyAlpha (int wide, int high, unsigned char *data)
188
+ {
189
+ int x,y;
190
+ unsigned char *srcPtr;
191
+
192
+ srcPtr = data;
193
+
194
+ for (y=0; y<high; y++)
195
+ {
196
+ /* skip rowfilter -- it's assumed to be 0 here anyway! */
197
+ srcPtr++;
198
+ for (x=0; x<4*wide; x+=4)
199
+ {
200
+ if (srcPtr[x+3])
201
+ {
202
+ srcPtr[x] = (srcPtr[x]*255+(srcPtr[x+3]>>1))/srcPtr[x+3];
203
+ srcPtr[x+1] = (srcPtr[x+1]*255+(srcPtr[x+3]>>1))/srcPtr[x+3];
204
+ srcPtr[x+2] = (srcPtr[x+2]*255+(srcPtr[x+3]>>1))/srcPtr[x+3];
205
+ }
206
+ }
207
+ srcPtr += 4*wide;
208
+ }
209
+ }
210
+
211
+ void removeRowFilters (int wide, int high, unsigned char *data)
212
+ {
213
+ int x,y, rowfilter;
214
+ unsigned char *srcPtr, *upPtr;
215
+
216
+ srcPtr = data;
217
+
218
+ for (y=0; y<high; y++)
219
+ {
220
+ rowfilter = *srcPtr;
221
+ /* Need to save original filter for re-applying! */
222
+ /* *srcPtr = 0; */
223
+ srcPtr++;
224
+ switch (rowfilter)
225
+ {
226
+ case 0: // None
227
+ break;
228
+ case 1: // Sub
229
+ for (x=4; x<4*wide; x++)
230
+ {
231
+ srcPtr[x] += srcPtr[x-4];
232
+ }
233
+ break;
234
+ case 2: // Up
235
+ upPtr = srcPtr - 4*wide - 1;
236
+ if (y > 0)
237
+ {
238
+ for (x=0; x<4*wide; x++)
239
+ {
240
+ srcPtr[x] += upPtr[x];
241
+ }
242
+ }
243
+ break;
244
+ case 3: // Average
245
+ upPtr = srcPtr - 4*wide - 1;
246
+ if (y == 0)
247
+ {
248
+ for (x=4; x<4*wide; x++)
249
+ {
250
+ srcPtr[x] += (srcPtr[x-4]>>1);
251
+ }
252
+ } else
253
+ {
254
+ srcPtr[0] += (upPtr[x]>>1);
255
+ for (x=4; x<4*wide; x++)
256
+ {
257
+ srcPtr[x] += ((upPtr[x] + srcPtr[x-4])>>1);
258
+ }
259
+ }
260
+ break;
261
+ case 4: // Paeth
262
+ upPtr = srcPtr - 4*wide - 1;
263
+ {
264
+ int p,pa,pb,pc,value;
265
+ int leftpix,toppix,topleftpix;
266
+
267
+ for (x=0; x<4*wide; x++)
268
+ {
269
+ leftpix = 0;
270
+ toppix = 0;
271
+ topleftpix = 0;
272
+ if (x > 0)
273
+ leftpix = srcPtr[x-4];
274
+ if (y > 0)
275
+ {
276
+ toppix = upPtr[x];
277
+ if (x >= 4)
278
+ topleftpix = upPtr[x-4];
279
+ }
280
+ p = leftpix + toppix - topleftpix;
281
+ pa = p - leftpix; if (pa < 0) pa = -pa;
282
+ pb = p - toppix; if (pb < 0) pb = -pb;
283
+ pc = p - topleftpix; if (pc < 0) pc = -pc;
284
+ if (pa <= pb && pa <= pc)
285
+ value = leftpix;
286
+ else if (pb <= pc)
287
+ value = toppix;
288
+ else
289
+ value = topleftpix;
290
+
291
+ srcPtr[x] += value;
292
+ }
293
+ }
294
+ break;
295
+ default:
296
+ printf ("removerowfilter() : Unknown row filter %d\n", rowfilter);
297
+ }
298
+ srcPtr += 4*wide;
299
+ }
300
+ }
301
+
302
+ void applyRowFilters (int wide, int high, unsigned char *data)
303
+ {
304
+ int x,y, rowfilter;
305
+ unsigned char *srcPtr, *upPtr;
306
+
307
+ srcPtr = data;
308
+
309
+ for (y=0; y<high; y++)
310
+ {
311
+ rowfilter = *srcPtr;
312
+ srcPtr++;
313
+ switch (rowfilter)
314
+ {
315
+ case 0: // None
316
+ break;
317
+ case 1: // Sub
318
+ for (x=4*wide-1; x>=4; x--)
319
+ {
320
+ srcPtr[x] -= srcPtr[x-4];
321
+ }
322
+ break;
323
+ case 2: // Up
324
+ if (y > 0)
325
+ {
326
+ upPtr = srcPtr - 1;
327
+ for (x=4*wide-1; x>=0; x--)
328
+ {
329
+ srcPtr[x] -= upPtr[x];
330
+ }
331
+ }
332
+ break;
333
+ case 3: // Average
334
+ upPtr = srcPtr - 4*wide - 1;
335
+ if (y == 0)
336
+ {
337
+ for (x=4*wide-1; x>=4; x--)
338
+ {
339
+ srcPtr[x] -= (srcPtr[x-4]>>1);
340
+ }
341
+ } else
342
+ {
343
+ srcPtr[0] -= (upPtr[x]>>1);
344
+ for (x=4*wide-1; x>=4; x--)
345
+ {
346
+ srcPtr[x] -= ((upPtr[x] + srcPtr[x-4])>>1);
347
+ }
348
+ }
349
+ break;
350
+ case 4: // Paeth
351
+ upPtr = srcPtr - 1;
352
+ {
353
+ int p,pa,pb,pc,value;
354
+ int leftpix,toppix,topleftpix;
355
+
356
+ for (x=4*wide-1; x>=0; x--)
357
+ {
358
+ leftpix = 0;
359
+ toppix = 0;
360
+ topleftpix = 0;
361
+ if (x > 0)
362
+ leftpix = srcPtr[x-4];
363
+ if (y > 0)
364
+ {
365
+ toppix = upPtr[x];
366
+ if (x >= 4)
367
+ topleftpix = upPtr[x-4];
368
+ }
369
+ p = leftpix + toppix - topleftpix;
370
+ pa = p - leftpix; if (pa < 0) pa = -pa;
371
+ pb = p - toppix; if (pb < 0) pb = -pb;
372
+ pc = p - topleftpix; if (pc < 0) pc = -pc;
373
+ if (pa <= pb && pa <= pc)
374
+ value = leftpix;
375
+ else if (pb <= pc)
376
+ value = toppix;
377
+ else
378
+ value = topleftpix;
379
+
380
+ srcPtr[x] -= value;
381
+ }
382
+ }
383
+ break;
384
+ default:
385
+ printf ("applyrowfilter : Unknown row filter %d\n", rowfilter);
386
+ }
387
+ srcPtr += 4*wide;
388
+ }
389
+ }
390
+
391
+ int process (char *filename, char *write_file_name)
392
+ {
393
+ FILE *f;
394
+ unsigned int length;
395
+ int i;
396
+ unsigned char buf[16];
397
+
398
+ /* This is what we're looking for */
399
+ int isPhoney = 0;
400
+
401
+ /* Standard IHDR items: */
402
+ unsigned int imgwidth, imgheight, bitdepth,colortype, compression, filter, interlace;
403
+ /* Derived IHRD items: */
404
+ unsigned int bitspp;
405
+ unsigned int bytespp;
406
+ unsigned int bytespline;
407
+
408
+ struct chunk_t *ihdr_chunk = NULL;
409
+ int idat_first_index = 0;
410
+ unsigned char *all_idat = NULL;
411
+ unsigned int total_idat_size = 0;
412
+
413
+ /* Adam7 interlacing information */
414
+ int Starting_Row [] = { 0, 0, 4, 0, 2, 0, 1 };
415
+ int Starting_Col [] = { 0, 4, 0, 2, 0, 1, 0 };
416
+ int Row_Increment [] = { 8, 8, 8, 4, 4, 2, 2 };
417
+ int Col_Increment [] = { 8, 8, 4, 4, 2, 2, 1 };
418
+ int row_filter_bytes = 0;
419
+
420
+ /* Needed for unpacking/repacking */
421
+ unsigned char *data_out;
422
+ int out_length;
423
+ unsigned char *data_repack = NULL;
424
+ int repack_size, repack_length;
425
+
426
+ /* New file name comes here */
427
+ FILE *write_file;
428
+ int write_block_size;
429
+
430
+ /* int i,j,b;
431
+ int blocklength, blockid;
432
+ unsigned int filterbytes;
433
+ int isInterlaced = 0; */
434
+
435
+ int didShowName = 0;
436
+
437
+ int crc, result;
438
+
439
+ f = fopen (filename, "rb");
440
+ if (!f)
441
+ {
442
+ printf ("%s : not found or could not be opened\n", filename);
443
+ return 0;
444
+ }
445
+
446
+ fseek (f, 0, SEEK_END);
447
+ length = ftell (f);
448
+ fseek (f, 0, SEEK_SET);
449
+
450
+ i = 0;
451
+
452
+ fread (buf,1,8, f); i += 8;
453
+ if (memcmp (buf, png_magic_bytes, 8))
454
+ {
455
+ printf ("%s : not a PNG file\n", filename);
456
+ fclose (f);
457
+ return 0;
458
+ }
459
+ result = init_chunk (f, length);
460
+ if (result < 0)
461
+ {
462
+ fclose (f);
463
+ switch (result)
464
+ {
465
+ case -1: printf ("%s : invalid chunk size\n", filename); break;
466
+ case -2: printf ("%s : out of memory\n", filename); break;
467
+ case -3: printf ("%s : premature end of file\n", filename); break;
468
+ }
469
+ reset_chunks ();
470
+ return 0;
471
+ }
472
+
473
+ isPhoney = 1;
474
+ if (pngChunks[0].id != 0x43674249) /* "CgBI" */
475
+ {
476
+ isPhoney = 0;
477
+ printf ("%s : not an -iphone crushed PNG file\n", filename);
478
+ if (!flag_Process_Anyway)
479
+ {
480
+ fclose (f);
481
+ reset_chunks ();
482
+ return 0;
483
+ }
484
+ didShowName = 1;
485
+ }
486
+
487
+ do
488
+ {
489
+ result = init_chunk (f, length);
490
+ if (result < 0)
491
+ {
492
+ fclose (f);
493
+
494
+ if (didShowName)
495
+ printf (" ");
496
+ else
497
+ {
498
+ didShowName = 1;
499
+ printf ("%s : ", filename);
500
+ }
501
+ switch (result)
502
+ {
503
+ case -1: printf ("invalid chunk size\n"); break;
504
+ case -2: printf ("out of memory\n"); break;
505
+ case -3: printf ("premature end of file\n"); break;
506
+ default: printf ("error code %d\n", result);
507
+ }
508
+ reset_chunks ();
509
+ return 0;
510
+ }
511
+ if (num_chunks > 0 && pngChunks[num_chunks-1].id == 0x49454E44) /* "IEND" */
512
+ break;
513
+ } while (!feof(f));
514
+
515
+ if (pngChunks[num_chunks-1].id != 0x49454E44) /* "IEND" */
516
+ {
517
+ fclose (f);
518
+
519
+ if (didShowName)
520
+ printf (" ");
521
+ else
522
+ {
523
+ didShowName = 1;
524
+ printf ("%s : ", filename);
525
+ }
526
+ printf ("missing IEND chunk\n");
527
+ reset_chunks ();
528
+ return 0;
529
+ }
530
+
531
+ if (fgetc (f) != EOF)
532
+ {
533
+ if (didShowName)
534
+ printf (" ");
535
+ else
536
+ {
537
+ didShowName = 1;
538
+ printf ("%s : ", filename);
539
+ }
540
+ printf ("Extra data after IEND, very suspicious! Excluded from conversion\n");
541
+ }
542
+ fclose (f);
543
+
544
+ if (flag_List_Chunks)
545
+ {
546
+ for (i=0; i<num_chunks; i++)
547
+ {
548
+ if (!didShowName)
549
+ {
550
+ didShowName = 1;
551
+ printf ("%s :\n", filename);
552
+ }
553
+ printf (" chunk : %c%c%c%c length %6u CRC32 %08X", (pngChunks[i].id >> 24) & 0xff,(pngChunks[i].id >> 16) & 0xff, (pngChunks[i].id >> 8) & 0xff,pngChunks[i].id & 0xff, pngChunks[i].length, pngChunks[i].crc32);
554
+ crc = crc32s (pngChunks[i].data, pngChunks[i].length+4);
555
+ if (pngChunks[i].crc32 != crc)
556
+ printf (" --> CRC32 check invalid! Should be %08X", crc);
557
+ printf ("\n");
558
+ }
559
+ } else
560
+ {
561
+ for (i=0; i<num_chunks; i++)
562
+ {
563
+ crc = crc32s (pngChunks[i].data, pngChunks[i].length+4);
564
+ if (pngChunks[i].crc32 != crc)
565
+ {
566
+ if (!didShowName)
567
+ {
568
+ didShowName = 1;
569
+ printf ("%s :\n", filename);
570
+ }
571
+ printf (" chunk : %c%c%c%c length %6u CRC32 %08X", (pngChunks[i].id >> 24) & 0xff,(pngChunks[i].id >> 16) & 0xff, (pngChunks[i].id >> 8) & 0xff,pngChunks[i].id & 0xff, pngChunks[i].length, pngChunks[i].crc32);
572
+ printf (" -> invalid, changed to %08X\n", crc);
573
+ pngChunks[i].crc32 = crc;
574
+ }
575
+ }
576
+ }
577
+
578
+ if (pngChunks[0].id == 0x43674249) /* "CgBI" */
579
+ {
580
+ if (num_chunks > 0 && pngChunks[1].id == 0x49484452) /* "IHDR" */
581
+ ihdr_chunk = &pngChunks[1];
582
+ } else
583
+ {
584
+ if (pngChunks[0].id == 0x49484452) /* "IHDR" */
585
+ ihdr_chunk = &pngChunks[0];
586
+ }
587
+
588
+ if (ihdr_chunk == NULL)
589
+ {
590
+ if (didShowName)
591
+ printf (" ");
592
+ else
593
+ {
594
+ didShowName = 1;
595
+ printf ("%s : ", filename);
596
+ }
597
+ printf ("no IHDR chunk found\n");
598
+ reset_chunks ();
599
+ return 0;
600
+ }
601
+ if (ihdr_chunk->length != 13)
602
+ {
603
+ if (didShowName)
604
+ printf (" ");
605
+ else
606
+ {
607
+ didShowName = 1;
608
+ printf ("%s : ", filename);
609
+ }
610
+ printf ("IHDR chunk length incorrect\n");
611
+ reset_chunks ();
612
+ return 0;
613
+ }
614
+ imgwidth = read_long (&ihdr_chunk->data[4]);
615
+ imgheight = read_long (&ihdr_chunk->data[8]);
616
+ bitdepth = ihdr_chunk->data[12];
617
+ colortype = ihdr_chunk->data[13];
618
+ compression = ihdr_chunk->data[14];
619
+ filter = ihdr_chunk->data[15];
620
+ interlace = ihdr_chunk->data[16];
621
+
622
+ if (imgwidth == 0 || imgheight == 0 || imgwidth > 2147483647 || imgheight > 2147483647)
623
+ {
624
+ if (didShowName)
625
+ printf (" ");
626
+ else
627
+ {
628
+ didShowName = 1;
629
+ printf ("%s : ", filename);
630
+ }
631
+ printf ("image dimensions invalid\n");
632
+ reset_chunks ();
633
+ return 0;
634
+ }
635
+ if (compression != 0)
636
+ {
637
+ if (didShowName)
638
+ printf (" ");
639
+ else
640
+ {
641
+ didShowName = 1;
642
+ printf ("%s : ", filename);
643
+ }
644
+ printf ("unknown compression type %d\n", compression);
645
+ reset_chunks ();
646
+ return 0;
647
+ }
648
+ if (filter != 0)
649
+ {
650
+ if (didShowName)
651
+ printf (" ");
652
+ else
653
+ {
654
+ didShowName = 1;
655
+ printf ("%s : ", filename);
656
+ }
657
+ printf ("unknown filter type %d\n", filter);
658
+ reset_chunks ();
659
+ return 0;
660
+ }
661
+ if (interlace != 0 && interlace != 1)
662
+ {
663
+ if (didShowName)
664
+ printf (" ");
665
+ else
666
+ {
667
+ didShowName = 1;
668
+ printf ("%s : ", filename);
669
+ }
670
+ printf ("unknown interlace type %d\n", interlace);
671
+ reset_chunks ();
672
+ return 0;
673
+ }
674
+
675
+ /*** From PNG Specs, http://www.w3.org/TR/PNG-Chunks.html
676
+ Color Allowed Interpretation
677
+ Type Bit Depths
678
+ ------ ---------- ----------------------------------
679
+ 0 1,2,4,8,16 Each pixel is a grayscale sample.
680
+
681
+ 2 8,16 Each pixel is an R,G,B triple.
682
+
683
+ 3 1,2,4,8 Each pixel is a palette index;
684
+ a PLTE chunk must appear.
685
+
686
+ 4 8,16 Each pixel is a grayscale sample,
687
+ followed by an alpha sample.
688
+
689
+ 6 8,16 Each pixel is an R,G,B triple,
690
+ followed by an alpha sample.
691
+ ***/
692
+
693
+ i = 0;
694
+
695
+ switch (colortype)
696
+ {
697
+ case 0:
698
+ if (bitdepth == 1 ||
699
+ bitdepth == 2 ||
700
+ bitdepth == 4 ||
701
+ bitdepth == 8 ||
702
+ bitdepth == 16)
703
+ i = 1;
704
+ bitspp = bitdepth;
705
+ break;
706
+ case 2:
707
+ if (bitdepth == 8 ||
708
+ bitdepth == 16)
709
+ i = 1;
710
+ bitspp = 3*bitdepth;
711
+ break;
712
+ case 3:
713
+ if (bitdepth == 1 ||
714
+ bitdepth == 2 ||
715
+ bitdepth == 4 ||
716
+ bitdepth == 8)
717
+ i = 1;
718
+ bitspp = bitdepth;
719
+ break;
720
+ case 4:
721
+ if (bitdepth == 8 ||
722
+ bitdepth == 16)
723
+ i = 1;
724
+ bitspp = 2*bitdepth;
725
+ break;
726
+ case 6:
727
+ if (bitdepth == 8 ||
728
+ bitdepth == 16)
729
+ i = 1;
730
+ bitspp = 4*bitdepth;
731
+ break;
732
+ default:
733
+ if (didShowName)
734
+ printf (" ");
735
+ else
736
+ {
737
+ didShowName = 1;
738
+ printf ("%s : ", filename);
739
+ }
740
+ printf ("unknown color type %d\n", colortype);
741
+ reset_chunks ();
742
+ return 0;
743
+ }
744
+ if (!i)
745
+ {
746
+ if (didShowName)
747
+ printf (" ");
748
+ else
749
+ {
750
+ didShowName = 1;
751
+ printf ("%s : ", filename);
752
+ }
753
+ printf ("invalid bit depth %d for color type %d\n", bitdepth, colortype);
754
+ reset_chunks ();
755
+ return 0;
756
+ }
757
+
758
+ bytespline = (imgwidth*bitspp+7)/8;
759
+ /* Warning!
760
+ This value is only valid for 8/16 bit images! */
761
+ bytespp = (bitspp+7)/8;
762
+
763
+ if (flag_Verbose)
764
+ {
765
+ if (!didShowName)
766
+ {
767
+ didShowName = 1;
768
+ printf ("%s :\n", filename);
769
+ }
770
+ printf (" image width : %u\n", imgwidth);
771
+ printf (" image height : %u\n", imgheight);
772
+ printf (" bit depth : %u\n", bitdepth);
773
+ printf (" color type : %u\n", colortype);
774
+ printf (" compression : %u\n", compression);
775
+ printf (" filter : %u\n", filter);
776
+ printf (" interlace : %u\n", interlace);
777
+ printf (" bits per pixel : %d\n", bitspp);
778
+ printf (" bytes per line : %d\n", bytespline);
779
+ }
780
+
781
+ row_filter_bytes = imgheight;
782
+ if (interlace == 1)
783
+ {
784
+ int w,h,pass;
785
+
786
+ if (flag_Verbose)
787
+ printf (" Adam7 interlacing:\n");
788
+
789
+ row_filter_bytes = 0;
790
+ for (pass=0; pass<7; pass++)
791
+ {
792
+ /* Formula taken from pngcheck ! */
793
+ w = (imgwidth - Starting_Col[pass] + Col_Increment[pass] - 1)/Col_Increment[pass];
794
+ h = (imgheight - Starting_Row[pass] + Row_Increment[pass] - 1)/Row_Increment[pass];
795
+ if (flag_Verbose)
796
+ printf (" pass %d: %d x %d\n", pass, w, h);
797
+ row_filter_bytes += h;
798
+ }
799
+ }
800
+ if (flag_Verbose)
801
+ {
802
+ printf (" row filter bytes : %u\n", row_filter_bytes);
803
+ printf (" expected data size : %u bytes\n", bytespline * imgheight + row_filter_bytes);
804
+ }
805
+
806
+ for (i=0; i<num_chunks; i++)
807
+ {
808
+ if (pngChunks[i].id == 0x49444154) /* "IDAT" */
809
+ {
810
+ idat_first_index = i;
811
+ break;
812
+ }
813
+ }
814
+ if (i == num_chunks)
815
+ {
816
+ if (didShowName)
817
+ printf (" ");
818
+ else
819
+ {
820
+ didShowName = 1;
821
+ printf ("%s : ", filename);
822
+ }
823
+ printf ("no IDAT chunks found\n");
824
+ reset_chunks ();
825
+ return 0;
826
+ }
827
+ /** Test for consecutive IDAT chunks */
828
+ /* continue where we left off */
829
+ while (i < num_chunks)
830
+ {
831
+ if (pngChunks[i].id != 0x49444154) /* "IDAT" */
832
+ break;
833
+ total_idat_size += pngChunks[i].length;
834
+ i++;
835
+ }
836
+ /* test the remaining chunks */
837
+ while (i < num_chunks)
838
+ {
839
+ if (pngChunks[i].id == 0x49444154) /* "IDAT" */
840
+ break;
841
+ i++;
842
+ }
843
+ if (i != num_chunks)
844
+ {
845
+ if (didShowName)
846
+ printf (" ");
847
+ else
848
+ {
849
+ didShowName = 1;
850
+ printf ("%s : ", filename);
851
+ }
852
+ printf ("IDAT chunks are not consecutive\n");
853
+ reset_chunks ();
854
+ return 0;
855
+ }
856
+
857
+ if (total_idat_size == 0)
858
+ {
859
+ if (didShowName)
860
+ printf (" ");
861
+ else
862
+ {
863
+ didShowName = 1;
864
+ printf ("%s : ", filename);
865
+ }
866
+ printf ("all IDAT chunks are empty\n");
867
+ reset_chunks ();
868
+ return 0;
869
+ }
870
+
871
+ /* Only need to re-write the image data for -phone 8 bit RGB and RGBA images */
872
+ /* Note To Self: Is that true? What about 16 bit images? What about palette images? */
873
+ /* Okay -- checked the above, it appears these two do NOT get fried. */
874
+
875
+ /* Swap BGR to RGB, BGRA to RGBA */
876
+ if (bitdepth == 8 &&
877
+ (colortype == 2 || /* Each pixel is an R,G,B triple (8 or 16 bits) */
878
+ colortype == 6)) /* Each pixel is an R,G,B triple, followed by an alpha sample (8 or 16 bits) */
879
+ {
880
+ if (isPhoney && flag_Verbose)
881
+ printf (" swapping BGR(A) to RGB(A)\n");
882
+
883
+ /*** Gather all IDATs into one ***/
884
+ if (flag_Debug)
885
+ printf (" informational : total idat size: %u\n", total_idat_size);
886
+ all_idat = (unsigned char *)malloc (total_idat_size);
887
+ if (all_idat == NULL)
888
+ {
889
+ if (didShowName)
890
+ printf (" ");
891
+ else
892
+ {
893
+ didShowName = 1;
894
+ printf ("%s : ", filename);
895
+ }
896
+ printf ("out of memory\n");
897
+ reset_chunks ();
898
+ return 0;
899
+ }
900
+ i = idat_first_index;
901
+ total_idat_size = 0;
902
+ while (i < num_chunks && pngChunks[i].id == 0x49444154) /* "IDAT" */
903
+ {
904
+ memcpy (all_idat+total_idat_size, pngChunks[i].data+4, pngChunks[i].length);
905
+ total_idat_size += pngChunks[i].length;
906
+ i++;
907
+ }
908
+
909
+ /*** So far everything appears to check out. Let's try uncompressing the IDAT chunks. ***/
910
+ data_out = (unsigned char *)malloc (bytespline * imgheight + row_filter_bytes);
911
+ if (data_out == NULL)
912
+ {
913
+ free (all_idat);
914
+ if (didShowName)
915
+ printf (" ");
916
+ else
917
+ {
918
+ didShowName = 1;
919
+ printf ("%s : ", filename);
920
+ }
921
+ printf ("out of memory\n");
922
+ reset_chunks ();
923
+ return 0;
924
+ }
925
+
926
+ if (isPhoney)
927
+ out_length = tinfl_decompress_mem_to_mem(data_out, bytespline * imgheight + row_filter_bytes, all_idat, total_idat_size, 0);
928
+ else
929
+ out_length = tinfl_decompress_mem_to_mem(data_out, bytespline * imgheight + row_filter_bytes, all_idat, total_idat_size, TINFL_FLAG_PARSE_ZLIB_HEADER);
930
+
931
+ free (all_idat);
932
+ all_idat = NULL;
933
+
934
+ if (out_length <= 0)
935
+ {
936
+ free (data_out);
937
+ if (didShowName)
938
+ printf (" ");
939
+ else
940
+ {
941
+ didShowName = 1;
942
+ printf ("%s : ", filename);
943
+ }
944
+ printf ("unspecified decompression error\n");
945
+ reset_chunks ();
946
+ return 0;
947
+ }
948
+
949
+ if (out_length != imgheight*bytespline + row_filter_bytes)
950
+ {
951
+ if (didShowName)
952
+ printf (" ");
953
+ else
954
+ {
955
+ didShowName = 1;
956
+ printf ("%s : ", filename);
957
+ }
958
+ printf ("decompression error, expected %u but got %u bytes\n", imgheight*bytespline + row_filter_bytes, out_length);
959
+ free (data_out);
960
+ reset_chunks ();
961
+ return 0;
962
+ }
963
+ if (flag_Verbose)
964
+ printf (" uncompressed size : %u bytes\n", bytespline * imgheight + row_filter_bytes);
965
+
966
+ if (isPhoney || flag_Process_Anyway)
967
+ {
968
+ if (interlace == 1) /* needs Adam7 unpacking! */
969
+ {
970
+ int x,y, b, row;
971
+ int pass, w,h;
972
+ int startat;
973
+
974
+ /* check if all row filters are okay */
975
+ y = 0;
976
+ for (pass=0; pass<7; pass++)
977
+ {
978
+ w = (imgwidth - Starting_Col[pass] + Col_Increment[pass] - 1)/Col_Increment[pass];
979
+ h = (imgheight - Starting_Row[pass] + Row_Increment[pass] - 1)/Row_Increment[pass];
980
+ row=0;
981
+ while (row < h)
982
+ {
983
+ if (data_out[y] > 4)
984
+ {
985
+ free (data_out);
986
+ if (didShowName)
987
+ printf (" ");
988
+ else
989
+ {
990
+ didShowName = 1;
991
+ printf ("%s : ", filename);
992
+ }
993
+ printf ("unknown row filter type (%d)\n", data_out[y]);
994
+ reset_chunks ();
995
+ return 0;
996
+ }
997
+ /* skip row filter byte */
998
+ y++;
999
+ /* skip rest of row */
1000
+ y += w * bytespp;
1001
+ row++;
1002
+ }
1003
+ }
1004
+
1005
+
1006
+ y = 0;
1007
+ for (pass=0; pass<7; pass++)
1008
+ {
1009
+ /* Formula taken from pngcheck ! */
1010
+ w = (imgwidth - Starting_Col[pass] + Col_Increment[pass] - 1)/Col_Increment[pass];
1011
+ h = (imgheight - Starting_Row[pass] + Row_Increment[pass] - 1)/Row_Increment[pass];
1012
+ startat = y;
1013
+ row=0;
1014
+ while (row < h)
1015
+ {
1016
+ /* skip row filter byte */
1017
+ y++;
1018
+ /* swap all bytes in this row */
1019
+ x = 0;
1020
+ while (x < w)
1021
+ {
1022
+ b = data_out[y+2];
1023
+ data_out[y+2] = data_out[y];
1024
+ data_out[y] = b;
1025
+ y += bytespp;
1026
+ x++;
1027
+ }
1028
+ row++;
1029
+ }
1030
+ if (isPhoney && flag_UpdateAlpha && colortype == 6) // RGBA
1031
+ {
1032
+ removeRowFilters (w, h, data_out+startat);
1033
+ demultiplyAlpha (w, h, data_out+startat);
1034
+ applyRowFilters (w, h, data_out+startat);
1035
+ }
1036
+ }
1037
+ } else
1038
+ {
1039
+ int x,y, b;
1040
+
1041
+ /* check row filters */
1042
+ y = 0;
1043
+ while (y < bytespline * imgheight + row_filter_bytes)
1044
+ {
1045
+ if (data_out[y] > 4)
1046
+ {
1047
+ free (data_out);
1048
+ if (didShowName)
1049
+ printf (" ");
1050
+ else
1051
+ {
1052
+ didShowName = 1;
1053
+ printf ("%s : ", filename);
1054
+ }
1055
+ printf ("unknown row filter type (%d)\n", data_out[y]);
1056
+ reset_chunks ();
1057
+ return 0;
1058
+ }
1059
+ /* skip row filter byte */
1060
+ y++;
1061
+ /* skip entire row */
1062
+ y += bytespline;
1063
+ }
1064
+
1065
+ y = 0;
1066
+ while (y < bytespline * imgheight + row_filter_bytes)
1067
+ {
1068
+ /* skip row filter byte */
1069
+ y++;
1070
+ /* swap all bytes in this row */
1071
+ x = 0;
1072
+ while (x < imgwidth)
1073
+ {
1074
+ b = data_out[y+2];
1075
+ data_out[y+2] = data_out[y];
1076
+ data_out[y] = b;
1077
+ y += bytespp;
1078
+ x++;
1079
+ }
1080
+ }
1081
+ if (isPhoney && flag_UpdateAlpha && colortype == 6) // RGBA
1082
+ {
1083
+ removeRowFilters (imgwidth, imgheight, data_out);
1084
+ demultiplyAlpha (imgwidth, imgheight, data_out);
1085
+ applyRowFilters (imgwidth, imgheight, data_out);
1086
+ }
1087
+ }
1088
+ }
1089
+
1090
+ /* Force VERY conservative repacking size ... */
1091
+ repack_size = 2*(bytespline * imgheight + row_filter_bytes);
1092
+ data_repack = (unsigned char *)malloc (repack_size);
1093
+ if (data_repack == NULL)
1094
+ {
1095
+ free (data_out);
1096
+ if (didShowName)
1097
+ printf (" ");
1098
+ else
1099
+ {
1100
+ didShowName = 1;
1101
+ printf ("%s : ", filename);
1102
+ }
1103
+ printf ("out of memory\n");
1104
+ reset_chunks ();
1105
+ return 0;
1106
+ }
1107
+
1108
+ /* ouch -- reserve 4 bytes at the start to put "IDAT" in! */
1109
+ /* yeah well, it beats having to re-allocate each block on writing ... */
1110
+ repack_length = tdefl_compress_mem_to_mem(data_repack+4, repack_size-4, data_out, out_length, TDEFL_WRITE_ZLIB_HEADER);
1111
+ if (repack_length == 0)
1112
+ {
1113
+ free (data_out);
1114
+ free (data_repack);
1115
+ if (didShowName)
1116
+ printf (" ");
1117
+ else
1118
+ {
1119
+ didShowName = 1;
1120
+ printf ("%s : ", filename);
1121
+ }
1122
+ printf ("unspecified compression error\n");
1123
+ reset_chunks ();
1124
+ return 0;
1125
+ }
1126
+
1127
+ if (flag_Verbose)
1128
+ printf (" repacked size: %u bytes\n", repack_length);
1129
+
1130
+ free (data_out);
1131
+ }
1132
+
1133
+ if (1)
1134
+ {
1135
+ if (!didShowName)
1136
+ {
1137
+ printf ("%s : ", filename);
1138
+ }
1139
+ printf ("writing to file %s\n", write_file_name);
1140
+
1141
+ write_file = fopen (write_file_name, "wb");
1142
+ if (!write_file)
1143
+ {
1144
+ printf (" failed to create output file!\n");
1145
+ reset_chunks ();
1146
+ return 0;
1147
+ }
1148
+
1149
+ fwrite (png_magic_bytes, 1, 8, write_file);
1150
+
1151
+ i = 0;
1152
+ /* need to skip first bogus chunk */
1153
+ /* at this point, I expect the first one to be IHDR! */
1154
+ if (pngChunks[0].id == 0x43674249) /* "CgBI" */
1155
+ i++;
1156
+ while (i < num_chunks && pngChunks[i].id != 0x49444154) /* "IDAT" */
1157
+ {
1158
+ fputc ( (pngChunks[i].length >> 24) & 0xff, write_file);
1159
+ fputc ( (pngChunks[i].length >> 16) & 0xff, write_file);
1160
+ fputc ( (pngChunks[i].length >> 8) & 0xff, write_file);
1161
+ fputc ( (pngChunks[i].length ) & 0xff, write_file);
1162
+ fwrite (pngChunks[i].data, pngChunks[i].length+4, 1, write_file);
1163
+ fputc ( (pngChunks[i].crc32 >> 24) & 0xff, write_file);
1164
+ fputc ( (pngChunks[i].crc32 >> 16) & 0xff, write_file);
1165
+ fputc ( (pngChunks[i].crc32 >> 8) & 0xff, write_file);
1166
+ fputc ( (pngChunks[i].crc32 ) & 0xff, write_file);
1167
+ i++;
1168
+ }
1169
+
1170
+ /* Did we repack the data, or do we just need to rewrite the file? */
1171
+ if (data_repack)
1172
+ {
1173
+ write_block_size = 0;
1174
+ while (write_block_size < repack_length)
1175
+ {
1176
+ data_repack[4+write_block_size-4] = 'I';
1177
+ data_repack[4+write_block_size-3] = 'D';
1178
+ data_repack[4+write_block_size-2] = 'A';
1179
+ data_repack[4+write_block_size-1] = 'T';
1180
+ if (repack_length-write_block_size > repack_IDAT_size)
1181
+ {
1182
+ fputc ( (repack_IDAT_size >> 24) & 0xff, write_file);
1183
+ fputc ( (repack_IDAT_size >> 16) & 0xff, write_file);
1184
+ fputc ( (repack_IDAT_size >> 8) & 0xff, write_file);
1185
+ fputc ( (repack_IDAT_size ) & 0xff, write_file);
1186
+ fwrite ( data_repack+write_block_size, repack_IDAT_size+4,1, write_file);
1187
+ crc = crc32s (data_repack+write_block_size, repack_IDAT_size+4);
1188
+ fputc ( (crc >> 24) & 0xff, write_file);
1189
+ fputc ( (crc >> 16) & 0xff, write_file);
1190
+ fputc ( (crc >> 8) & 0xff, write_file);
1191
+ fputc ( (crc ) & 0xff, write_file);
1192
+ write_block_size += repack_IDAT_size;
1193
+ } else
1194
+ {
1195
+ fputc ( ((repack_length-write_block_size) >> 24) & 0xff, write_file);
1196
+ fputc ( ((repack_length-write_block_size) >> 16) & 0xff, write_file);
1197
+ fputc ( ((repack_length-write_block_size) >> 8) & 0xff, write_file);
1198
+ fputc ( ((repack_length-write_block_size) ) & 0xff, write_file);
1199
+ fwrite ( data_repack+write_block_size, (repack_length-write_block_size)+4,1, write_file);
1200
+ crc = crc32s (data_repack+write_block_size, (repack_length-write_block_size)+4);
1201
+ fputc ( (crc >> 24) & 0xff, write_file);
1202
+ fputc ( (crc >> 16) & 0xff, write_file);
1203
+ fputc ( (crc >> 8) & 0xff, write_file);
1204
+ fputc ( (crc ) & 0xff, write_file);
1205
+ write_block_size = repack_length;
1206
+ }
1207
+ }
1208
+
1209
+ /* skip original IDAT chunks */
1210
+ while (i < num_chunks && pngChunks[i].id == 0x49444154) /* "IDAT" */
1211
+ i++;
1212
+
1213
+ free (data_repack);
1214
+ } else
1215
+ {
1216
+ /* image was not repacked */
1217
+ /* output original IDAT chunks */
1218
+ while (i < num_chunks && pngChunks[i].id == 0x49444154) /* "IDAT" */
1219
+ {
1220
+ fputc ( (pngChunks[i].length >> 24) & 0xff, write_file);
1221
+ fputc ( (pngChunks[i].length >> 16) & 0xff, write_file);
1222
+ fputc ( (pngChunks[i].length >> 8) & 0xff, write_file);
1223
+ fputc ( (pngChunks[i].length ) & 0xff, write_file);
1224
+ fwrite (pngChunks[i].data, pngChunks[i].length+4, 1, write_file);
1225
+ fputc ( (pngChunks[i].crc32 >> 24) & 0xff, write_file);
1226
+ fputc ( (pngChunks[i].crc32 >> 16) & 0xff, write_file);
1227
+ fputc ( (pngChunks[i].crc32 >> 8) & 0xff, write_file);
1228
+ fputc ( (pngChunks[i].crc32 ) & 0xff, write_file);
1229
+ i++;
1230
+ }
1231
+ }
1232
+
1233
+ /* output remaining chunks */
1234
+ while (i < num_chunks)
1235
+ {
1236
+ fputc ( (pngChunks[i].length >> 24) & 0xff, write_file);
1237
+ fputc ( (pngChunks[i].length >> 16) & 0xff, write_file);
1238
+ fputc ( (pngChunks[i].length >> 8) & 0xff, write_file);
1239
+ fputc ( (pngChunks[i].length ) & 0xff, write_file);
1240
+ fwrite (pngChunks[i].data, pngChunks[i].length+4, 1, write_file);
1241
+ fputc ( (pngChunks[i].crc32 >> 24) & 0xff, write_file);
1242
+ fputc ( (pngChunks[i].crc32 >> 16) & 0xff, write_file);
1243
+ fputc ( (pngChunks[i].crc32 >> 8) & 0xff, write_file);
1244
+ fputc ( (pngChunks[i].crc32 ) & 0xff, write_file);
1245
+ i++;
1246
+ }
1247
+ fclose (write_file);
1248
+ free (write_file_name);
1249
+ reset_chunks ();
1250
+
1251
+ return 1;
1252
+ }
1253
+
1254
+ /* We come here if nothing was written */
1255
+ /* Just show the name and go away */
1256
+ if (!didShowName)
1257
+ {
1258
+ printf ("%s\n", filename);
1259
+ }
1260
+
1261
+ if (data_repack)
1262
+ free (data_repack);
1263
+
1264
+ reset_chunks ();
1265
+ return 0;
1266
+ }
1267
+
1268
+ // === Ruby ===
1269
+
1270
+ #include <ruby.h>
1271
+
1272
+ VALUE Pngdefry = Qnil;
1273
+ void Init_pngdefry();
1274
+ VALUE method_pngdefry_defry(VALUE self, VALUE input, VALUE output);
1275
+
1276
+ void Init_pngdefry() {
1277
+ Pngdefry = rb_define_module("Pngdefry");
1278
+ rb_define_singleton_method(Pngdefry, "defry", method_pngdefry_defry, 2);
1279
+ }
1280
+
1281
+ VALUE method_pngdefry_defry(VALUE self, VALUE input, VALUE output) {
1282
+ char *filename = StringValueCStr(input);
1283
+ char *outputFilename = StringValueCStr(output);
1284
+ int result = process(filename, outputFilename);
1285
+ return INT2FIX(result);
1286
+ }