tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pngwtran.c (15336B)


      1 /* pngwtran.c - transforms the data in a row for PNG writers
      2 *
      3 * Copyright (c) 2018 Cosmin Truta
      4 * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
      5 * Copyright (c) 1996-1997 Andreas Dilger
      6 * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
      7 *
      8 * This code is released under the libpng license.
      9 * For conditions of distribution and use, see the disclaimer
     10 * and license in png.h
     11 */
     12 
     13 #include "pngpriv.h"
     14 
     15 #ifdef PNG_WRITE_SUPPORTED
     16 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
     17 
     18 #ifdef PNG_WRITE_PACK_SUPPORTED
     19 /* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
     20 * row_info bit depth should be 8 (one pixel per byte).  The channels
     21 * should be 1 (this only happens on grayscale and paletted images).
     22 */
     23 static void
     24 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
     25 {
     26   png_debug(1, "in png_do_pack");
     27 
     28   if (row_info->bit_depth == 8 &&
     29      row_info->channels == 1)
     30   {
     31      switch ((int)bit_depth)
     32      {
     33         case 1:
     34         {
     35            png_bytep sp, dp;
     36            int mask, v;
     37            png_uint_32 i;
     38            png_uint_32 row_width = row_info->width;
     39 
     40            sp = row;
     41            dp = row;
     42            mask = 0x80;
     43            v = 0;
     44 
     45            for (i = 0; i < row_width; i++)
     46            {
     47               if (*sp != 0)
     48                  v |= mask;
     49 
     50               sp++;
     51 
     52               if (mask > 1)
     53                  mask >>= 1;
     54 
     55               else
     56               {
     57                  mask = 0x80;
     58                  *dp = (png_byte)v;
     59                  dp++;
     60                  v = 0;
     61               }
     62            }
     63 
     64            if (mask != 0x80)
     65               *dp = (png_byte)v;
     66 
     67            break;
     68         }
     69 
     70         case 2:
     71         {
     72            png_bytep sp, dp;
     73            unsigned int shift;
     74            int v;
     75            png_uint_32 i;
     76            png_uint_32 row_width = row_info->width;
     77 
     78            sp = row;
     79            dp = row;
     80            shift = 6;
     81            v = 0;
     82 
     83            for (i = 0; i < row_width; i++)
     84            {
     85               png_byte value;
     86 
     87               value = (png_byte)(*sp & 0x03);
     88               v |= (value << shift);
     89 
     90               if (shift == 0)
     91               {
     92                  shift = 6;
     93                  *dp = (png_byte)v;
     94                  dp++;
     95                  v = 0;
     96               }
     97 
     98               else
     99                  shift -= 2;
    100 
    101               sp++;
    102            }
    103 
    104            if (shift != 6)
    105               *dp = (png_byte)v;
    106 
    107            break;
    108         }
    109 
    110         case 4:
    111         {
    112            png_bytep sp, dp;
    113            unsigned int shift;
    114            int v;
    115            png_uint_32 i;
    116            png_uint_32 row_width = row_info->width;
    117 
    118            sp = row;
    119            dp = row;
    120            shift = 4;
    121            v = 0;
    122 
    123            for (i = 0; i < row_width; i++)
    124            {
    125               png_byte value;
    126 
    127               value = (png_byte)(*sp & 0x0f);
    128               v |= (value << shift);
    129 
    130               if (shift == 0)
    131               {
    132                  shift = 4;
    133                  *dp = (png_byte)v;
    134                  dp++;
    135                  v = 0;
    136               }
    137 
    138               else
    139                  shift -= 4;
    140 
    141               sp++;
    142            }
    143 
    144            if (shift != 4)
    145               *dp = (png_byte)v;
    146 
    147            break;
    148         }
    149 
    150         default:
    151            break;
    152      }
    153 
    154      row_info->bit_depth = (png_byte)bit_depth;
    155      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
    156      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
    157          row_info->width);
    158   }
    159 }
    160 #endif
    161 
    162 #ifdef PNG_WRITE_SHIFT_SUPPORTED
    163 /* Shift pixel values to take advantage of whole range.  Pass the
    164 * true number of bits in bit_depth.  The row should be packed
    165 * according to row_info->bit_depth.  Thus, if you had a row of
    166 * bit depth 4, but the pixels only had values from 0 to 7, you
    167 * would pass 3 as bit_depth, and this routine would translate the
    168 * data to 0 to 15.
    169 */
    170 static void
    171 png_do_shift(png_row_infop row_info, png_bytep row,
    172    png_const_color_8p bit_depth)
    173 {
    174   png_debug(1, "in png_do_shift");
    175 
    176   if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
    177   {
    178      int shift_start[4], shift_dec[4];
    179      unsigned int channels = 0;
    180 
    181      if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
    182      {
    183         shift_start[channels] = row_info->bit_depth - bit_depth->red;
    184         shift_dec[channels] = bit_depth->red;
    185         channels++;
    186 
    187         shift_start[channels] = row_info->bit_depth - bit_depth->green;
    188         shift_dec[channels] = bit_depth->green;
    189         channels++;
    190 
    191         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
    192         shift_dec[channels] = bit_depth->blue;
    193         channels++;
    194      }
    195 
    196      else
    197      {
    198         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
    199         shift_dec[channels] = bit_depth->gray;
    200         channels++;
    201      }
    202 
    203      if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
    204      {
    205         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
    206         shift_dec[channels] = bit_depth->alpha;
    207         channels++;
    208      }
    209 
    210      /* With low row depths, could only be grayscale, so one channel */
    211      if (row_info->bit_depth < 8)
    212      {
    213         png_bytep bp = row;
    214         size_t i;
    215         unsigned int mask;
    216         size_t row_bytes = row_info->rowbytes;
    217 
    218         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
    219            mask = 0x55;
    220 
    221         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
    222            mask = 0x11;
    223 
    224         else
    225            mask = 0xff;
    226 
    227         for (i = 0; i < row_bytes; i++, bp++)
    228         {
    229            int j;
    230            unsigned int v, out;
    231 
    232            v = *bp;
    233            out = 0;
    234 
    235            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
    236            {
    237               if (j > 0)
    238                  out |= v << j;
    239 
    240               else
    241                  out |= (v >> (-j)) & mask;
    242            }
    243 
    244            *bp = (png_byte)(out & 0xff);
    245         }
    246      }
    247 
    248      else if (row_info->bit_depth == 8)
    249      {
    250         png_bytep bp = row;
    251         png_uint_32 i;
    252         png_uint_32 istop = channels * row_info->width;
    253 
    254         for (i = 0; i < istop; i++, bp++)
    255         {
    256            unsigned int c = i%channels;
    257            int j;
    258            unsigned int v, out;
    259 
    260            v = *bp;
    261            out = 0;
    262 
    263            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
    264            {
    265               if (j > 0)
    266                  out |= v << j;
    267 
    268               else
    269                  out |= v >> (-j);
    270            }
    271 
    272            *bp = (png_byte)(out & 0xff);
    273         }
    274      }
    275 
    276      else
    277      {
    278         png_bytep bp;
    279         png_uint_32 i;
    280         png_uint_32 istop = channels * row_info->width;
    281 
    282         for (bp = row, i = 0; i < istop; i++)
    283         {
    284            unsigned int c = i%channels;
    285            int j;
    286            unsigned int value, v;
    287 
    288            v = png_get_uint_16(bp);
    289            value = 0;
    290 
    291            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
    292            {
    293               if (j > 0)
    294                  value |= v << j;
    295 
    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
    306 
    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");
    312 
    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;
    322 
    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         }
    332 
    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;
    340 
    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 /* WRITE_16BIT */
    357      }
    358 
    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;
    367 
    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         }
    375 
    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;
    383 
    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 /* WRITE_16BIT */
    396      }
    397   }
    398 }
    399 #endif
    400 
    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");
    406 
    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;
    416 
    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         }
    428 
    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;
    436 
    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 /* WRITE_16BIT */
    453      }
    454 
    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;
    463 
    464            for (i = 0, sp = dp = row; i < row_width; i++)
    465            {
    466               *(dp++) = *(sp++);
    467               *(dp++) = (png_byte)(255 - *(sp++));
    468            }
    469         }
    470 
    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;
    478 
    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 /* WRITE_16BIT */
    491      }
    492   }
    493 }
    494 #endif
    495 
    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");
    503 
    504   if (png_ptr == NULL)
    505      return;
    506 
    507 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
    508   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
    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                /*  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
    522 
    523 #ifdef PNG_WRITE_FILLER_SUPPORTED
    524   if ((png_ptr->transformations & PNG_FILLER) != 0)
    525      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
    526          !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
    527 #endif
    528 
    529 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED
    530   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
    531      png_do_packswap(row_info, png_ptr->row_buf + 1);
    532 #endif
    533 
    534 #ifdef PNG_WRITE_PACK_SUPPORTED
    535   if ((png_ptr->transformations & PNG_PACK) != 0)
    536      png_do_pack(row_info, png_ptr->row_buf + 1,
    537          (png_uint_32)png_ptr->bit_depth);
    538 #endif
    539 
    540 #ifdef PNG_WRITE_SWAP_SUPPORTED
    541 #  ifdef PNG_16BIT_SUPPORTED
    542   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
    543      png_do_swap(row_info, png_ptr->row_buf + 1);
    544 #  endif
    545 #endif
    546 
    547 #ifdef PNG_WRITE_SHIFT_SUPPORTED
    548   if ((png_ptr->transformations & PNG_SHIFT) != 0)
    549      png_do_shift(row_info, png_ptr->row_buf + 1,
    550           &(png_ptr->shift));
    551 #endif
    552 
    553 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
    554   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
    555      png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
    556 #endif
    557 
    558 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
    559   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
    560      png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
    561 #endif
    562 
    563 #ifdef PNG_WRITE_BGR_SUPPORTED
    564   if ((png_ptr->transformations & PNG_BGR) != 0)
    565      png_do_bgr(row_info, png_ptr->row_buf + 1);
    566 #endif
    567 
    568 #ifdef PNG_WRITE_INVERT_SUPPORTED
    569   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
    570      png_do_invert(row_info, png_ptr->row_buf + 1);
    571 #endif
    572 }
    573 #endif /* WRITE_TRANSFORMS */
    574 #endif /* WRITE */