15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* pngwtran.c - transforms the data in a row for PNG writers
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Last changed in libpng 1.2.43 [February 25, 2010]
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 1998-2010 Glenn Randers-Pehrson
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This code is released under the libpng license.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For conditions of distribution and use, see the disclaimer
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and license in png.h
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_INTERNAL
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_NO_PEDANTIC_WARNINGS
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "png.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SUPPORTED
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Transform the data according to the user's wishes.  The order of
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * transformations is significant.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_write_transformations(png_structp png_ptr)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_write_transformations");
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr == NULL)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_USER_TRANSFORM)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (png_ptr->write_user_transform_fn != NULL)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (*(png_ptr->write_user_transform_fn)) /* User write transform
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 function */
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (png_ptr,                    /* png_ptr */
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           &(png_ptr->row_info),       /* row_info:     */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             /*  png_uint_32 width;          width of row */
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             /*  png_uint_32 rowbytes;       number of bytes in row */
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             /*  png_byte color_type;        color type of pixels */
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             /*  png_byte bit_depth;         bit depth of samples */
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             /*  png_byte channels;          number of channels (1-4) */
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           png_ptr->row_buf + 1);      /* start of pixel data for row */
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_FILLER_SUPPORTED
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_FILLER)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_ptr->flags);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_PACKSWAP)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_PACK_SUPPORTED
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_PACK)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (png_uint_32)png_ptr->bit_depth);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SWAP_SUPPORTED
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_SWAP_BYTES)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SHIFT_SUPPORTED
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_SHIFT)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         &(png_ptr->shift));
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_SWAP_ALPHA)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_INVERT_ALPHA)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_BGR_SUPPORTED
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_BGR)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INVERT_SUPPORTED
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (png_ptr->transformations & PNG_INVERT_MONO)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_PACK_SUPPORTED
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * row_info bit depth should be 8 (one pixel per byte).  The channels
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * should be 1 (this only happens on grayscale and paletted images).
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_pack");
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row_info->bit_depth == 8 &&
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->channels == 1)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch ((int)bit_depth)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 1:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int mask, v;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sp = row;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dp = row;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mask = 0x80;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            v = 0;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (*sp != 0)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v |= mask;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp++;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (mask > 1)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  mask >>= 1;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  mask = 0x80;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp = (png_byte)v;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp++;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = 0;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (mask != 0x80)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp = (png_byte)v;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 2:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int shift, v;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sp = row;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dp = row;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            shift = 6;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            v = 0;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte value;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               value = (png_byte)(*sp & 0x03);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               v |= (value << shift);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (shift == 0)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 6;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp = (png_byte)v;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp++;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = 0;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift -= 2;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp++;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (shift != 6)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp = (png_byte)v;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         case 4:
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int shift, v;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sp = row;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dp = row;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            shift = 4;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            v = 0;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0; i < row_width; i++)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte value;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               value = (png_byte)(*sp & 0x0f);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               v |= (value << shift);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (shift == 0)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift = 4;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *dp = (png_byte)v;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  dp++;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  v = 0;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  shift -= 4;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp++;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (shift != 4)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *dp = (png_byte)v;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->bit_depth = (png_byte)bit_depth;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         row_info->width);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SHIFT_SUPPORTED
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Shift pixel values to take advantage of whole range.  Pass the
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * true number of bits in bit_depth.  The row should be packed
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * according to row_info->bit_depth.  Thus, if you had a row of
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * bit depth 4, but the pixels only had values from 0 to 7, you
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * would pass 3 as bit_depth, and this routine would translate the
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * data to 0 to 15.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_shift");
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL &&
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int shift_start[4], shift_dec[4];
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int channels = 0;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_start[channels] = row_info->bit_depth - bit_depth->red;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_dec[channels] = bit_depth->red;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         channels++;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_start[channels] = row_info->bit_depth - bit_depth->green;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_dec[channels] = bit_depth->green;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         channels++;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_dec[channels] = bit_depth->blue;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         channels++;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_dec[channels] = bit_depth->gray;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         channels++;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         shift_dec[channels] = bit_depth->alpha;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         channels++;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* With low row depths, could only be grayscale, so one channel */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->bit_depth < 8)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep bp = row;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_byte mask;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 row_bytes = row_info->rowbytes;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mask = 0x55;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mask = 0x11;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            mask = 0xff;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < row_bytes; i++, bp++)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_16 v;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int j;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            v = *bp;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *bp = 0;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (j > 0)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *bp |= (png_byte)((v << j) & 0xff);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *bp |= (png_byte)((v >> (-j)) & mask);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->bit_depth == 8)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep bp = row;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 istop = channels * row_info->width;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0; i < istop; i++, bp++)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_16 v;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int j;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int c = (int)(i%channels);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            v = *bp;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *bp = 0;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (j > 0)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *bp |= (png_byte)((v << j) & 0xff);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  *bp |= (png_byte)((v >> (-j)) & 0xff);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep bp;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 istop = channels * row_info->width;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (bp = row, i = 0; i < istop; i++)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int c = (int)(i%channels);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_16 value, v;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int j;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            value = 0;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               if (j > 0)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               else
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *bp++ = (png_byte)(value >> 8);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *bp++ = (png_byte)(value & 0xff);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_write_swap_alpha");
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from ARGB to RGBA */
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte save = *(sp++);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = save;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from AARRGGBB to RRGGBBAA */
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte save[2];
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[0] = *(sp++);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[1] = *(sp++);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = save[0];
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = save[1];
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from AG to GA */
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte save = *(sp++);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = save;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This converts from AAGG to GGAA */
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               png_byte save[2];
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[0] = *(sp++);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               save[1] = *(sp++);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = save[0];
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = save[1];
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_write_invert_alpha");
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (row != NULL && row_info != NULL)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in RGBA */
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* Does nothing
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               */
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp+=3; dp = sp;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = (png_byte)(255 - *(sp++));
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in RRGGBBAA */
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* Does nothing
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               */
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp+=6; dp = sp;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = (png_byte)(255 - *(sp++));
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = (png_byte)(255 - *(sp++));
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in GA */
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->bit_depth == 8)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = (png_byte)(255 - *(sp++));
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This inverts the alpha channel in GGAA */
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_bytep sp, dp;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 i;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 row_width = row_info->width;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for (i = 0, sp = dp = row; i < row_width; i++)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               /* Does nothing
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = *(sp++);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               */
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               sp+=2; dp = sp;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = (png_byte)(255 - *(sp++));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               *(dp++) = (png_byte)(255 - *(sp++));
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_MNG_FEATURES_SUPPORTED
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Undoes intrapixel differencing  */
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   png_debug(1, "in png_do_write_intrapixel");
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       row != NULL && row_info != NULL &&
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (row_info->color_type & PNG_COLOR_MASK_COLOR))
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int bytes_per_pixel;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      png_uint_32 row_width = row_info->width;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (row_info->bit_depth == 8)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep rp;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 3;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 4;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp)   = (png_byte)((*rp     - *(rp+1))&0xff);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (row_info->bit_depth == 16)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_bytep rp;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         png_uint_32 i;
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 6;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            bytes_per_pixel = 8;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         else
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 red  = (png_uint_32)((s0 - s1) & 0xffffL);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp  ) = (png_byte)((red >> 8) & 0xff);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+1) = (png_byte)(red & 0xff);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+4) = (png_byte)((blue >> 8) & 0xff);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *(rp+5) = (png_byte)(blue & 0xff);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_MNG_FEATURES_SUPPORTED */
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_WRITE_SUPPORTED */
583