Subversion Repositories Kolibri OS

Rev

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

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