(root)/
libpng-1.6.40/
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 precedes 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  
      33  static int verbose = 1;
      34  static png_byte no_profile[] = "no profile";
      35  
      36  static png_bytep
      37  extract(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  
      90  static int
      91  extract_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  
     167  int
     168  main(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 */