xref: /plan9-contrib/sys/src/cmd/gs/libpng/pngwtran.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier 
27dd7cddfSDavid du Colombier /* pngwtran.c - transforms the data in a row for PNG writers
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * libpng version 1.2.8 - December 3, 2004
57dd7cddfSDavid du Colombier  * For conditions of distribution and use, see copyright notice in png.h
6*593dc095SDavid du Colombier  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7*593dc095SDavid du Colombier  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8*593dc095SDavid du Colombier  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
97dd7cddfSDavid du Colombier  */
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier #define PNG_INTERNAL
127dd7cddfSDavid du Colombier #include "png.h"
13*593dc095SDavid du Colombier #ifdef PNG_WRITE_SUPPORTED
147dd7cddfSDavid du Colombier 
15*593dc095SDavid du Colombier /* Transform the data according to the user's wishes.  The order of
167dd7cddfSDavid du Colombier  * transformations is significant.
177dd7cddfSDavid du Colombier  */
18*593dc095SDavid du Colombier void /* PRIVATE */
png_do_write_transformations(png_structp png_ptr)197dd7cddfSDavid du Colombier png_do_write_transformations(png_structp png_ptr)
207dd7cddfSDavid du Colombier {
217dd7cddfSDavid du Colombier    png_debug(1, "in png_do_write_transformations\n");
22*593dc095SDavid du Colombier 
23*593dc095SDavid du Colombier    if (png_ptr == NULL)
24*593dc095SDavid du Colombier       return;
25*593dc095SDavid du Colombier 
26*593dc095SDavid du Colombier #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
27*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_USER_TRANSFORM)
28*593dc095SDavid du Colombier       if(png_ptr->write_user_transform_fn != NULL)
29*593dc095SDavid du Colombier         (*(png_ptr->write_user_transform_fn)) /* user write transform function */
30*593dc095SDavid du Colombier           (png_ptr,                    /* png_ptr */
31*593dc095SDavid du Colombier            &(png_ptr->row_info),       /* row_info:     */
32*593dc095SDavid du Colombier              /*  png_uint_32 width;          width of row */
33*593dc095SDavid du Colombier              /*  png_uint_32 rowbytes;       number of bytes in row */
34*593dc095SDavid du Colombier              /*  png_byte color_type;        color type of pixels */
35*593dc095SDavid du Colombier              /*  png_byte bit_depth;         bit depth of samples */
36*593dc095SDavid du Colombier              /*  png_byte channels;          number of channels (1-4) */
37*593dc095SDavid du Colombier              /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
38*593dc095SDavid du Colombier            png_ptr->row_buf + 1);      /* start of pixel data for row */
39*593dc095SDavid du Colombier #endif
407dd7cddfSDavid du Colombier #if defined(PNG_WRITE_FILLER_SUPPORTED)
417dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_FILLER)
427dd7cddfSDavid du Colombier       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
437dd7cddfSDavid du Colombier          png_ptr->flags);
447dd7cddfSDavid du Colombier #endif
457dd7cddfSDavid du Colombier #if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
467dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_PACKSWAP)
477dd7cddfSDavid du Colombier       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
487dd7cddfSDavid du Colombier #endif
497dd7cddfSDavid du Colombier #if defined(PNG_WRITE_PACK_SUPPORTED)
507dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_PACK)
517dd7cddfSDavid du Colombier       png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
527dd7cddfSDavid du Colombier          (png_uint_32)png_ptr->bit_depth);
537dd7cddfSDavid du Colombier #endif
54*593dc095SDavid du Colombier #if defined(PNG_WRITE_SWAP_SUPPORTED)
55*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_SWAP_BYTES)
56*593dc095SDavid du Colombier       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
57*593dc095SDavid du Colombier #endif
587dd7cddfSDavid du Colombier #if defined(PNG_WRITE_SHIFT_SUPPORTED)
597dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_SHIFT)
607dd7cddfSDavid du Colombier       png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
617dd7cddfSDavid du Colombier          &(png_ptr->shift));
627dd7cddfSDavid du Colombier #endif
63*593dc095SDavid du Colombier #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
64*593dc095SDavid du Colombier    if (png_ptr->transformations & PNG_INVERT_ALPHA)
65*593dc095SDavid du Colombier       png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
667dd7cddfSDavid du Colombier #endif
677dd7cddfSDavid du Colombier #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
687dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_SWAP_ALPHA)
697dd7cddfSDavid du Colombier       png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
707dd7cddfSDavid du Colombier #endif
717dd7cddfSDavid du Colombier #if defined(PNG_WRITE_BGR_SUPPORTED)
727dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_BGR)
737dd7cddfSDavid du Colombier       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
747dd7cddfSDavid du Colombier #endif
757dd7cddfSDavid du Colombier #if defined(PNG_WRITE_INVERT_SUPPORTED)
767dd7cddfSDavid du Colombier    if (png_ptr->transformations & PNG_INVERT_MONO)
777dd7cddfSDavid du Colombier       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
787dd7cddfSDavid du Colombier #endif
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier #if defined(PNG_WRITE_PACK_SUPPORTED)
827dd7cddfSDavid du Colombier /* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
837dd7cddfSDavid du Colombier  * row_info bit depth should be 8 (one pixel per byte).  The channels
847dd7cddfSDavid du Colombier  * should be 1 (this only happens on grayscale and paletted images).
857dd7cddfSDavid du Colombier  */
86*593dc095SDavid du Colombier void /* PRIVATE */
png_do_pack(png_row_infop row_info,png_bytep row,png_uint_32 bit_depth)877dd7cddfSDavid du Colombier png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
887dd7cddfSDavid du Colombier {
897dd7cddfSDavid du Colombier    png_debug(1, "in png_do_pack\n");
907dd7cddfSDavid du Colombier    if (row_info->bit_depth == 8 &&
917dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
927dd7cddfSDavid du Colombier        row != NULL && row_info != NULL &&
937dd7cddfSDavid du Colombier #endif
947dd7cddfSDavid du Colombier       row_info->channels == 1)
957dd7cddfSDavid du Colombier    {
967dd7cddfSDavid du Colombier       switch ((int)bit_depth)
977dd7cddfSDavid du Colombier       {
987dd7cddfSDavid du Colombier          case 1:
997dd7cddfSDavid du Colombier          {
1007dd7cddfSDavid du Colombier             png_bytep sp, dp;
1017dd7cddfSDavid du Colombier             int mask, v;
1027dd7cddfSDavid du Colombier             png_uint_32 i;
103*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier             sp = row;
1067dd7cddfSDavid du Colombier             dp = row;
1077dd7cddfSDavid du Colombier             mask = 0x80;
1087dd7cddfSDavid du Colombier             v = 0;
109*593dc095SDavid du Colombier 
110*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
1117dd7cddfSDavid du Colombier             {
1127dd7cddfSDavid du Colombier                if (*sp != 0)
1137dd7cddfSDavid du Colombier                   v |= mask;
1147dd7cddfSDavid du Colombier                sp++;
1157dd7cddfSDavid du Colombier                if (mask > 1)
1167dd7cddfSDavid du Colombier                   mask >>= 1;
1177dd7cddfSDavid du Colombier                else
1187dd7cddfSDavid du Colombier                {
1197dd7cddfSDavid du Colombier                   mask = 0x80;
1207dd7cddfSDavid du Colombier                   *dp = (png_byte)v;
1217dd7cddfSDavid du Colombier                   dp++;
1227dd7cddfSDavid du Colombier                   v = 0;
1237dd7cddfSDavid du Colombier                }
1247dd7cddfSDavid du Colombier             }
1257dd7cddfSDavid du Colombier             if (mask != 0x80)
1267dd7cddfSDavid du Colombier                *dp = (png_byte)v;
1277dd7cddfSDavid du Colombier             break;
1287dd7cddfSDavid du Colombier          }
1297dd7cddfSDavid du Colombier          case 2:
1307dd7cddfSDavid du Colombier          {
1317dd7cddfSDavid du Colombier             png_bytep sp, dp;
1327dd7cddfSDavid du Colombier             int shift, v;
1337dd7cddfSDavid du Colombier             png_uint_32 i;
134*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier             sp = row;
1377dd7cddfSDavid du Colombier             dp = row;
1387dd7cddfSDavid du Colombier             shift = 6;
1397dd7cddfSDavid du Colombier             v = 0;
140*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
1417dd7cddfSDavid du Colombier             {
1427dd7cddfSDavid du Colombier                png_byte value;
1437dd7cddfSDavid du Colombier 
144*593dc095SDavid du Colombier                value = (png_byte)(*sp & 0x03);
1457dd7cddfSDavid du Colombier                v |= (value << shift);
1467dd7cddfSDavid du Colombier                if (shift == 0)
1477dd7cddfSDavid du Colombier                {
1487dd7cddfSDavid du Colombier                   shift = 6;
1497dd7cddfSDavid du Colombier                   *dp = (png_byte)v;
1507dd7cddfSDavid du Colombier                   dp++;
1517dd7cddfSDavid du Colombier                   v = 0;
1527dd7cddfSDavid du Colombier                }
1537dd7cddfSDavid du Colombier                else
1547dd7cddfSDavid du Colombier                   shift -= 2;
1557dd7cddfSDavid du Colombier                sp++;
1567dd7cddfSDavid du Colombier             }
1577dd7cddfSDavid du Colombier             if (shift != 6)
1587dd7cddfSDavid du Colombier                *dp = (png_byte)v;
1597dd7cddfSDavid du Colombier             break;
1607dd7cddfSDavid du Colombier          }
1617dd7cddfSDavid du Colombier          case 4:
1627dd7cddfSDavid du Colombier          {
1637dd7cddfSDavid du Colombier             png_bytep sp, dp;
1647dd7cddfSDavid du Colombier             int shift, v;
1657dd7cddfSDavid du Colombier             png_uint_32 i;
166*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier             sp = row;
1697dd7cddfSDavid du Colombier             dp = row;
1707dd7cddfSDavid du Colombier             shift = 4;
1717dd7cddfSDavid du Colombier             v = 0;
172*593dc095SDavid du Colombier             for (i = 0; i < row_width; i++)
1737dd7cddfSDavid du Colombier             {
1747dd7cddfSDavid du Colombier                png_byte value;
1757dd7cddfSDavid du Colombier 
176*593dc095SDavid du Colombier                value = (png_byte)(*sp & 0x0f);
1777dd7cddfSDavid du Colombier                v |= (value << shift);
1787dd7cddfSDavid du Colombier 
1797dd7cddfSDavid du Colombier                if (shift == 0)
1807dd7cddfSDavid du Colombier                {
1817dd7cddfSDavid du Colombier                   shift = 4;
1827dd7cddfSDavid du Colombier                   *dp = (png_byte)v;
1837dd7cddfSDavid du Colombier                   dp++;
1847dd7cddfSDavid du Colombier                   v = 0;
1857dd7cddfSDavid du Colombier                }
1867dd7cddfSDavid du Colombier                else
1877dd7cddfSDavid du Colombier                   shift -= 4;
1887dd7cddfSDavid du Colombier 
1897dd7cddfSDavid du Colombier                sp++;
1907dd7cddfSDavid du Colombier             }
1917dd7cddfSDavid du Colombier             if (shift != 4)
1927dd7cddfSDavid du Colombier                *dp = (png_byte)v;
1937dd7cddfSDavid du Colombier             break;
1947dd7cddfSDavid du Colombier          }
1957dd7cddfSDavid du Colombier       }
1967dd7cddfSDavid du Colombier       row_info->bit_depth = (png_byte)bit_depth;
1977dd7cddfSDavid du Colombier       row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
198*593dc095SDavid du Colombier       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
199*593dc095SDavid du Colombier          row_info->width);
2007dd7cddfSDavid du Colombier    }
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier #endif
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier #if defined(PNG_WRITE_SHIFT_SUPPORTED)
2057dd7cddfSDavid du Colombier /* Shift pixel values to take advantage of whole range.  Pass the
2067dd7cddfSDavid du Colombier  * true number of bits in bit_depth.  The row should be packed
2077dd7cddfSDavid du Colombier  * according to row_info->bit_depth.  Thus, if you had a row of
2087dd7cddfSDavid du Colombier  * bit depth 4, but the pixels only had values from 0 to 7, you
2097dd7cddfSDavid du Colombier  * would pass 3 as bit_depth, and this routine would translate the
2107dd7cddfSDavid du Colombier  * data to 0 to 15.
2117dd7cddfSDavid du Colombier  */
212*593dc095SDavid du Colombier void /* PRIVATE */
png_do_shift(png_row_infop row_info,png_bytep row,png_color_8p bit_depth)2137dd7cddfSDavid du Colombier png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
2147dd7cddfSDavid du Colombier {
2157dd7cddfSDavid du Colombier    png_debug(1, "in png_do_shift\n");
2167dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
2177dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL &&
2187dd7cddfSDavid du Colombier #else
2197dd7cddfSDavid du Colombier    if (
2207dd7cddfSDavid du Colombier #endif
2217dd7cddfSDavid du Colombier       row_info->color_type != PNG_COLOR_TYPE_PALETTE)
2227dd7cddfSDavid du Colombier    {
2237dd7cddfSDavid du Colombier       int shift_start[4], shift_dec[4];
224*593dc095SDavid du Colombier       int channels = 0;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
2277dd7cddfSDavid du Colombier       {
2287dd7cddfSDavid du Colombier          shift_start[channels] = row_info->bit_depth - bit_depth->red;
2297dd7cddfSDavid du Colombier          shift_dec[channels] = bit_depth->red;
2307dd7cddfSDavid du Colombier          channels++;
2317dd7cddfSDavid du Colombier          shift_start[channels] = row_info->bit_depth - bit_depth->green;
2327dd7cddfSDavid du Colombier          shift_dec[channels] = bit_depth->green;
2337dd7cddfSDavid du Colombier          channels++;
2347dd7cddfSDavid du Colombier          shift_start[channels] = row_info->bit_depth - bit_depth->blue;
2357dd7cddfSDavid du Colombier          shift_dec[channels] = bit_depth->blue;
2367dd7cddfSDavid du Colombier          channels++;
2377dd7cddfSDavid du Colombier       }
2387dd7cddfSDavid du Colombier       else
2397dd7cddfSDavid du Colombier       {
2407dd7cddfSDavid du Colombier          shift_start[channels] = row_info->bit_depth - bit_depth->gray;
2417dd7cddfSDavid du Colombier          shift_dec[channels] = bit_depth->gray;
2427dd7cddfSDavid du Colombier          channels++;
2437dd7cddfSDavid du Colombier       }
2447dd7cddfSDavid du Colombier       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
2457dd7cddfSDavid du Colombier       {
2467dd7cddfSDavid du Colombier          shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
2477dd7cddfSDavid du Colombier          shift_dec[channels] = bit_depth->alpha;
2487dd7cddfSDavid du Colombier          channels++;
2497dd7cddfSDavid du Colombier       }
2507dd7cddfSDavid du Colombier 
251*593dc095SDavid du Colombier       /* with low row depths, could only be grayscale, so one channel */
2527dd7cddfSDavid du Colombier       if (row_info->bit_depth < 8)
2537dd7cddfSDavid du Colombier       {
254*593dc095SDavid du Colombier          png_bytep bp = row;
2557dd7cddfSDavid du Colombier          png_uint_32 i;
2567dd7cddfSDavid du Colombier          png_byte mask;
257*593dc095SDavid du Colombier          png_uint_32 row_bytes = row_info->rowbytes;
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier          if (bit_depth->gray == 1 && row_info->bit_depth == 2)
2607dd7cddfSDavid du Colombier             mask = 0x55;
2617dd7cddfSDavid du Colombier          else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
2627dd7cddfSDavid du Colombier             mask = 0x11;
2637dd7cddfSDavid du Colombier          else
2647dd7cddfSDavid du Colombier             mask = 0xff;
2657dd7cddfSDavid du Colombier 
266*593dc095SDavid du Colombier          for (i = 0; i < row_bytes; i++, bp++)
2677dd7cddfSDavid du Colombier          {
2687dd7cddfSDavid du Colombier             png_uint_16 v;
2697dd7cddfSDavid du Colombier             int j;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier             v = *bp;
2727dd7cddfSDavid du Colombier             *bp = 0;
2737dd7cddfSDavid du Colombier             for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
2747dd7cddfSDavid du Colombier             {
2757dd7cddfSDavid du Colombier                if (j > 0)
2767dd7cddfSDavid du Colombier                   *bp |= (png_byte)((v << j) & 0xff);
2777dd7cddfSDavid du Colombier                else
2787dd7cddfSDavid du Colombier                   *bp |= (png_byte)((v >> (-j)) & mask);
2797dd7cddfSDavid du Colombier             }
2807dd7cddfSDavid du Colombier          }
2817dd7cddfSDavid du Colombier       }
2827dd7cddfSDavid du Colombier       else if (row_info->bit_depth == 8)
2837dd7cddfSDavid du Colombier       {
284*593dc095SDavid du Colombier          png_bytep bp = row;
2857dd7cddfSDavid du Colombier          png_uint_32 i;
286*593dc095SDavid du Colombier          png_uint_32 istop = channels * row_info->width;
2877dd7cddfSDavid du Colombier 
288*593dc095SDavid du Colombier          for (i = 0; i < istop; i++, bp++)
2897dd7cddfSDavid du Colombier          {
2907dd7cddfSDavid du Colombier 
2917dd7cddfSDavid du Colombier             png_uint_16 v;
2927dd7cddfSDavid du Colombier             int j;
293*593dc095SDavid du Colombier             int c = (int)(i%channels);
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier             v = *bp;
2967dd7cddfSDavid du Colombier             *bp = 0;
2977dd7cddfSDavid du Colombier             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
2987dd7cddfSDavid du Colombier             {
2997dd7cddfSDavid du Colombier                if (j > 0)
3007dd7cddfSDavid du Colombier                   *bp |= (png_byte)((v << j) & 0xff);
3017dd7cddfSDavid du Colombier                else
3027dd7cddfSDavid du Colombier                   *bp |= (png_byte)((v >> (-j)) & 0xff);
3037dd7cddfSDavid du Colombier             }
3047dd7cddfSDavid du Colombier          }
3057dd7cddfSDavid du Colombier       }
3067dd7cddfSDavid du Colombier       else
3077dd7cddfSDavid du Colombier       {
3087dd7cddfSDavid du Colombier          png_bytep bp;
3097dd7cddfSDavid du Colombier          png_uint_32 i;
310*593dc095SDavid du Colombier          png_uint_32 istop = channels * row_info->width;
3117dd7cddfSDavid du Colombier 
312*593dc095SDavid du Colombier          for (bp = row, i = 0; i < istop; i++)
3137dd7cddfSDavid du Colombier          {
314*593dc095SDavid du Colombier             int c = (int)(i%channels);
3157dd7cddfSDavid du Colombier             png_uint_16 value, v;
3167dd7cddfSDavid du Colombier             int j;
3177dd7cddfSDavid du Colombier 
318*593dc095SDavid du Colombier             v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
3197dd7cddfSDavid du Colombier             value = 0;
3207dd7cddfSDavid du Colombier             for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
3217dd7cddfSDavid du Colombier             {
3227dd7cddfSDavid du Colombier                if (j > 0)
3237dd7cddfSDavid du Colombier                   value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
3247dd7cddfSDavid du Colombier                else
3257dd7cddfSDavid du Colombier                   value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
3267dd7cddfSDavid du Colombier             }
327*593dc095SDavid du Colombier             *bp++ = (png_byte)(value >> 8);
328*593dc095SDavid du Colombier             *bp++ = (png_byte)(value & 0xff);
3297dd7cddfSDavid du Colombier          }
3307dd7cddfSDavid du Colombier       }
3317dd7cddfSDavid du Colombier    }
3327dd7cddfSDavid du Colombier }
3337dd7cddfSDavid du Colombier #endif
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
336*593dc095SDavid du Colombier void /* PRIVATE */
png_do_write_swap_alpha(png_row_infop row_info,png_bytep row)3377dd7cddfSDavid du Colombier png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
3387dd7cddfSDavid du Colombier {
3397dd7cddfSDavid du Colombier    png_debug(1, "in png_do_write_swap_alpha\n");
3407dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
3417dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL)
3427dd7cddfSDavid du Colombier #endif
3437dd7cddfSDavid du Colombier    {
3447dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3457dd7cddfSDavid du Colombier       {
3467dd7cddfSDavid du Colombier          /* This converts from ARGB to RGBA */
3477dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
3487dd7cddfSDavid du Colombier          {
3497dd7cddfSDavid du Colombier             png_bytep sp, dp;
3507dd7cddfSDavid du Colombier             png_uint_32 i;
351*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
352*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
3537dd7cddfSDavid du Colombier             {
354*593dc095SDavid du Colombier                png_byte save = *(sp++);
3557dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3567dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3577dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3587dd7cddfSDavid du Colombier                *(dp++) = save;
3597dd7cddfSDavid du Colombier             }
3607dd7cddfSDavid du Colombier          }
3617dd7cddfSDavid du Colombier          /* This converts from AARRGGBB to RRGGBBAA */
3627dd7cddfSDavid du Colombier          else
3637dd7cddfSDavid du Colombier          {
3647dd7cddfSDavid du Colombier             png_bytep sp, dp;
3657dd7cddfSDavid du Colombier             png_uint_32 i;
366*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
3677dd7cddfSDavid du Colombier 
368*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
3697dd7cddfSDavid du Colombier             {
370*593dc095SDavid du Colombier                png_byte save[2];
3717dd7cddfSDavid du Colombier                save[0] = *(sp++);
3727dd7cddfSDavid du Colombier                save[1] = *(sp++);
3737dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3747dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3757dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3767dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3777dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3787dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3797dd7cddfSDavid du Colombier                *(dp++) = save[0];
3807dd7cddfSDavid du Colombier                *(dp++) = save[1];
3817dd7cddfSDavid du Colombier             }
3827dd7cddfSDavid du Colombier          }
3837dd7cddfSDavid du Colombier       }
3847dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3857dd7cddfSDavid du Colombier       {
3867dd7cddfSDavid du Colombier          /* This converts from AG to GA */
3877dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
3887dd7cddfSDavid du Colombier          {
3897dd7cddfSDavid du Colombier             png_bytep sp, dp;
3907dd7cddfSDavid du Colombier             png_uint_32 i;
391*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
3927dd7cddfSDavid du Colombier 
393*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
3947dd7cddfSDavid du Colombier             {
395*593dc095SDavid du Colombier                png_byte save = *(sp++);
3967dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
3977dd7cddfSDavid du Colombier                *(dp++) = save;
3987dd7cddfSDavid du Colombier             }
3997dd7cddfSDavid du Colombier          }
4007dd7cddfSDavid du Colombier          /* This converts from AAGG to GGAA */
4017dd7cddfSDavid du Colombier          else
4027dd7cddfSDavid du Colombier          {
4037dd7cddfSDavid du Colombier             png_bytep sp, dp;
4047dd7cddfSDavid du Colombier             png_uint_32 i;
405*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
4067dd7cddfSDavid du Colombier 
407*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
4087dd7cddfSDavid du Colombier             {
409*593dc095SDavid du Colombier                png_byte save[2];
4107dd7cddfSDavid du Colombier                save[0] = *(sp++);
4117dd7cddfSDavid du Colombier                save[1] = *(sp++);
4127dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4137dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4147dd7cddfSDavid du Colombier                *(dp++) = save[0];
4157dd7cddfSDavid du Colombier                *(dp++) = save[1];
4167dd7cddfSDavid du Colombier             }
4177dd7cddfSDavid du Colombier          }
4187dd7cddfSDavid du Colombier       }
4197dd7cddfSDavid du Colombier    }
4207dd7cddfSDavid du Colombier }
4217dd7cddfSDavid du Colombier #endif
4227dd7cddfSDavid du Colombier 
4237dd7cddfSDavid du Colombier #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
424*593dc095SDavid du Colombier void /* PRIVATE */
png_do_write_invert_alpha(png_row_infop row_info,png_bytep row)4257dd7cddfSDavid du Colombier png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
4267dd7cddfSDavid du Colombier {
4277dd7cddfSDavid du Colombier    png_debug(1, "in png_do_write_invert_alpha\n");
4287dd7cddfSDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
4297dd7cddfSDavid du Colombier    if (row != NULL && row_info != NULL)
4307dd7cddfSDavid du Colombier #endif
4317dd7cddfSDavid du Colombier    {
4327dd7cddfSDavid du Colombier       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4337dd7cddfSDavid du Colombier       {
4347dd7cddfSDavid du Colombier          /* This inverts the alpha channel in RGBA */
4357dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
4367dd7cddfSDavid du Colombier          {
4377dd7cddfSDavid du Colombier             png_bytep sp, dp;
4387dd7cddfSDavid du Colombier             png_uint_32 i;
439*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
440*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
4417dd7cddfSDavid du Colombier             {
4427dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4437dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4447dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
445*593dc095SDavid du Colombier                *(dp++) = (png_byte)(255 - *(sp++));
4467dd7cddfSDavid du Colombier             }
4477dd7cddfSDavid du Colombier          }
4487dd7cddfSDavid du Colombier          /* This inverts the alpha channel in RRGGBBAA */
4497dd7cddfSDavid du Colombier          else
4507dd7cddfSDavid du Colombier          {
4517dd7cddfSDavid du Colombier             png_bytep sp, dp;
4527dd7cddfSDavid du Colombier             png_uint_32 i;
453*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
4547dd7cddfSDavid du Colombier 
455*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
4567dd7cddfSDavid du Colombier             {
4577dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4587dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4597dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4607dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4617dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4627dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
463*593dc095SDavid du Colombier                *(dp++) = (png_byte)(255 - *(sp++));
464*593dc095SDavid du Colombier                *(dp++) = (png_byte)(255 - *(sp++));
4657dd7cddfSDavid du Colombier             }
4667dd7cddfSDavid du Colombier          }
4677dd7cddfSDavid du Colombier       }
4687dd7cddfSDavid du Colombier       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
4697dd7cddfSDavid du Colombier       {
4707dd7cddfSDavid du Colombier          /* This inverts the alpha channel in GA */
4717dd7cddfSDavid du Colombier          if (row_info->bit_depth == 8)
4727dd7cddfSDavid du Colombier          {
4737dd7cddfSDavid du Colombier             png_bytep sp, dp;
4747dd7cddfSDavid du Colombier             png_uint_32 i;
475*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
4767dd7cddfSDavid du Colombier 
477*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
4787dd7cddfSDavid du Colombier             {
4797dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
480*593dc095SDavid du Colombier                *(dp++) = (png_byte)(255 - *(sp++));
4817dd7cddfSDavid du Colombier             }
4827dd7cddfSDavid du Colombier          }
4837dd7cddfSDavid du Colombier          /* This inverts the alpha channel in GGAA */
4847dd7cddfSDavid du Colombier          else
4857dd7cddfSDavid du Colombier          {
4867dd7cddfSDavid du Colombier             png_bytep sp, dp;
4877dd7cddfSDavid du Colombier             png_uint_32 i;
488*593dc095SDavid du Colombier             png_uint_32 row_width = row_info->width;
4897dd7cddfSDavid du Colombier 
490*593dc095SDavid du Colombier             for (i = 0, sp = dp = row; i < row_width; i++)
4917dd7cddfSDavid du Colombier             {
4927dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
4937dd7cddfSDavid du Colombier                *(dp++) = *(sp++);
494*593dc095SDavid du Colombier                *(dp++) = (png_byte)(255 - *(sp++));
495*593dc095SDavid du Colombier                *(dp++) = (png_byte)(255 - *(sp++));
4967dd7cddfSDavid du Colombier             }
4977dd7cddfSDavid du Colombier          }
4987dd7cddfSDavid du Colombier       }
4997dd7cddfSDavid du Colombier    }
5007dd7cddfSDavid du Colombier }
5017dd7cddfSDavid du Colombier #endif
502*593dc095SDavid du Colombier 
503*593dc095SDavid du Colombier #if defined(PNG_MNG_FEATURES_SUPPORTED)
504*593dc095SDavid du Colombier /* undoes intrapixel differencing  */
505*593dc095SDavid du Colombier void /* PRIVATE */
png_do_write_intrapixel(png_row_infop row_info,png_bytep row)506*593dc095SDavid du Colombier png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
507*593dc095SDavid du Colombier {
508*593dc095SDavid du Colombier    png_debug(1, "in png_do_write_intrapixel\n");
509*593dc095SDavid du Colombier    if (
510*593dc095SDavid du Colombier #if defined(PNG_USELESS_TESTS_SUPPORTED)
511*593dc095SDavid du Colombier        row != NULL && row_info != NULL &&
512*593dc095SDavid du Colombier #endif
513*593dc095SDavid du Colombier        (row_info->color_type & PNG_COLOR_MASK_COLOR))
514*593dc095SDavid du Colombier    {
515*593dc095SDavid du Colombier       int bytes_per_pixel;
516*593dc095SDavid du Colombier       png_uint_32 row_width = row_info->width;
517*593dc095SDavid du Colombier       if (row_info->bit_depth == 8)
518*593dc095SDavid du Colombier       {
519*593dc095SDavid du Colombier          png_bytep rp;
520*593dc095SDavid du Colombier          png_uint_32 i;
521*593dc095SDavid du Colombier 
522*593dc095SDavid du Colombier          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
523*593dc095SDavid du Colombier             bytes_per_pixel = 3;
524*593dc095SDavid du Colombier          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
525*593dc095SDavid du Colombier             bytes_per_pixel = 4;
526*593dc095SDavid du Colombier          else
527*593dc095SDavid du Colombier             return;
528*593dc095SDavid du Colombier 
529*593dc095SDavid du Colombier          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
530*593dc095SDavid du Colombier          {
531*593dc095SDavid du Colombier             *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
532*593dc095SDavid du Colombier             *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
533*593dc095SDavid du Colombier          }
534*593dc095SDavid du Colombier       }
535*593dc095SDavid du Colombier       else if (row_info->bit_depth == 16)
536*593dc095SDavid du Colombier       {
537*593dc095SDavid du Colombier          png_bytep rp;
538*593dc095SDavid du Colombier          png_uint_32 i;
539*593dc095SDavid du Colombier 
540*593dc095SDavid du Colombier          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
541*593dc095SDavid du Colombier             bytes_per_pixel = 6;
542*593dc095SDavid du Colombier          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
543*593dc095SDavid du Colombier             bytes_per_pixel = 8;
544*593dc095SDavid du Colombier          else
545*593dc095SDavid du Colombier             return;
546*593dc095SDavid du Colombier 
547*593dc095SDavid du Colombier          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
548*593dc095SDavid du Colombier          {
549*593dc095SDavid du Colombier             png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
550*593dc095SDavid du Colombier             png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
551*593dc095SDavid du Colombier             png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
552*593dc095SDavid du Colombier             png_uint_32 red  = (png_uint_32)((s0-s1) & 0xffffL);
553*593dc095SDavid du Colombier             png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL);
554*593dc095SDavid du Colombier             *(rp  ) = (png_byte)((red >> 8) & 0xff);
555*593dc095SDavid du Colombier             *(rp+1) = (png_byte)(red & 0xff);
556*593dc095SDavid du Colombier             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
557*593dc095SDavid du Colombier             *(rp+5) = (png_byte)(blue & 0xff);
558*593dc095SDavid du Colombier          }
559*593dc095SDavid du Colombier       }
560*593dc095SDavid du Colombier    }
561*593dc095SDavid du Colombier }
562*593dc095SDavid du Colombier #endif /* PNG_MNG_FEATURES_SUPPORTED */
563*593dc095SDavid du Colombier #endif /* PNG_WRITE_SUPPORTED */
564