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