"Fossies" - the Fresh Open Source Software Archive

Member "pngcrush-1.8.13/pngwtran.c" (29 Aug 2017, 15402 Bytes) of package /linux/privat/pngcrush-1.8.13.tar.gz:


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 "pngwtran.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.8.8_vs_1.8.9.

    1 
    2 /* pngwtran.c - transforms the data in a row for PNG writers
    3  *
    4  * Last changed in libpng 1.6.26 [October 20, 2016]
    5  * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
    6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
    7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
    8  *
    9  * This code is released under the libpng license.
   10  * For conditions of distribution and use, see the disclaimer
   11  * and license in png.h
   12  */
   13 
   14 #include "pngpriv.h"
   15 
   16 #ifdef PNG_WRITE_SUPPORTED
   17 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
   18 
   19 #ifdef PNG_WRITE_PACK_SUPPORTED
   20 /* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
   21  * row_info bit depth should be 8 (one pixel per byte).  The channels
   22  * should be 1 (this only happens on grayscale and paletted images).
   23  */
   24 static void
   25 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
   26 {
   27    png_debug(1, "in png_do_pack");
   28 
   29    if (row_info->bit_depth == 8 &&
   30       row_info->channels == 1)
   31    {
   32       switch ((int)bit_depth)
   33       {
   34          case 1:
   35          {
   36             png_bytep sp, dp;
   37             int mask, v;
   38             png_uint_32 i;
   39             png_uint_32 row_width = row_info->width;
   40 
   41             sp = row;
   42             dp = row;
   43             mask = 0x80;
   44             v = 0;
   45 
   46             for (i = 0; i < row_width; i++)
   47             {
   48                if (*sp != 0)
   49                   v |= mask;
   50 
   51                sp++;
   52 
   53                if (mask > 1)
   54                   mask >>= 1;
   55 
   56                else
   57                {
   58                   mask = 0x80;
   59                   *dp = (png_byte)v;
   60                   dp++;
   61                   v = 0;
   62                }
   63             }
   64 
   65             if (mask != 0x80)
   66                *dp = (png_byte)v;
   67 
   68             break;
   69          }
   70 
   71          case 2:
   72          {
   73             png_bytep sp, dp;
   74             unsigned int shift;
   75             int v;
   76             png_uint_32 i;
   77             png_uint_32 row_width = row_info->width;
   78 
   79             sp = row;
   80             dp = row;
   81             shift = 6;
   82             v = 0;
   83 
   84             for (i = 0; i < row_width; i++)
   85             {
   86                png_byte value;
   87 
   88                value = (png_byte)(*sp & 0x03);
   89                v |= (value << shift);
   90 
   91                if (shift == 0)
   92                {
   93                   shift = 6;
   94                   *dp = (png_byte)v;
   95                   dp++;
   96                   v = 0;
   97                }
   98 
   99                else
  100                   shift -= 2;
  101 
  102                sp++;
  103             }
  104 
  105             if (shift != 6)
  106                *dp = (png_byte)v;
  107 
  108             break;
  109          }
  110 
  111          case 4:
  112          {
  113             png_bytep sp, dp;
  114             unsigned int shift;
  115             int v;
  116             png_uint_32 i;
  117             png_uint_32 row_width = row_info->width;
  118 
  119             sp = row;
  120             dp = row;
  121             shift = 4;
  122             v = 0;
  123 
  124             for (i = 0; i < row_width; i++)
  125             {
  126                png_byte value;
  127 
  128                value = (png_byte)(*sp & 0x0f);
  129                v |= (value << shift);
  130 
  131                if (shift == 0)
  132                {
  133                   shift = 4;
  134                   *dp = (png_byte)v;
  135                   dp++;
  136                   v = 0;
  137                }
  138 
  139                else
  140                   shift -= 4;
  141 
  142                sp++;
  143             }
  144 
  145             if (shift != 4)
  146                *dp = (png_byte)v;
  147 
  148             break;
  149          }
  150 
  151          default:
  152             break;
  153       }
  154 
  155       row_info->bit_depth = (png_byte)bit_depth;
  156       row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
  157       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
  158           row_info->width);
  159    }
  160 }
  161 #endif
  162 
  163 #ifdef PNG_WRITE_SHIFT_SUPPORTED
  164 /* Shift pixel values to take advantage of whole range.  Pass the
  165  * true number of bits in bit_depth.  The row should be packed
  166  * according to row_info->bit_depth.  Thus, if you had a row of
  167  * bit depth 4, but the pixels only had values from 0 to 7, you
  168  * would pass 3 as bit_depth, and this routine would translate the
  169  * data to 0 to 15.
  170  */
  171 static void
  172 png_do_shift(png_row_infop row_info, png_bytep row,
  173     png_const_color_8p bit_depth)
  174 {
  175    png_debug(1, "in png_do_shift");
  176 
  177    if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
  178    {
  179       int shift_start[4], shift_dec[4];
  180       unsigned int channels = 0;
  181 
  182       if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
  183       {
  184          shift_start[channels] = row_info->bit_depth - bit_depth->red;
  185          shift_dec[channels] = bit_depth->red;
  186          channels++;
  187 
  188          shift_start[channels] = row_info->bit_depth - bit_depth->green;
  189          shift_dec[channels] = bit_depth->green;
  190          channels++;
  191 
  192          shift_start[channels] = row_info->bit_depth - bit_depth->blue;
  193          shift_dec[channels] = bit_depth->blue;
  194          channels++;
  195       }
  196 
  197       else
  198       {
  199          shift_start[channels] = row_info->bit_depth - bit_depth->gray;
  200          shift_dec[channels] = bit_depth->gray;
  201          channels++;
  202       }
  203 
  204       if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
  205       {
  206          shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
  207          shift_dec[channels] = bit_depth->alpha;
  208          channels++;
  209       }
  210 
  211       /* With low row depths, could only be grayscale, so one channel */
  212       if (row_info->bit_depth < 8)
  213       {
  214          png_bytep bp = row;
  215          png_size_t i;
  216          unsigned int mask;
  217          png_size_t row_bytes = row_info->rowbytes;
  218 
  219          if (bit_depth->gray == 1 && row_info->bit_depth == 2)
  220             mask = 0x55;
  221 
  222          else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
  223             mask = 0x11;
  224 
  225          else
  226             mask = 0xff;
  227 
  228          for (i = 0; i < row_bytes; i++, bp++)
  229          {
  230             int j;
  231             unsigned int v, out;
  232 
  233             v = *bp;
  234             out = 0;
  235 
  236             for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
  237             {
  238                if (j > 0)
  239                   out |= v << j;
  240 
  241                else
  242                   out |= (v >> (-j)) & mask;
  243             }
  244 
  245             *bp = (png_byte)(out & 0xff);
  246          }
  247       }
  248 
  249       else if (row_info->bit_depth == 8)
  250       {
  251          png_bytep bp = row;
  252          png_uint_32 i;
  253          png_uint_32 istop = channels * row_info->width;
  254 
  255          for (i = 0; i < istop; i++, bp++)
  256          {
  257 
  258             const unsigned int c = i%channels;
  259             int j;
  260             unsigned int v, out;
  261 
  262             v = *bp;
  263             out = 0;
  264 
  265             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
  266             {
  267                if (j > 0)
  268                   out |= v << j;
  269 
  270                else
  271                   out |= v >> (-j);
  272             }
  273 
  274             *bp = (png_byte)(out & 0xff);
  275          }
  276       }
  277 
  278       else
  279       {
  280          png_bytep bp;
  281          png_uint_32 i;
  282          png_uint_32 istop = channels * row_info->width;
  283 
  284          for (bp = row, i = 0; i < istop; i++)
  285          {
  286             const unsigned int c = i%channels;
  287             int j;
  288             unsigned int value, v;
  289 
  290             v = png_get_uint_16(bp);
  291             value = 0;
  292 
  293             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
  294             {
  295                if (j > 0)
  296                   value |= v << j;
  297 
  298                else
  299                   value |= v >> (-j);
  300             }
  301             *bp++ = (png_byte)((value >> 8) & 0xff);
  302             *bp++ = (png_byte)(value & 0xff);
  303          }
  304       }
  305    }
  306 }
  307 #endif
  308 
  309 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
  310 static void
  311 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
  312 {
  313    png_debug(1, "in png_do_write_swap_alpha");
  314 
  315    {
  316       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  317       {
  318          if (row_info->bit_depth == 8)
  319          {
  320             /* This converts from ARGB to RGBA */
  321             png_bytep sp, dp;
  322             png_uint_32 i;
  323             png_uint_32 row_width = row_info->width;
  324 
  325             for (i = 0, sp = dp = row; i < row_width; i++)
  326             {
  327                png_byte save = *(sp++);
  328                *(dp++) = *(sp++);
  329                *(dp++) = *(sp++);
  330                *(dp++) = *(sp++);
  331                *(dp++) = save;
  332             }
  333          }
  334 
  335 #ifdef PNG_WRITE_16BIT_SUPPORTED
  336          else
  337          {
  338             /* This converts from AARRGGBB to RRGGBBAA */
  339             png_bytep sp, dp;
  340             png_uint_32 i;
  341             png_uint_32 row_width = row_info->width;
  342 
  343             for (i = 0, sp = dp = row; i < row_width; i++)
  344             {
  345                png_byte save[2];
  346                save[0] = *(sp++);
  347                save[1] = *(sp++);
  348                *(dp++) = *(sp++);
  349                *(dp++) = *(sp++);
  350                *(dp++) = *(sp++);
  351                *(dp++) = *(sp++);
  352                *(dp++) = *(sp++);
  353                *(dp++) = *(sp++);
  354                *(dp++) = save[0];
  355                *(dp++) = save[1];
  356             }
  357          }
  358 #endif /* WRITE_16BIT */
  359       }
  360 
  361       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  362       {
  363          if (row_info->bit_depth == 8)
  364          {
  365             /* This converts from AG to GA */
  366             png_bytep sp, dp;
  367             png_uint_32 i;
  368             png_uint_32 row_width = row_info->width;
  369 
  370             for (i = 0, sp = dp = row; i < row_width; i++)
  371             {
  372                png_byte save = *(sp++);
  373                *(dp++) = *(sp++);
  374                *(dp++) = save;
  375             }
  376          }
  377 
  378 #ifdef PNG_WRITE_16BIT_SUPPORTED
  379          else
  380          {
  381             /* This converts from AAGG to GGAA */
  382             png_bytep sp, dp;
  383             png_uint_32 i;
  384             png_uint_32 row_width = row_info->width;
  385 
  386             for (i = 0, sp = dp = row; i < row_width; i++)
  387             {
  388                png_byte save[2];
  389                save[0] = *(sp++);
  390                save[1] = *(sp++);
  391                *(dp++) = *(sp++);
  392                *(dp++) = *(sp++);
  393                *(dp++) = save[0];
  394                *(dp++) = save[1];
  395             }
  396          }
  397 #endif /* WRITE_16BIT */
  398       }
  399    }
  400 }
  401 #endif
  402 
  403 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
  404 static void
  405 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
  406 {
  407    png_debug(1, "in png_do_write_invert_alpha");
  408 
  409    {
  410       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  411       {
  412          if (row_info->bit_depth == 8)
  413          {
  414             /* This inverts the alpha channel in RGBA */
  415             png_bytep sp, dp;
  416             png_uint_32 i;
  417             png_uint_32 row_width = row_info->width;
  418 
  419             for (i = 0, sp = dp = row; i < row_width; i++)
  420             {
  421                /* Does nothing
  422                *(dp++) = *(sp++);
  423                *(dp++) = *(sp++);
  424                *(dp++) = *(sp++);
  425                */
  426                sp+=3; dp = sp;
  427                *dp = (png_byte)(255 - *(sp++));
  428             }
  429          }
  430 
  431 #ifdef PNG_WRITE_16BIT_SUPPORTED
  432          else
  433          {
  434             /* This inverts the alpha channel in RRGGBBAA */
  435             png_bytep sp, dp;
  436             png_uint_32 i;
  437             png_uint_32 row_width = row_info->width;
  438 
  439             for (i = 0, sp = dp = row; i < row_width; i++)
  440             {
  441                /* Does nothing
  442                *(dp++) = *(sp++);
  443                *(dp++) = *(sp++);
  444                *(dp++) = *(sp++);
  445                *(dp++) = *(sp++);
  446                *(dp++) = *(sp++);
  447                *(dp++) = *(sp++);
  448                */
  449                sp+=6; dp = sp;
  450                *(dp++) = (png_byte)(255 - *(sp++));
  451                *dp     = (png_byte)(255 - *(sp++));
  452             }
  453          }
  454 #endif /* WRITE_16BIT */
  455       }
  456 
  457       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  458       {
  459          if (row_info->bit_depth == 8)
  460          {
  461             /* This inverts the alpha channel in GA */
  462             png_bytep sp, dp;
  463             png_uint_32 i;
  464             png_uint_32 row_width = row_info->width;
  465 
  466             for (i = 0, sp = dp = row; i < row_width; i++)
  467             {
  468                *(dp++) = *(sp++);
  469                *(dp++) = (png_byte)(255 - *(sp++));
  470             }
  471          }
  472 
  473 #ifdef PNG_WRITE_16BIT_SUPPORTED
  474          else
  475          {
  476             /* This inverts the alpha channel in GGAA */
  477             png_bytep sp, dp;
  478             png_uint_32 i;
  479             png_uint_32 row_width = row_info->width;
  480 
  481             for (i = 0, sp = dp = row; i < row_width; i++)
  482             {
  483                /* Does nothing
  484                *(dp++) = *(sp++);
  485                *(dp++) = *(sp++);
  486                */
  487                sp+=2; dp = sp;
  488                *(dp++) = (png_byte)(255 - *(sp++));
  489                *dp     = (png_byte)(255 - *(sp++));
  490             }
  491          }
  492 #endif /* WRITE_16BIT */
  493       }
  494    }
  495 }
  496 #endif
  497 
  498 /* Transform the data according to the user's wishes.  The order of
  499  * transformations is significant.
  500  */
  501 void /* PRIVATE */
  502 png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
  503 {
  504    png_debug(1, "in png_do_write_transformations");
  505 
  506    if (png_ptr == NULL)
  507       return;
  508 
  509 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
  510    if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
  511       if (png_ptr->write_user_transform_fn != NULL)
  512          (*(png_ptr->write_user_transform_fn)) /* User write transform
  513                                                  function */
  514              (png_ptr,  /* png_ptr */
  515              row_info,  /* row_info: */
  516                 /*  png_uint_32 width;       width of row */
  517                 /*  png_size_t rowbytes;     number of bytes in row */
  518                 /*  png_byte color_type;     color type of pixels */
  519                 /*  png_byte bit_depth;      bit depth of samples */
  520                 /*  png_byte channels;       number of channels (1-4) */
  521                 /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
  522              png_ptr->row_buf + 1);      /* start of pixel data for row */
  523 #endif
  524 
  525 #ifdef PNG_WRITE_FILLER_SUPPORTED
  526    if ((png_ptr->transformations & PNG_FILLER) != 0)
  527       png_do_strip_channel(row_info, png_ptr->row_buf + 1,
  528           !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
  529 #endif
  530 
  531 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
  532    if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
  533       png_do_packswap(row_info, png_ptr->row_buf + 1);
  534 #endif
  535 
  536 #ifdef PNG_WRITE_PACK_SUPPORTED
  537    if ((png_ptr->transformations & PNG_PACK) != 0)
  538       png_do_pack(row_info, png_ptr->row_buf + 1,
  539           (png_uint_32)png_ptr->bit_depth);
  540 #endif
  541 
  542 #ifdef PNG_WRITE_SWAP_SUPPORTED
  543 #  ifdef PNG_16BIT_SUPPORTED
  544    if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
  545       png_do_swap(row_info, png_ptr->row_buf + 1);
  546 #  endif
  547 #endif
  548 
  549 #ifdef PNG_WRITE_SHIFT_SUPPORTED
  550    if ((png_ptr->transformations & PNG_SHIFT) != 0)
  551       png_do_shift(row_info, png_ptr->row_buf + 1,
  552            &(png_ptr->shift));
  553 #endif
  554 
  555 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
  556    if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
  557       png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
  558 #endif
  559 
  560 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
  561    if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
  562       png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
  563 #endif
  564 
  565 #ifdef PNG_WRITE_BGR_SUPPORTED
  566    if ((png_ptr->transformations & PNG_BGR) != 0)
  567       png_do_bgr(row_info, png_ptr->row_buf + 1);
  568 #endif
  569 
  570 #ifdef PNG_WRITE_INVERT_SUPPORTED
  571    if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
  572       png_do_invert(row_info, png_ptr->row_buf + 1);
  573 #endif
  574 }
  575 #endif /* WRITE_TRANSFORMS */
  576 #endif /* WRITE */