home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / flash078.zip / flashsource-r0_7_8.zip / libpng / pngwtran.c < prev    next >
C/C++ Source or Header  |  2001-04-27  |  18KB  |  564 lines

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