Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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