Home | History | Annotate | Download | only in libpng
      1 
      2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
      3  *
      4  * Last changed in libpng 1.2.41 [December 3, 2009]
      5  * Copyright (c) 1998-2009 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 #define PNG_INTERNAL
     15 #define PNG_NO_PEDANTIC_WARNINGS
     16 #include "png.h"
     17 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
     18 
     19 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
     20 /* Turn on BGR-to-RGB mapping */
     21 void PNGAPI
     22 png_set_bgr(png_structp png_ptr)
     23 {
     24    png_debug(1, "in png_set_bgr");
     25 
     26    if (png_ptr == NULL)
     27       return;
     28    png_ptr->transformations |= PNG_BGR;
     29 }
     30 #endif
     31 
     32 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
     33 /* Turn on 16 bit byte swapping */
     34 void PNGAPI
     35 png_set_swap(png_structp png_ptr)
     36 {
     37    png_debug(1, "in png_set_swap");
     38 
     39    if (png_ptr == NULL)
     40       return;
     41    if (png_ptr->bit_depth == 16)
     42       png_ptr->transformations |= PNG_SWAP_BYTES;
     43 }
     44 #endif
     45 
     46 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
     47 /* Turn on pixel packing */
     48 void PNGAPI
     49 png_set_packing(png_structp png_ptr)
     50 {
     51    png_debug(1, "in png_set_packing");
     52 
     53    if (png_ptr == NULL)
     54       return;
     55    if (png_ptr->bit_depth < 8)
     56    {
     57       png_ptr->transformations |= PNG_PACK;
     58       png_ptr->usr_bit_depth = 8;
     59    }
     60 }
     61 #endif
     62 
     63 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
     64 /* Turn on packed pixel swapping */
     65 void PNGAPI
     66 png_set_packswap(png_structp png_ptr)
     67 {
     68    png_debug(1, "in png_set_packswap");
     69 
     70    if (png_ptr == NULL)
     71       return;
     72    if (png_ptr->bit_depth < 8)
     73       png_ptr->transformations |= PNG_PACKSWAP;
     74 }
     75 #endif
     76 
     77 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
     78 void PNGAPI
     79 png_set_shift(png_structp png_ptr, png_color_8p true_bits)
     80 {
     81    png_debug(1, "in png_set_shift");
     82 
     83    if (png_ptr == NULL)
     84       return;
     85    png_ptr->transformations |= PNG_SHIFT;
     86    png_ptr->shift = *true_bits;
     87 }
     88 #endif
     89 
     90 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
     91     defined(PNG_WRITE_INTERLACING_SUPPORTED)
     92 int PNGAPI
     93 png_set_interlace_handling(png_structp png_ptr)
     94 {
     95    png_debug(1, "in png_set_interlace handling");
     96 
     97    if (png_ptr && png_ptr->interlaced)
     98    {
     99       png_ptr->transformations |= PNG_INTERLACE;
    100       return (7);
    101    }
    102 
    103    return (1);
    104 }
    105 #endif
    106 
    107 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
    108 /* Add a filler byte on read, or remove a filler or alpha byte on write.
    109  * The filler type has changed in v0.95 to allow future 2-byte fillers
    110  * for 48-bit input data, as well as to avoid problems with some compilers
    111  * that don't like bytes as parameters.
    112  */
    113 void PNGAPI
    114 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
    115 {
    116    png_debug(1, "in png_set_filler");
    117 
    118    if (png_ptr == NULL)
    119       return;
    120    png_ptr->transformations |= PNG_FILLER;
    121 #ifdef PNG_LEGACY_SUPPORTED
    122    png_ptr->filler = (png_byte)filler;
    123 #else
    124    png_ptr->filler = (png_uint_16)filler;
    125 #endif
    126    if (filler_loc == PNG_FILLER_AFTER)
    127       png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
    128    else
    129       png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
    130 
    131    /* This should probably go in the "do_read_filler" routine.
    132     * I attempted to do that in libpng-1.0.1a but that caused problems
    133     * so I restored it in libpng-1.0.2a
    134    */
    135 
    136    if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
    137    {
    138       png_ptr->usr_channels = 4;
    139    }
    140 
    141    /* Also I added this in libpng-1.0.2a (what happens when we expand
    142     * a less-than-8-bit grayscale to GA? */
    143 
    144    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
    145    {
    146       png_ptr->usr_channels = 2;
    147    }
    148 }
    149 
    150 #ifndef PNG_1_0_X
    151 /* Added to libpng-1.2.7 */
    152 void PNGAPI
    153 png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
    154 {
    155    png_debug(1, "in png_set_add_alpha");
    156 
    157    if (png_ptr == NULL)
    158       return;
    159    png_set_filler(png_ptr, filler, filler_loc);
    160    png_ptr->transformations |= PNG_ADD_ALPHA;
    161 }
    162 #endif
    163 
    164 #endif
    165 
    166 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
    167     defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
    168 void PNGAPI
    169 png_set_swap_alpha(png_structp png_ptr)
    170 {
    171    png_debug(1, "in png_set_swap_alpha");
    172 
    173    if (png_ptr == NULL)
    174       return;
    175    png_ptr->transformations |= PNG_SWAP_ALPHA;
    176 }
    177 #endif
    178 
    179 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
    180     defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
    181 void PNGAPI
    182 png_set_invert_alpha(png_structp png_ptr)
    183 {
    184    png_debug(1, "in png_set_invert_alpha");
    185 
    186    if (png_ptr == NULL)
    187       return;
    188    png_ptr->transformations |= PNG_INVERT_ALPHA;
    189 }
    190 #endif
    191 
    192 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
    193 void PNGAPI
    194 png_set_invert_mono(png_structp png_ptr)
    195 {
    196    png_debug(1, "in png_set_invert_mono");
    197 
    198    if (png_ptr == NULL)
    199       return;
    200    png_ptr->transformations |= PNG_INVERT_MONO;
    201 }
    202 
    203 /* Invert monochrome grayscale data */
    204 void /* PRIVATE */
    205 png_do_invert(png_row_infop row_info, png_bytep row)
    206 {
    207    png_debug(1, "in png_do_invert");
    208 
    209   /* This test removed from libpng version 1.0.13 and 1.2.0:
    210    *   if (row_info->bit_depth == 1 &&
    211    */
    212 #ifdef PNG_USELESS_TESTS_SUPPORTED
    213    if (row == NULL || row_info == NULL)
    214      return;
    215 #endif
    216    if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
    217    {
    218       png_bytep rp = row;
    219       png_uint_32 i;
    220       png_uint_32 istop = row_info->rowbytes;
    221 
    222       for (i = 0; i < istop; i++)
    223       {
    224          *rp = (png_byte)(~(*rp));
    225          rp++;
    226       }
    227    }
    228    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
    229       row_info->bit_depth == 8)
    230    {
    231       png_bytep rp = row;
    232       png_uint_32 i;
    233       png_uint_32 istop = row_info->rowbytes;
    234 
    235       for (i = 0; i < istop; i+=2)
    236       {
    237          *rp = (png_byte)(~(*rp));
    238          rp+=2;
    239       }
    240    }
    241    else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
    242       row_info->bit_depth == 16)
    243    {
    244       png_bytep rp = row;
    245       png_uint_32 i;
    246       png_uint_32 istop = row_info->rowbytes;
    247 
    248       for (i = 0; i < istop; i+=4)
    249       {
    250          *rp = (png_byte)(~(*rp));
    251          *(rp+1) = (png_byte)(~(*(rp+1)));
    252          rp+=4;
    253       }
    254    }
    255 }
    256 #endif
    257 
    258 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
    259 /* Swaps byte order on 16 bit depth images */
    260 void /* PRIVATE */
    261 png_do_swap(png_row_infop row_info, png_bytep row)
    262 {
    263    png_debug(1, "in png_do_swap");
    264 
    265    if (
    266 #ifdef PNG_USELESS_TESTS_SUPPORTED
    267        row != NULL && row_info != NULL &&
    268 #endif
    269        row_info->bit_depth == 16)
    270    {
    271       png_bytep rp = row;
    272       png_uint_32 i;
    273       png_uint_32 istop= row_info->width * row_info->channels;
    274 
    275       for (i = 0; i < istop; i++, rp += 2)
    276       {
    277          png_byte t = *rp;
    278          *rp = *(rp + 1);
    279          *(rp + 1) = t;
    280       }
    281    }
    282 }
    283 #endif
    284 
    285 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
    286 static PNG_CONST png_byte onebppswaptable[256] = {
    287    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
    288    0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
    289    0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
    290    0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
    291    0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
    292    0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
    293    0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
    294    0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
    295    0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
    296    0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
    297    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
    298    0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
    299    0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
    300    0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
    301    0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
    302    0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
    303    0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
    304    0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
    305    0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
    306    0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
    307    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
    308    0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
    309    0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
    310    0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
    311    0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
    312    0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
    313    0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
    314    0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
    315    0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
    316    0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
    317    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
    318    0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
    319 };
    320 
    321 static PNG_CONST png_byte twobppswaptable[256] = {
    322    0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
    323    0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
    324    0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
    325    0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
    326    0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
    327    0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
    328    0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
    329    0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
    330    0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
    331    0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
    332    0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
    333    0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
    334    0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
    335    0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
    336    0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
    337    0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
    338    0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
    339    0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
    340    0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
    341    0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
    342    0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
    343    0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
    344    0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
    345    0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
    346    0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
    347    0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
    348    0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
    349    0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
    350    0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
    351    0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
    352    0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
    353    0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
    354 };
    355 
    356 static PNG_CONST png_byte fourbppswaptable[256] = {
    357    0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
    358    0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
    359    0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
    360    0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
    361    0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
    362    0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
    363    0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
    364    0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
    365    0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
    366    0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
    367    0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
    368    0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
    369    0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
    370    0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
    371    0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
    372    0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
    373    0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
    374    0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
    375    0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
    376    0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
    377    0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
    378    0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
    379    0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
    380    0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
    381    0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
    382    0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
    383    0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
    384    0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
    385    0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
    386    0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
    387    0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
    388    0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
    389 };
    390 
    391 /* Swaps pixel packing order within bytes */
    392 void /* PRIVATE */
    393 png_do_packswap(png_row_infop row_info, png_bytep row)
    394 {
    395    png_debug(1, "in png_do_packswap");
    396 
    397    if (
    398 #ifdef PNG_USELESS_TESTS_SUPPORTED
    399        row != NULL && row_info != NULL &&
    400 #endif
    401        row_info->bit_depth < 8)
    402    {
    403       png_bytep rp, end, table;
    404 
    405       end = row + row_info->rowbytes;
    406 
    407       if (row_info->bit_depth == 1)
    408          table = (png_bytep)onebppswaptable;
    409       else if (row_info->bit_depth == 2)
    410          table = (png_bytep)twobppswaptable;
    411       else if (row_info->bit_depth == 4)
    412          table = (png_bytep)fourbppswaptable;
    413       else
    414          return;
    415 
    416       for (rp = row; rp < end; rp++)
    417          *rp = table[*rp];
    418    }
    419 }
    420 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
    421 
    422 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
    423     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
    424 /* Remove filler or alpha byte(s) */
    425 void /* PRIVATE */
    426 png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
    427 {
    428    png_debug(1, "in png_do_strip_filler");
    429 
    430 #ifdef PNG_USELESS_TESTS_SUPPORTED
    431    if (row != NULL && row_info != NULL)
    432 #endif
    433    {
    434       png_bytep sp=row;
    435       png_bytep dp=row;
    436       png_uint_32 row_width=row_info->width;
    437       png_uint_32 i;
    438 
    439       if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
    440           (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
    441           (flags & PNG_FLAG_STRIP_ALPHA))) &&
    442           row_info->channels == 4)
    443       {
    444          if (row_info->bit_depth == 8)
    445          {
    446             /* This converts from RGBX or RGBA to RGB */
    447             if (flags & PNG_FLAG_FILLER_AFTER)
    448             {
    449                dp+=3; sp+=4;
    450                for (i = 1; i < row_width; i++)
    451                {
    452                   *dp++ = *sp++;
    453                   *dp++ = *sp++;
    454                   *dp++ = *sp++;
    455                   sp++;
    456                }
    457             }
    458             /* This converts from XRGB or ARGB to RGB */
    459             else
    460             {
    461                for (i = 0; i < row_width; i++)
    462                {
    463                   sp++;
    464                   *dp++ = *sp++;
    465                   *dp++ = *sp++;
    466                   *dp++ = *sp++;
    467                }
    468             }
    469             row_info->pixel_depth = 24;
    470             row_info->rowbytes = row_width * 3;
    471          }
    472          else /* if (row_info->bit_depth == 16) */
    473          {
    474             if (flags & PNG_FLAG_FILLER_AFTER)
    475             {
    476                /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
    477                sp += 8; dp += 6;
    478                for (i = 1; i < row_width; i++)
    479                {
    480                   /* This could be (although png_memcpy is probably slower):
    481                   png_memcpy(dp, sp, 6);
    482                   sp += 8;
    483                   dp += 6;
    484                   */
    485 
    486                   *dp++ = *sp++;
    487                   *dp++ = *sp++;
    488                   *dp++ = *sp++;
    489                   *dp++ = *sp++;
    490                   *dp++ = *sp++;
    491                   *dp++ = *sp++;
    492                   sp += 2;
    493                }
    494             }
    495             else
    496             {
    497                /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
    498                for (i = 0; i < row_width; i++)
    499                {
    500                   /* This could be (although png_memcpy is probably slower):
    501                   png_memcpy(dp, sp, 6);
    502                   sp += 8;
    503                   dp += 6;
    504                   */
    505 
    506                   sp+=2;
    507                   *dp++ = *sp++;
    508                   *dp++ = *sp++;
    509                   *dp++ = *sp++;
    510                   *dp++ = *sp++;
    511                   *dp++ = *sp++;
    512                   *dp++ = *sp++;
    513                }
    514             }
    515             row_info->pixel_depth = 48;
    516             row_info->rowbytes = row_width * 6;
    517          }
    518          row_info->channels = 3;
    519       }
    520       else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
    521          (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
    522          (flags & PNG_FLAG_STRIP_ALPHA))) &&
    523           row_info->channels == 2)
    524       {
    525          if (row_info->bit_depth == 8)
    526          {
    527             /* This converts from GX or GA to G */
    528             if (flags & PNG_FLAG_FILLER_AFTER)
    529             {
    530                for (i = 0; i < row_width; i++)
    531                {
    532                   *dp++ = *sp++;
    533                   sp++;
    534                }
    535             }
    536             /* This converts from XG or AG to G */
    537             else
    538             {
    539                for (i = 0; i < row_width; i++)
    540                {
    541                   sp++;
    542                   *dp++ = *sp++;
    543                }
    544             }
    545             row_info->pixel_depth = 8;
    546             row_info->rowbytes = row_width;
    547          }
    548          else /* if (row_info->bit_depth == 16) */
    549          {
    550             if (flags & PNG_FLAG_FILLER_AFTER)
    551             {
    552                /* This converts from GGXX or GGAA to GG */
    553                sp += 4; dp += 2;
    554                for (i = 1; i < row_width; i++)
    555                {
    556                   *dp++ = *sp++;
    557                   *dp++ = *sp++;
    558                   sp += 2;
    559                }
    560             }
    561             else
    562             {
    563                /* This converts from XXGG or AAGG to GG */
    564                for (i = 0; i < row_width; i++)
    565                {
    566                   sp += 2;
    567                   *dp++ = *sp++;
    568                   *dp++ = *sp++;
    569                }
    570             }
    571             row_info->pixel_depth = 16;
    572             row_info->rowbytes = row_width * 2;
    573          }
    574          row_info->channels = 1;
    575       }
    576       if (flags & PNG_FLAG_STRIP_ALPHA)
    577         row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
    578    }
    579 }
    580 #endif
    581 
    582 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
    583 /* Swaps red and blue bytes within a pixel */
    584 void /* PRIVATE */
    585 png_do_bgr(png_row_infop row_info, png_bytep row)
    586 {
    587    png_debug(1, "in png_do_bgr");
    588 
    589    if (
    590 #ifdef PNG_USELESS_TESTS_SUPPORTED
    591        row != NULL && row_info != NULL &&
    592 #endif
    593        (row_info->color_type & PNG_COLOR_MASK_COLOR))
    594    {
    595       png_uint_32 row_width = row_info->width;
    596       if (row_info->bit_depth == 8)
    597       {
    598          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
    599          {
    600             png_bytep rp;
    601             png_uint_32 i;
    602 
    603             for (i = 0, rp = row; i < row_width; i++, rp += 3)
    604             {
    605                png_byte save = *rp;
    606                *rp = *(rp + 2);
    607                *(rp + 2) = save;
    608             }
    609          }
    610          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    611          {
    612             png_bytep rp;
    613             png_uint_32 i;
    614 
    615             for (i = 0, rp = row; i < row_width; i++, rp += 4)
    616             {
    617                png_byte save = *rp;
    618                *rp = *(rp + 2);
    619                *(rp + 2) = save;
    620             }
    621          }
    622       }
    623       else if (row_info->bit_depth == 16)
    624       {
    625          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
    626          {
    627             png_bytep rp;
    628             png_uint_32 i;
    629 
    630             for (i = 0, rp = row; i < row_width; i++, rp += 6)
    631             {
    632                png_byte save = *rp;
    633                *rp = *(rp + 4);
    634                *(rp + 4) = save;
    635                save = *(rp + 1);
    636                *(rp + 1) = *(rp + 5);
    637                *(rp + 5) = save;
    638             }
    639          }
    640          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    641          {
    642             png_bytep rp;
    643             png_uint_32 i;
    644 
    645             for (i = 0, rp = row; i < row_width; i++, rp += 8)
    646             {
    647                png_byte save = *rp;
    648                *rp = *(rp + 4);
    649                *(rp + 4) = save;
    650                save = *(rp + 1);
    651                *(rp + 1) = *(rp + 5);
    652                *(rp + 5) = save;
    653             }
    654          }
    655       }
    656    }
    657 }
    658 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
    659 
    660 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
    661     defined(PNG_LEGACY_SUPPORTED) || \
    662     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
    663 void PNGAPI
    664 png_set_user_transform_info(png_structp png_ptr, png_voidp
    665    user_transform_ptr, int user_transform_depth, int user_transform_channels)
    666 {
    667    png_debug(1, "in png_set_user_transform_info");
    668 
    669    if (png_ptr == NULL)
    670       return;
    671 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
    672    png_ptr->user_transform_ptr = user_transform_ptr;
    673    png_ptr->user_transform_depth = (png_byte)user_transform_depth;
    674    png_ptr->user_transform_channels = (png_byte)user_transform_channels;
    675 #else
    676    if (user_transform_ptr || user_transform_depth || user_transform_channels)
    677       png_warning(png_ptr,
    678         "This version of libpng does not support user transform info");
    679 #endif
    680 }
    681 #endif
    682 
    683 /* This function returns a pointer to the user_transform_ptr associated with
    684  * the user transform functions.  The application should free any memory
    685  * associated with this pointer before png_write_destroy and png_read_destroy
    686  * are called.
    687  */
    688 png_voidp PNGAPI
    689 png_get_user_transform_ptr(png_structp png_ptr)
    690 {
    691    if (png_ptr == NULL)
    692       return (NULL);
    693 #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
    694    return ((png_voidp)png_ptr->user_transform_ptr);
    695 #else
    696    return (NULL);
    697 #endif
    698 }
    699 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
    700