xref: /aosp_15_r20/external/libpng/contrib/examples/iccfrompng.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
1*a67afe4dSAndroid Build Coastguard Worker /*- iccfrompng
2*a67afe4dSAndroid Build Coastguard Worker  *
3*a67afe4dSAndroid Build Coastguard Worker  * COPYRIGHT: Written by John Cunningham Bowler, 2011.
4*a67afe4dSAndroid Build Coastguard Worker  * To the extent possible under law, the author has waived all copyright and
5*a67afe4dSAndroid Build Coastguard Worker  * related or neighboring rights to this work.  This work is published from:
6*a67afe4dSAndroid Build Coastguard Worker  * United States.
7*a67afe4dSAndroid Build Coastguard Worker  *
8*a67afe4dSAndroid Build Coastguard Worker  * Extract any icc profiles found in the given PNG files.  This is a simple
9*a67afe4dSAndroid Build Coastguard Worker  * example of a program that extracts information from the header of a PNG file
10*a67afe4dSAndroid Build Coastguard Worker  * without processing the image.  Notice that some header information may occur
11*a67afe4dSAndroid Build Coastguard Worker  * after the image data. Textual data and comments are an example; the approach
12*a67afe4dSAndroid Build Coastguard Worker  * in this file won't work reliably for such data because it only looks for the
13*a67afe4dSAndroid Build Coastguard Worker  * information in the section of the file that precedes the image data.
14*a67afe4dSAndroid Build Coastguard Worker  *
15*a67afe4dSAndroid Build Coastguard Worker  * Compile and link against libpng and zlib, plus anything else required on the
16*a67afe4dSAndroid Build Coastguard Worker  * system you use.
17*a67afe4dSAndroid Build Coastguard Worker  *
18*a67afe4dSAndroid Build Coastguard Worker  * To use supply a list of PNG files containing iCCP chunks, the chunks will be
19*a67afe4dSAndroid Build Coastguard Worker  * extracted to a similarly named file with the extension replaced by 'icc',
20*a67afe4dSAndroid Build Coastguard Worker  * which will be overwritten without warning.
21*a67afe4dSAndroid Build Coastguard Worker  */
22*a67afe4dSAndroid Build Coastguard Worker #include <stdlib.h>
23*a67afe4dSAndroid Build Coastguard Worker #include <setjmp.h>
24*a67afe4dSAndroid Build Coastguard Worker #include <string.h>
25*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
26*a67afe4dSAndroid Build Coastguard Worker 
27*a67afe4dSAndroid Build Coastguard Worker #include <png.h>
28*a67afe4dSAndroid Build Coastguard Worker 
29*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \
30*a67afe4dSAndroid Build Coastguard Worker     defined (PNG_iCCP_SUPPORTED)
31*a67afe4dSAndroid Build Coastguard Worker 
32*a67afe4dSAndroid Build Coastguard Worker 
33*a67afe4dSAndroid Build Coastguard Worker static int verbose = 1;
34*a67afe4dSAndroid Build Coastguard Worker static png_byte no_profile[] = "no profile";
35*a67afe4dSAndroid Build Coastguard Worker 
36*a67afe4dSAndroid Build Coastguard Worker static png_bytep
extract(FILE * fp,png_uint_32 * proflen)37*a67afe4dSAndroid Build Coastguard Worker extract(FILE *fp, png_uint_32 *proflen)
38*a67afe4dSAndroid Build Coastguard Worker {
39*a67afe4dSAndroid Build Coastguard Worker    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
40*a67afe4dSAndroid Build Coastguard Worker    png_infop info_ptr = NULL;
41*a67afe4dSAndroid Build Coastguard Worker    png_bytep result = NULL;
42*a67afe4dSAndroid Build Coastguard Worker 
43*a67afe4dSAndroid Build Coastguard Worker    /* Initialize for error or no profile: */
44*a67afe4dSAndroid Build Coastguard Worker    *proflen = 0;
45*a67afe4dSAndroid Build Coastguard Worker 
46*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
47*a67afe4dSAndroid Build Coastguard Worker    {
48*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, "iccfrompng: version library mismatch?\n");
49*a67afe4dSAndroid Build Coastguard Worker       return 0;
50*a67afe4dSAndroid Build Coastguard Worker    }
51*a67afe4dSAndroid Build Coastguard Worker 
52*a67afe4dSAndroid Build Coastguard Worker    if (setjmp(png_jmpbuf(png_ptr)))
53*a67afe4dSAndroid Build Coastguard Worker    {
54*a67afe4dSAndroid Build Coastguard Worker       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
55*a67afe4dSAndroid Build Coastguard Worker       return 0;
56*a67afe4dSAndroid Build Coastguard Worker    }
57*a67afe4dSAndroid Build Coastguard Worker 
58*a67afe4dSAndroid Build Coastguard Worker    png_init_io(png_ptr, fp);
59*a67afe4dSAndroid Build Coastguard Worker 
60*a67afe4dSAndroid Build Coastguard Worker    info_ptr = png_create_info_struct(png_ptr);
61*a67afe4dSAndroid Build Coastguard Worker    if (info_ptr == NULL)
62*a67afe4dSAndroid Build Coastguard Worker       png_error(png_ptr, "OOM allocating info structure");
63*a67afe4dSAndroid Build Coastguard Worker 
64*a67afe4dSAndroid Build Coastguard Worker    png_read_info(png_ptr, info_ptr);
65*a67afe4dSAndroid Build Coastguard Worker 
66*a67afe4dSAndroid Build Coastguard Worker    {
67*a67afe4dSAndroid Build Coastguard Worker       png_charp name;
68*a67afe4dSAndroid Build Coastguard Worker       int compression_type;
69*a67afe4dSAndroid Build Coastguard Worker       png_bytep profile;
70*a67afe4dSAndroid Build Coastguard Worker 
71*a67afe4dSAndroid Build Coastguard Worker       if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
72*a67afe4dSAndroid Build Coastguard Worker          proflen) & PNG_INFO_iCCP)
73*a67afe4dSAndroid Build Coastguard Worker       {
74*a67afe4dSAndroid Build Coastguard Worker          result = malloc(*proflen);
75*a67afe4dSAndroid Build Coastguard Worker          if (result != NULL)
76*a67afe4dSAndroid Build Coastguard Worker             memcpy(result, profile, *proflen);
77*a67afe4dSAndroid Build Coastguard Worker 
78*a67afe4dSAndroid Build Coastguard Worker          else
79*a67afe4dSAndroid Build Coastguard Worker             png_error(png_ptr, "OOM allocating profile buffer");
80*a67afe4dSAndroid Build Coastguard Worker       }
81*a67afe4dSAndroid Build Coastguard Worker 
82*a67afe4dSAndroid Build Coastguard Worker       else
83*a67afe4dSAndroid Build Coastguard Worker          result = no_profile;
84*a67afe4dSAndroid Build Coastguard Worker    }
85*a67afe4dSAndroid Build Coastguard Worker 
86*a67afe4dSAndroid Build Coastguard Worker    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
87*a67afe4dSAndroid Build Coastguard Worker    return result;
88*a67afe4dSAndroid Build Coastguard Worker }
89*a67afe4dSAndroid Build Coastguard Worker 
90*a67afe4dSAndroid Build Coastguard Worker static int
extract_one_file(const char * filename)91*a67afe4dSAndroid Build Coastguard Worker extract_one_file(const char *filename)
92*a67afe4dSAndroid Build Coastguard Worker {
93*a67afe4dSAndroid Build Coastguard Worker    int result = 0;
94*a67afe4dSAndroid Build Coastguard Worker    FILE *fp = fopen(filename, "rb");
95*a67afe4dSAndroid Build Coastguard Worker 
96*a67afe4dSAndroid Build Coastguard Worker    if (fp != NULL)
97*a67afe4dSAndroid Build Coastguard Worker    {
98*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 proflen = 0;
99*a67afe4dSAndroid Build Coastguard Worker       png_bytep profile = extract(fp, &proflen);
100*a67afe4dSAndroid Build Coastguard Worker 
101*a67afe4dSAndroid Build Coastguard Worker       if (profile != NULL && profile != no_profile)
102*a67afe4dSAndroid Build Coastguard Worker       {
103*a67afe4dSAndroid Build Coastguard Worker          size_t len;
104*a67afe4dSAndroid Build Coastguard Worker          char *output;
105*a67afe4dSAndroid Build Coastguard Worker 
106*a67afe4dSAndroid Build Coastguard Worker          {
107*a67afe4dSAndroid Build Coastguard Worker             const char *ep = strrchr(filename, '.');
108*a67afe4dSAndroid Build Coastguard Worker 
109*a67afe4dSAndroid Build Coastguard Worker             if (ep != NULL)
110*a67afe4dSAndroid Build Coastguard Worker                len = ep-filename;
111*a67afe4dSAndroid Build Coastguard Worker 
112*a67afe4dSAndroid Build Coastguard Worker             else
113*a67afe4dSAndroid Build Coastguard Worker                len = strlen(filename);
114*a67afe4dSAndroid Build Coastguard Worker          }
115*a67afe4dSAndroid Build Coastguard Worker 
116*a67afe4dSAndroid Build Coastguard Worker          output = malloc(len + 5);
117*a67afe4dSAndroid Build Coastguard Worker          if (output != NULL)
118*a67afe4dSAndroid Build Coastguard Worker          {
119*a67afe4dSAndroid Build Coastguard Worker             FILE *of;
120*a67afe4dSAndroid Build Coastguard Worker 
121*a67afe4dSAndroid Build Coastguard Worker             memcpy(output, filename, len);
122*a67afe4dSAndroid Build Coastguard Worker             strcpy(output+len, ".icc");
123*a67afe4dSAndroid Build Coastguard Worker 
124*a67afe4dSAndroid Build Coastguard Worker             of = fopen(output, "wb");
125*a67afe4dSAndroid Build Coastguard Worker             if (of != NULL)
126*a67afe4dSAndroid Build Coastguard Worker             {
127*a67afe4dSAndroid Build Coastguard Worker                if (fwrite(profile, proflen, 1, of) == 1 &&
128*a67afe4dSAndroid Build Coastguard Worker                   fflush(of) == 0 &&
129*a67afe4dSAndroid Build Coastguard Worker                   fclose(of) == 0)
130*a67afe4dSAndroid Build Coastguard Worker                {
131*a67afe4dSAndroid Build Coastguard Worker                   if (verbose)
132*a67afe4dSAndroid Build Coastguard Worker                      printf("%s -> %s\n", filename, output);
133*a67afe4dSAndroid Build Coastguard Worker                   /* Success return */
134*a67afe4dSAndroid Build Coastguard Worker                   result = 1;
135*a67afe4dSAndroid Build Coastguard Worker                }
136*a67afe4dSAndroid Build Coastguard Worker 
137*a67afe4dSAndroid Build Coastguard Worker                else
138*a67afe4dSAndroid Build Coastguard Worker                {
139*a67afe4dSAndroid Build Coastguard Worker                   fprintf(stderr, "%s: error writing profile\n", output);
140*a67afe4dSAndroid Build Coastguard Worker                   if (remove(output))
141*a67afe4dSAndroid Build Coastguard Worker                      fprintf(stderr, "%s: could not remove file\n", output);
142*a67afe4dSAndroid Build Coastguard Worker                }
143*a67afe4dSAndroid Build Coastguard Worker             }
144*a67afe4dSAndroid Build Coastguard Worker 
145*a67afe4dSAndroid Build Coastguard Worker             else
146*a67afe4dSAndroid Build Coastguard Worker                fprintf(stderr, "%s: failed to open output file\n", output);
147*a67afe4dSAndroid Build Coastguard Worker 
148*a67afe4dSAndroid Build Coastguard Worker             free(output);
149*a67afe4dSAndroid Build Coastguard Worker          }
150*a67afe4dSAndroid Build Coastguard Worker 
151*a67afe4dSAndroid Build Coastguard Worker          else
152*a67afe4dSAndroid Build Coastguard Worker             fprintf(stderr, "%s: OOM allocating string!\n", filename);
153*a67afe4dSAndroid Build Coastguard Worker 
154*a67afe4dSAndroid Build Coastguard Worker          free(profile);
155*a67afe4dSAndroid Build Coastguard Worker       }
156*a67afe4dSAndroid Build Coastguard Worker 
157*a67afe4dSAndroid Build Coastguard Worker       else if (verbose && profile == no_profile)
158*a67afe4dSAndroid Build Coastguard Worker          printf("%s has no profile\n", filename);
159*a67afe4dSAndroid Build Coastguard Worker    }
160*a67afe4dSAndroid Build Coastguard Worker 
161*a67afe4dSAndroid Build Coastguard Worker    else
162*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, "%s: could not open file\n", filename);
163*a67afe4dSAndroid Build Coastguard Worker 
164*a67afe4dSAndroid Build Coastguard Worker    return result;
165*a67afe4dSAndroid Build Coastguard Worker }
166*a67afe4dSAndroid Build Coastguard Worker 
167*a67afe4dSAndroid Build Coastguard Worker int
main(int argc,char ** argv)168*a67afe4dSAndroid Build Coastguard Worker main(int argc, char **argv)
169*a67afe4dSAndroid Build Coastguard Worker {
170*a67afe4dSAndroid Build Coastguard Worker    int i;
171*a67afe4dSAndroid Build Coastguard Worker    int extracted = 0;
172*a67afe4dSAndroid Build Coastguard Worker 
173*a67afe4dSAndroid Build Coastguard Worker    for (i=1; i<argc; ++i)
174*a67afe4dSAndroid Build Coastguard Worker    {
175*a67afe4dSAndroid Build Coastguard Worker       if (strcmp(argv[i], "-q") == 0)
176*a67afe4dSAndroid Build Coastguard Worker          verbose = 0;
177*a67afe4dSAndroid Build Coastguard Worker 
178*a67afe4dSAndroid Build Coastguard Worker       else if (extract_one_file(argv[i]))
179*a67afe4dSAndroid Build Coastguard Worker          extracted = 1;
180*a67afe4dSAndroid Build Coastguard Worker    }
181*a67afe4dSAndroid Build Coastguard Worker 
182*a67afe4dSAndroid Build Coastguard Worker    /* Exit code is true if any extract succeeds */
183*a67afe4dSAndroid Build Coastguard Worker    return extracted == 0;
184*a67afe4dSAndroid Build Coastguard Worker }
185*a67afe4dSAndroid Build Coastguard Worker #endif /* READ && STDIO && iCCP */
186