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