mirror of
				https://git.code.sf.net/p/libpng/code.git
				synced 2025-07-10 18:04:09 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			186 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*- iccfrompng
 | |
|  *
 | |
|  * COPYRIGHT: Written by John Cunningham Bowler, 2011.
 | |
|  * To the extent possible under law, the author has waived all copyright and
 | |
|  * related or neighboring rights to this work.  This work is published from:
 | |
|  * United States.
 | |
|  *
 | |
|  * Extract any icc profiles found in the given PNG files.  This is a simple
 | |
|  * example of a program that extracts information from the header of a PNG file
 | |
|  * without processing the image.  Notice that some header information may occur
 | |
|  * after the image data. Textual data and comments are an example; the approach
 | |
|  * in this file won't work reliably for such data because it only looks for the
 | |
|  * information in the section of the file that preceeds the image data.
 | |
|  *
 | |
|  * Compile and link against libpng and zlib, plus anything else required on the
 | |
|  * system you use.
 | |
|  *
 | |
|  * To use supply a list of PNG files containing iCCP chunks, the chunks will be
 | |
|  * extracted to a similarly named file with the extension replaced by 'icc',
 | |
|  * which will be overwritten without warning.
 | |
|  */
 | |
| #include <stdlib.h>
 | |
| #include <setjmp.h>
 | |
| #include <string.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include <png.h>
 | |
| 
 | |
| #if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \
 | |
|     defined (PNG_iCCP_SUPPORTED)
 | |
| 
 | |
| 
 | |
| static int verbose = 1;
 | |
| static png_byte no_profile[] = "no profile";
 | |
| 
 | |
| static png_bytep
 | |
| extract(FILE *fp, png_uint_32 *proflen)
 | |
| {
 | |
|    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
 | |
|    png_infop info_ptr = NULL;
 | |
|    png_bytep result = NULL;
 | |
| 
 | |
|    /* Initialize for error or no profile: */
 | |
|    *proflen = 0;
 | |
| 
 | |
|    if (png_ptr == NULL)
 | |
|    {
 | |
|       fprintf(stderr, "iccfrompng: version library mismatch?\n");
 | |
|       return 0;
 | |
|    }
 | |
| 
 | |
|    if (setjmp(png_jmpbuf(png_ptr)))
 | |
|    {
 | |
|       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 | |
|       return 0;
 | |
|    }
 | |
| 
 | |
|    png_init_io(png_ptr, fp);
 | |
| 
 | |
|    info_ptr = png_create_info_struct(png_ptr);
 | |
|    if (info_ptr == NULL)
 | |
|       png_error(png_ptr, "OOM allocating info structure");
 | |
| 
 | |
|    png_read_info(png_ptr, info_ptr);
 | |
| 
 | |
|    {
 | |
|       png_charp name;
 | |
|       int compression_type;
 | |
|       png_bytep profile;
 | |
| 
 | |
|       if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile,
 | |
|          proflen) & PNG_INFO_iCCP)
 | |
|       {
 | |
|          result = malloc(*proflen);
 | |
|          if (result != NULL)
 | |
|             memcpy(result, profile, *proflen);
 | |
| 
 | |
|          else
 | |
|             png_error(png_ptr, "OOM allocating profile buffer");
 | |
|       }
 | |
| 
 | |
|       else
 | |
| 	result = no_profile;
 | |
|    }
 | |
| 
 | |
|    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
 | |
|    return result;
 | |
| }
 | |
| 
 | |
| static int
 | |
| extract_one_file(const char *filename)
 | |
| {
 | |
|    int result = 0;
 | |
|    FILE *fp = fopen(filename, "rb");
 | |
| 
 | |
|    if (fp != NULL)
 | |
|    {
 | |
|       png_uint_32 proflen = 0;
 | |
|       png_bytep profile = extract(fp, &proflen);
 | |
| 
 | |
|       if (profile != NULL && profile != no_profile)
 | |
|       {
 | |
|          size_t len;
 | |
|          char *output;
 | |
| 
 | |
|          {
 | |
|             const char *ep = strrchr(filename, '.');
 | |
| 
 | |
|             if (ep != NULL)
 | |
|                len = ep-filename;
 | |
| 
 | |
|             else
 | |
|                len = strlen(filename);
 | |
|          }
 | |
| 
 | |
|          output = malloc(len + 5);
 | |
|          if (output != NULL)
 | |
|          {
 | |
|             FILE *of;
 | |
| 
 | |
|             memcpy(output, filename, len);
 | |
|             strcpy(output+len, ".icc");
 | |
| 
 | |
|             of = fopen(output, "wb");
 | |
|             if (of != NULL)
 | |
|             {
 | |
|                if (fwrite(profile, proflen, 1, of) == 1 &&
 | |
|                   fflush(of) == 0 &&
 | |
|                   fclose(of) == 0)
 | |
|                {
 | |
|                   if (verbose)
 | |
|                      printf("%s -> %s\n", filename, output);
 | |
|                   /* Success return */
 | |
|                   result = 1;
 | |
|                }
 | |
| 
 | |
|                else
 | |
|                {
 | |
|                   fprintf(stderr, "%s: error writing profile\n", output);
 | |
|                   if (remove(output))
 | |
|                      fprintf(stderr, "%s: could not remove file\n", output);
 | |
|                }
 | |
|             }
 | |
| 
 | |
|             else
 | |
|                fprintf(stderr, "%s: failed to open output file\n", output);
 | |
| 
 | |
|             free(output);
 | |
|          }
 | |
| 
 | |
|          else
 | |
|             fprintf(stderr, "%s: OOM allocating string!\n", filename);
 | |
| 
 | |
|          free(profile);
 | |
|       }
 | |
| 
 | |
|       else if (verbose && profile == no_profile)
 | |
| 	printf("%s has no profile\n", filename);
 | |
|    }
 | |
| 
 | |
|    else
 | |
|       fprintf(stderr, "%s: could not open file\n", filename);
 | |
| 
 | |
|    return result;
 | |
| }
 | |
| 
 | |
| int
 | |
| main(int argc, char **argv)
 | |
| {
 | |
|    int i;
 | |
|    int extracted = 0;
 | |
| 
 | |
|    for (i=1; i<argc; ++i)
 | |
|    {
 | |
|       if (strcmp(argv[i], "-q") == 0)
 | |
|          verbose = 0;
 | |
| 
 | |
|       else if (extract_one_file(argv[i]))
 | |
|          extracted = 1;
 | |
|    }
 | |
| 
 | |
|    /* Exit code is true if any extract succeeds */
 | |
|    return extracted == 0;
 | |
| }
 | |
| #endif /* READ && STDIO && iCCP */
 | 
