"Fossies" - the Fresh Open Source Software Archive

Member "littleutils-1.2.5/imageutils/pngstrip.c" (29 Oct 2021, 11521 Bytes) of package /linux/privat/littleutils-1.2.5.tar.lz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "pngstrip.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.2.4_vs_1.2.5.

    1 /* pngstrip:  Rewrite a PNG file with all extraneous information removed
    2 
    3    A quick and dirty utility to rewrite a (possibly interlaced) PNG image file
    4    as a non-interlaced PNG image file with all ancillary chunks beyond
    5 
    6        bKGD - background color
    7        gAMA - image gamma setting
    8        pHYs - physical pixel dimensions
    9        sRGB - srgb color space indicator
   10        tRNS - transparency
   11 
   12    being removed.
   13 
   14    Copyright (C) 2004-2021 by Brian Lindholm.  This file is part of the
   15    littleutils utility set.
   16 
   17    The pngstrip utility is free software; you can redistribute it and/or modify
   18    it under the terms of the GNU General Public License as published by the
   19    Free Software Foundation; either version 3, or (at your option) any later
   20    version.
   21 
   22    The pngstrip utility is distributed in the hope that it will be useful, but
   23    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   24    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   25    more details.
   26 
   27    You should have received a copy of the GNU General Public License along with
   28    the littleutils.  If not, see <https://www.gnu.org/licenses/>. */
   29 
   30 
   31 #include <config.h>
   32 
   33 #ifdef HAVE_STDIO_H
   34 # include <stdio.h>
   35 #endif
   36 #ifdef HAVE_STDLIB_H
   37 # include <stdlib.h>
   38 #endif
   39 
   40 #ifdef HAVE_UNISTD_H
   41 # include <unistd.h>
   42 # define OPTEND -1
   43 #else
   44 # define OPTEND EOF
   45 #endif
   46 #ifdef HAVE_GETOPT_H
   47 # include <getopt.h>
   48 #endif
   49 
   50 #ifdef HAVE_ZLIB_H
   51 # include <zlib.h>
   52 #endif
   53 
   54 #include <png.h>
   55 
   56 #ifdef __MINGW32__
   57 extern int getopt (int argc, char * const *argv, const char *optstring);
   58 extern char *optarg;
   59 extern int optind;
   60 #endif
   61 
   62 #ifndef PNG_TRANSFORM_GRAYSCALE
   63 # define PNG_TRANSFORM_GRAYSCALE 0x1000 /* on reads only */
   64 #endif
   65 
   66 
   67 typedef struct
   68 {
   69   png_uint_32 width;
   70   png_uint_32 height;
   71   int bit_depth;
   72   int color_type;
   73   int interlace_type;
   74   int compression_type;
   75   int filter_type;
   76 }
   77 ihdr_t;
   78 
   79 
   80 /* help function */
   81 
   82 static void
   83 help (FILE *where)
   84 {
   85   fprintf (where,
   86     "pngstrip " PACKAGE_VERSION "\n"
   87     "usage: pngstrip [-8(bit_strip_to)] [-a(lpha_strip)] [-e(xpand_to_rgb)]\n"
   88     "  [-g(rayscale_convert)] [-r DPM] [-h(elp)] infile outfile\n");
   89 }
   90 
   91 
   92 /* rewrite PNG function */
   93 
   94 static void
   95 rewrite_png (char *read_file, char *write_file, png_uint_32 trnsfrm, png_uint_32 dpm)
   96 {
   97   png_bytep header, trans;
   98   png_bytepp row_pointers;
   99   png_colorp palette;
  100   png_color_16p trans_values, background;
  101   png_infop read_info_ptr, write_info_ptr, read_end_info;
  102   png_structp read_png_ptr, write_png_ptr;
  103   png_uint_32 has_bkgd, has_gama, has_phys, has_plte,
  104               has_srgb, has_trns, row, res_x, res_y;
  105   FILE *fp, *fp2;
  106   double gamma;
  107   ihdr_t ihdr;
  108   int srgb_intent, num_palette, num_trans, is_png, unit_type;
  109 
  110   /* open file for reading */
  111   if ((fp = fopen (read_file, "rb")) == NULL)
  112     {
  113       fprintf (stderr, "pngstrip error: can't open file %s\n", read_file);
  114       exit (1);
  115     }
  116 
  117   /* check for PNG signature */
  118   header = (png_bytep) calloc ((size_t) 8, (size_t) 1);
  119   (void) fread(header, (size_t) 1, (size_t) 8, fp);
  120   is_png = !png_sig_cmp(header, (png_size_t) 0, (png_size_t) 8);
  121   free (header);
  122   if (!is_png)
  123     {
  124       fprintf (stderr, "pngstrip error: %s is not a PNG file\n", read_file);
  125       (void) fclose (fp);
  126       exit (2);
  127     }
  128 
  129   /* allocate various png memory structures */
  130   read_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL,
  131     NULL);
  132   if (read_png_ptr == NULL)
  133     {
  134       fprintf (stderr, "pngstrip error: can't create read_struct\n");
  135       (void) fclose (fp);
  136       exit (3);
  137     }
  138   read_info_ptr = png_create_info_struct (read_png_ptr);
  139   if (read_info_ptr == NULL)
  140     {
  141       fprintf (stderr, "pngstrip error: can't create read_info_struct\n");
  142       png_destroy_read_struct (&read_png_ptr, (png_infopp) NULL,
  143         (png_infopp) NULL);
  144       (void) fclose (fp);
  145       exit (3);
  146     }
  147   read_end_info = png_create_info_struct (read_png_ptr);
  148   if (read_end_info == NULL)
  149     {
  150       fprintf (stderr, "pngstrip error: can't create read_end_info\n");
  151       png_destroy_read_struct (&read_png_ptr, &read_info_ptr,
  152         (png_infopp) NULL);
  153       (void) fclose (fp);
  154       exit (3);
  155     }
  156   if (setjmp (png_jmpbuf (read_png_ptr)))
  157     {
  158       fprintf (stderr, "bizzare pngstrip error: unknown problem on read\n");
  159       png_destroy_read_struct (&read_png_ptr, &read_info_ptr, &read_end_info);
  160       (void) fclose (fp);
  161       exit (3);
  162     }
  163 
  164   /* read the file the simple way */
  165   /* png_init_io (read_png_ptr, fp);
  166   png_set_sig_bytes(read_png_ptr, 8);
  167   png_read_png (read_png_ptr, read_info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  168   (void) fclose (fp); */
  169   /* This was dropped because it didn't allow grayscale transforms. */
  170 
  171   /* begin reading the file the complicated way */
  172   png_init_io (read_png_ptr, fp);
  173   png_set_sig_bytes(read_png_ptr, 8);
  174   png_read_info (read_png_ptr, read_info_ptr);
  175 
  176   /* extract image header */
  177   png_get_IHDR (read_png_ptr, read_info_ptr, &ihdr.width, &ihdr.height,
  178     &ihdr.bit_depth, &ihdr.color_type, &ihdr.interlace_type,
  179     &ihdr.compression_type, &ihdr.filter_type);
  180 
  181   /* activate requested transformations */
  182   if ((trnsfrm & PNG_TRANSFORM_STRIP_16) && (ihdr.bit_depth == 16))
  183     {
  184       png_set_strip_16 (read_png_ptr);
  185       ihdr.bit_depth = 8;
  186     }
  187   if (trnsfrm & PNG_TRANSFORM_STRIP_ALPHA)
  188     {
  189       if (ihdr.color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  190         {
  191           png_set_strip_alpha (read_png_ptr);
  192           ihdr.color_type = PNG_COLOR_TYPE_RGB;
  193         }
  194       else if (ihdr.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  195         {
  196           png_set_strip_alpha (read_png_ptr);
  197           ihdr.color_type = PNG_COLOR_TYPE_GRAY;
  198         }
  199     }
  200   if (((trnsfrm & PNG_TRANSFORM_EXPAND) ||
  201     (trnsfrm & PNG_TRANSFORM_GRAYSCALE)) &&
  202     (ihdr.color_type == PNG_COLOR_TYPE_PALETTE))
  203     {
  204       png_set_palette_to_rgb (read_png_ptr);
  205       ihdr.bit_depth = 8;
  206       ihdr.color_type = PNG_COLOR_TYPE_RGB;
  207       if (((trnsfrm & PNG_TRANSFORM_STRIP_ALPHA) == 0) &&
  208         png_get_valid (read_png_ptr, read_info_ptr, PNG_INFO_tRNS))
  209         {
  210           png_set_tRNS_to_alpha(read_png_ptr);
  211           ihdr.color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  212         }
  213     }
  214   if (trnsfrm & PNG_TRANSFORM_GRAYSCALE)
  215     {
  216       if (ihdr.color_type == PNG_COLOR_TYPE_RGB)
  217         {
  218           png_set_rgb_to_gray_fixed (read_png_ptr, 1, 21268, 71514);
  219           ihdr.color_type = PNG_COLOR_TYPE_GRAY;
  220         }
  221       else if (ihdr.color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  222         {
  223           png_set_rgb_to_gray_fixed (read_png_ptr, 1, 21268, 71514);
  224           ihdr.color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
  225         }
  226     }
  227   if (trnsfrm != 0)
  228     png_read_update_info (read_png_ptr, read_info_ptr);
  229 
  230   /* allocate memory for image and finish reading in the image */
  231   row_pointers = png_malloc (read_png_ptr, ihdr.height * sizeof (png_bytep));
  232   for (row = 0; row < ihdr.height; row++)
  233     row_pointers[row] = png_malloc (read_png_ptr, png_get_rowbytes
  234       (read_png_ptr, read_info_ptr));
  235   png_read_image (read_png_ptr, row_pointers);
  236   png_read_end (read_png_ptr, read_info_ptr);
  237   (void) fclose (fp);
  238 
  239   /* extract additional information to variables */
  240   has_bkgd = png_get_bKGD (read_png_ptr, read_info_ptr, &background);
  241   has_gama = png_get_gAMA (read_png_ptr, read_info_ptr, &gamma);
  242   if (dpm > 0)
  243     {
  244       has_phys = PNG_INFO_pHYs;
  245       res_x = dpm;
  246       res_y = dpm;
  247       unit_type = PNG_RESOLUTION_METER;
  248     }
  249   else
  250     has_phys = png_get_pHYs (read_png_ptr, read_info_ptr, &res_x, &res_y, &unit_type);
  251   has_plte = png_get_PLTE (read_png_ptr, read_info_ptr, &palette, &num_palette);
  252   has_srgb = png_get_sRGB (read_png_ptr, read_info_ptr, &srgb_intent);
  253   has_trns = png_get_tRNS (read_png_ptr, read_info_ptr, &trans, &num_trans,
  254     &trans_values);
  255 
  256   /* open file for writing */
  257   fp2 = fopen (write_file, "wb");
  258   if (!fp2)
  259     {
  260       fprintf (stderr, "pngstrip error: can't open file %s for writing\n",
  261         write_file);
  262       png_destroy_read_struct (&read_png_ptr, &read_info_ptr, &read_end_info);
  263       exit (1);
  264     }
  265 
  266   /* allocate various png memory structures */
  267   write_png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL,
  268     NULL);
  269   if (!write_png_ptr)
  270     {
  271       fprintf (stderr, "pngstrip error: can't create write struct\n");
  272       png_destroy_read_struct (&read_png_ptr, &read_info_ptr, &read_end_info);
  273       (void) fclose (fp);
  274       exit (3);
  275     }
  276   write_info_ptr = png_create_info_struct (write_png_ptr);
  277   if (!write_info_ptr)
  278     {
  279       fprintf (stderr, "pngstrip error: can't create write info struct\n");
  280       png_destroy_write_struct (&write_png_ptr, NULL);
  281       png_destroy_read_struct (&read_png_ptr, &read_info_ptr, &read_end_info);
  282       (void) fclose (fp);
  283       exit (3);
  284     }
  285   if (setjmp (png_jmpbuf (write_png_ptr)))
  286     {
  287       fprintf (stderr, "bizzare pngstrip error: unknown problem on write\n");
  288       png_destroy_write_struct (&write_png_ptr, &write_info_ptr);
  289       png_destroy_read_struct (&read_png_ptr, &read_info_ptr, &read_end_info);
  290       (void) fclose (fp);
  291       exit (3);
  292     }
  293   png_init_io (write_png_ptr, fp2);
  294 
  295   /* assign various pointers and pieces of information */
  296   png_set_IHDR (write_png_ptr, write_info_ptr, ihdr.width, ihdr.height,
  297     ihdr.bit_depth, ihdr.color_type, PNG_INTERLACE_NONE,
  298     ihdr.compression_type, ihdr.filter_type);
  299   if (has_bkgd)
  300     png_set_bKGD(write_png_ptr, write_info_ptr, background);
  301   if (has_gama)
  302     png_set_gAMA(write_png_ptr, write_info_ptr, gamma);
  303   if (has_phys)
  304     png_set_pHYs(write_png_ptr, write_info_ptr, res_x, res_y, unit_type);
  305   if (has_plte && (ihdr.color_type == PNG_COLOR_TYPE_PALETTE))
  306     png_set_PLTE (write_png_ptr, write_info_ptr, palette, num_palette);
  307   if (has_srgb)
  308     png_set_sRGB(write_png_ptr, write_info_ptr, srgb_intent);
  309   if (has_trns && ((trnsfrm & PNG_TRANSFORM_STRIP_ALPHA) == 0))
  310     png_set_tRNS(write_png_ptr, write_info_ptr, trans, num_trans, trans_values);
  311   png_set_rows (write_png_ptr, write_info_ptr, row_pointers);
  312   png_set_compression_level(write_png_ptr, Z_BEST_COMPRESSION);
  313 
  314   /* write file */
  315   png_write_png (write_png_ptr, write_info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  316   (void) fclose (fp2);
  317 
  318   /* free allocated memory structures */
  319   png_destroy_write_struct (&write_png_ptr, &write_info_ptr);
  320   png_destroy_read_struct (&read_png_ptr, &read_info_ptr, &read_end_info);
  321 }
  322 
  323 
  324 /* main program */
  325 
  326 int
  327 main (int argc, char **argv)
  328 {
  329   int opt;
  330   png_uint_32 dpm, trnsfrm;
  331 
  332   /* parse options */
  333   trnsfrm = 0;
  334   dpm = 0;
  335   while ((opt = getopt (argc, argv, "8aeghr:")) != OPTEND)
  336     switch (opt)
  337       {
  338       case '8':
  339         trnsfrm += PNG_TRANSFORM_STRIP_16;
  340         break;
  341       case 'a':
  342         trnsfrm += PNG_TRANSFORM_STRIP_ALPHA;
  343         break;
  344       case 'e':
  345         trnsfrm += PNG_TRANSFORM_EXPAND;
  346         break;
  347       case 'g':
  348         trnsfrm += PNG_TRANSFORM_GRAYSCALE;
  349         break;
  350       case 'h':
  351         help (stdout);
  352         return (0);
  353       case 'r':
  354         dpm = (png_uint_32) atoi(optarg);
  355         break;
  356       case '?':
  357         help (stderr);
  358         return (1);
  359       }
  360 
  361   /* Ensure that two files were given as input. */
  362   if ((argc - optind) != 2)
  363     {
  364       fprintf (stderr, "pngstrip error: missing input or output file\n");
  365       help (stderr);
  366       return (1);
  367     }
  368 
  369   /* Rewrite the image without interlacing and unwanted chunks removed. */
  370   rewrite_png (argv[optind], argv[optind + 1], trnsfrm, dpm);
  371 
  372   /* Indicate successful finish. */
  373   return (0);
  374 }