3 * COPYRIGHT: Written by John Cunningham Bowler, 2011.
4 * To the extent possible under law, the author has waived all copyright and
5 * related or neighboring rights to this work. This work is published from:
8 * Extract any icc profiles found in the given PNG files. This is a simple
9 * example of a program that extracts information from the header of a PNG file
10 * without processing the image. Notice that some header information may occur
11 * after the image data. Textual data and comments are an example; the approach
12 * in this file won't work reliably for such data because it only looks for the
13 * information in the section of the file that precedes the image data.
15 * Compile and link against libpng and zlib, plus anything else required on the
18 * To use supply a list of PNG files containing iCCP chunks, the chunks will be
19 * extracted to a similarly named file with the extension replaced by 'icc',
20 * which will be overwritten without warning.
29 #if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \
30 defined (PNG_iCCP_SUPPORTED)
33 static int verbose
= 1;
34 static png_byte no_profile
[] = "no profile";
37 extract(FILE *fp
, png_uint_32
*proflen
)
39 png_structp png_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
,0,0,0);
40 png_infop info_ptr
= NULL
;
41 png_bytep result
= NULL
;
43 /* Initialize for error or no profile: */
48 fprintf(stderr
, "iccfrompng: version library mismatch?\n");
52 if (setjmp(png_jmpbuf(png_ptr
)))
54 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
58 png_init_io(png_ptr
, fp
);
60 info_ptr
= png_create_info_struct(png_ptr
);
62 png_error(png_ptr
, "OOM allocating info structure");
64 png_read_info(png_ptr
, info_ptr
);
71 if (png_get_iCCP(png_ptr
, info_ptr
, &name
, &compression_type
, &profile
,
72 proflen
) & PNG_INFO_iCCP
)
74 result
= malloc(*proflen
);
76 memcpy(result
, profile
, *proflen
);
79 png_error(png_ptr
, "OOM allocating profile buffer");
86 png_destroy_read_struct(&png_ptr
, &info_ptr
, NULL
);
91 extract_one_file(const char *filename
)
94 FILE *fp
= fopen(filename
, "rb");
98 png_uint_32 proflen
= 0;
99 png_bytep profile
= extract(fp
, &proflen
);
101 if (profile
!= NULL
&& profile
!= no_profile
)
107 const char *ep
= strrchr(filename
, '.');
113 len
= strlen(filename
);
116 output
= malloc(len
+ 5);
121 memcpy(output
, filename
, len
);
122 strcpy(output
+len
, ".icc");
124 of
= fopen(output
, "wb");
127 if (fwrite(profile
, proflen
, 1, of
) == 1 &&
132 printf("%s -> %s\n", filename
, output
);
139 fprintf(stderr
, "%s: error writing profile\n", output
);
141 fprintf(stderr
, "%s: could not remove file\n", output
);
146 fprintf(stderr
, "%s: failed to open output file\n", output
);
152 fprintf(stderr
, "%s: OOM allocating string!\n", filename
);
157 else if (verbose
&& profile
== no_profile
)
158 printf("%s has no profile\n", filename
);
162 fprintf(stderr
, "%s: could not open file\n", filename
);
168 main(int argc
, char **argv
)
173 for (i
=1; i
<argc
; ++i
)
175 if (strcmp(argv
[i
], "-q") == 0)
178 else if (extract_one_file(argv
[i
]))
182 /* Exit code is true if any extract succeeds */
183 return extracted
== 0;
185 #endif /* READ && STDIO && iCCP */