Imported Upstream version 1.6.13
[platform/upstream/libpng.git] / contrib / examples / iccfrompng.c
1 /*- iccfrompng
2  *
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:
6  * United States.
7  *
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 preceeds the image data.
14  *
15  * Compile and link against libpng and zlib, plus anything else required on the
16  * system you use.
17  *
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.
21  */
22 #include <stdlib.h>
23 #include <setjmp.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #include <png.h>
28
29 static int verbose = 1;
30 static png_byte no_profile[] = "no profile";
31
32 static png_bytep
33 extract(FILE *fp, png_uint_32 *proflen)
34 {
35    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
36    png_infop info_ptr = NULL;
37    png_bytep result = NULL;
38
39    /* Initialize for error or no profile: */
40    *proflen = 0;
41
42    if (png_ptr == NULL)
43    {
44       fprintf(stderr, "iccfrompng: version library mismatch?\n");
45       return 0;
46    }
47
48    if (setjmp(png_jmpbuf(png_ptr)))
49    {
50       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
51       return 0;
52    }
53
54    png_init_io(png_ptr, fp);
55
56    info_ptr = png_create_info_struct(png_ptr);
57    if (info_ptr == NULL)
58       png_error(png_ptr, "OOM allocating info structure");
59
60    png_read_info(png_ptr, info_ptr);
61
62    {
63       png_charp name;
64       int compression_type;
65       png_bytep profile;
66
67       if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
68          proflen) & PNG_INFO_iCCP)
69       {
70          result = malloc(*proflen);
71          if (result != NULL)
72             memcpy(result, profile, *proflen);
73
74          else
75             png_error(png_ptr, "OOM allocating profile buffer");
76       }
77
78       else
79         result = no_profile;
80    }
81
82    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
83    return result;
84 }
85
86 static int
87 extract_one_file(const char *filename)
88 {
89    int result = 0;
90    FILE *fp = fopen(filename, "rb");
91
92    if (fp != NULL)
93    {
94       png_uint_32 proflen = 0;
95       png_bytep profile = extract(fp, &proflen);
96
97       if (profile != NULL && profile != no_profile)
98       {
99          size_t len;
100          char *output;
101
102          {
103             const char *ep = strrchr(filename, '.');
104
105             if (ep != NULL)
106                len = ep-filename;
107
108             else
109                len = strlen(filename);
110          }
111
112          output = malloc(len + 5);
113          if (output != NULL)
114          {
115             FILE *of;
116
117             memcpy(output, filename, len);
118             strcpy(output+len, ".icc");
119
120             of = fopen(output, "wb");
121             if (of != NULL)
122             {
123                if (fwrite(profile, proflen, 1, of) == 1 &&
124                   fflush(of) == 0 &&
125                   fclose(of) == 0)
126                {
127                   if (verbose)
128                      printf("%s -> %s\n", filename, output);
129                   /* Success return */
130                   result = 1;
131                }
132
133                else
134                {
135                   fprintf(stderr, "%s: error writing profile\n", output);
136                   if (remove(output))
137                      fprintf(stderr, "%s: could not remove file\n", output);
138                }
139             }
140
141             else
142                fprintf(stderr, "%s: failed to open output file\n", output);
143
144             free(output);
145          }
146
147          else
148             fprintf(stderr, "%s: OOM allocating string!\n", filename);
149
150          free(profile);
151       }
152
153       else if (verbose && profile == no_profile)
154         printf("%s has no profile\n", filename);
155    }
156
157    else
158       fprintf(stderr, "%s: could not open file\n", filename);
159
160    return result;
161 }
162
163 int
164 main(int argc, char **argv)
165 {
166    int i;
167    int extracted = 0;
168
169    for (i=1; i<argc; ++i)
170    {
171       if (strcmp(argv[i], "-q") == 0)
172          verbose = 0;
173
174       else if (extract_one_file(argv[i]))
175          extracted = 1;
176    }
177
178    /* Exit code is true if any extract succeeds */
179    return extracted == 0;
180 }