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