media/libpng/pngwtran.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial