123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /*- 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>
- 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;
- }
|