Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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