pngwtran.c
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:17k
源码类别:

界面编程

开发平台:

Visual C++

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