all repos — mgba @ 9de8f084ba55460b02d300c1dd8b8e6c56f691d5

mGBA Game Boy Advance Emulator

src/third-party/libpng/contrib/examples/iccfrompng.c (view raw)

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