1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25/* pngtrans.c - transforms the data in a row (used by both readers and writers)
26 *
27 * This file is available under and governed by the GNU General Public
28 * License version 2 only, as published by the Free Software Foundation.
29 * However, the following notice accompanied the original version of this
30 * file and, per its terms, should not be removed:
31 *
32 * Last changed in libpng 1.6.26 [October 20, 2016]
33 * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
34 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
35 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
36 *
37 * This code is released under the libpng license.
38 * For conditions of distribution and use, see the disclaimer
39 * and license in png.h
40 */
41
42#include "pngpriv.h"
43
44#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
45
46#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
47/* Turn on BGR-to-RGB mapping */
48void PNGAPI
49png_set_bgr(png_structrp png_ptr)
50{
51   png_debug(1, "in png_set_bgr");
52
53   if (png_ptr == NULL)
54      return;
55
56   png_ptr->transformations |= PNG_BGR;
57}
58#endif
59
60#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
61/* Turn on 16-bit byte swapping */
62void PNGAPI
63png_set_swap(png_structrp png_ptr)
64{
65   png_debug(1, "in png_set_swap");
66
67   if (png_ptr == NULL)
68      return;
69
70   if (png_ptr->bit_depth == 16)
71      png_ptr->transformations |= PNG_SWAP_BYTES;
72}
73#endif
74
75#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
76/* Turn on pixel packing */
77void PNGAPI
78png_set_packing(png_structrp png_ptr)
79{
80   png_debug(1, "in png_set_packing");
81
82   if (png_ptr == NULL)
83      return;
84
85   if (png_ptr->bit_depth < 8)
86   {
87      png_ptr->transformations |= PNG_PACK;
88#     ifdef PNG_WRITE_SUPPORTED
89         png_ptr->usr_bit_depth = 8;
90#     endif
91   }
92}
93#endif
94
95#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
96/* Turn on packed pixel swapping */
97void PNGAPI
98png_set_packswap(png_structrp png_ptr)
99{
100   png_debug(1, "in png_set_packswap");
101
102   if (png_ptr == NULL)
103      return;
104
105   if (png_ptr->bit_depth < 8)
106      png_ptr->transformations |= PNG_PACKSWAP;
107}
108#endif
109
110#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
111void PNGAPI
112png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
113{
114   png_debug(1, "in png_set_shift");
115
116   if (png_ptr == NULL)
117      return;
118
119   png_ptr->transformations |= PNG_SHIFT;
120   png_ptr->shift = *true_bits;
121}
122#endif
123
124#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
125    defined(PNG_WRITE_INTERLACING_SUPPORTED)
126int PNGAPI
127png_set_interlace_handling(png_structrp png_ptr)
128{
129   png_debug(1, "in png_set_interlace handling");
130
131   if (png_ptr != 0 && png_ptr->interlaced != 0)
132   {
133      png_ptr->transformations |= PNG_INTERLACE;
134      return (7);
135   }
136
137   return (1);
138}
139#endif
140
141#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
142/* Add a filler byte on read, or remove a filler or alpha byte on write.
143 * The filler type has changed in v0.95 to allow future 2-byte fillers
144 * for 48-bit input data, as well as to avoid problems with some compilers
145 * that don't like bytes as parameters.
146 */
147void PNGAPI
148png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
149{
150   png_debug(1, "in png_set_filler");
151
152   if (png_ptr == NULL)
153      return;
154
155   /* In libpng 1.6 it is possible to determine whether this is a read or write
156    * operation and therefore to do more checking here for a valid call.
157    */
158   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
159   {
160#     ifdef PNG_READ_FILLER_SUPPORTED
161         /* On read png_set_filler is always valid, regardless of the base PNG
162          * format, because other transformations can give a format where the
163          * filler code can execute (basically an 8 or 16-bit component RGB or G
164          * format.)
165          *
166          * NOTE: usr_channels is not used by the read code!  (This has led to
167          * confusion in the past.)  The filler is only used in the read code.
168          */
169         png_ptr->filler = (png_uint_16)filler;
170#     else
171         png_app_error(png_ptr, "png_set_filler not supported on read");
172         PNG_UNUSED(filler) /* not used in the write case */
173         return;
174#     endif
175   }
176
177   else /* write */
178   {
179#     ifdef PNG_WRITE_FILLER_SUPPORTED
180         /* On write the usr_channels parameter must be set correctly at the
181          * start to record the number of channels in the app-supplied data.
182          */
183         switch (png_ptr->color_type)
184         {
185            case PNG_COLOR_TYPE_RGB:
186               png_ptr->usr_channels = 4;
187               break;
188
189            case PNG_COLOR_TYPE_GRAY:
190               if (png_ptr->bit_depth >= 8)
191               {
192                  png_ptr->usr_channels = 2;
193                  break;
194               }
195
196               else
197               {
198                  /* There simply isn't any code in libpng to strip out bits
199                   * from bytes when the components are less than a byte in
200                   * size!
201                   */
202                  png_app_error(png_ptr,
203                      "png_set_filler is invalid for"
204                      " low bit depth gray output");
205                  return;
206               }
207
208            default:
209               png_app_error(png_ptr,
210                   "png_set_filler: inappropriate color type");
211               return;
212         }
213#     else
214         png_app_error(png_ptr, "png_set_filler not supported on write");
215         return;
216#     endif
217   }
218
219   /* Here on success - libpng supports the operation, set the transformation
220    * and the flag to say where the filler channel is.
221    */
222   png_ptr->transformations |= PNG_FILLER;
223
224   if (filler_loc == PNG_FILLER_AFTER)
225      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
226
227   else
228      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
229}
230
231/* Added to libpng-1.2.7 */
232void PNGAPI
233png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
234{
235   png_debug(1, "in png_set_add_alpha");
236
237   if (png_ptr == NULL)
238      return;
239
240   png_set_filler(png_ptr, filler, filler_loc);
241   /* The above may fail to do anything. */
242   if ((png_ptr->transformations & PNG_FILLER) != 0)
243      png_ptr->transformations |= PNG_ADD_ALPHA;
244}
245
246#endif
247
248#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
249    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
250void PNGAPI
251png_set_swap_alpha(png_structrp png_ptr)
252{
253   png_debug(1, "in png_set_swap_alpha");
254
255   if (png_ptr == NULL)
256      return;
257
258   png_ptr->transformations |= PNG_SWAP_ALPHA;
259}
260#endif
261
262#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
263    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
264void PNGAPI
265png_set_invert_alpha(png_structrp png_ptr)
266{
267   png_debug(1, "in png_set_invert_alpha");
268
269   if (png_ptr == NULL)
270      return;
271
272   png_ptr->transformations |= PNG_INVERT_ALPHA;
273}
274#endif
275
276#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
277void PNGAPI
278png_set_invert_mono(png_structrp png_ptr)
279{
280   png_debug(1, "in png_set_invert_mono");
281
282   if (png_ptr == NULL)
283      return;
284
285   png_ptr->transformations |= PNG_INVERT_MONO;
286}
287
288/* Invert monochrome grayscale data */
289void /* PRIVATE */
290png_do_invert(png_row_infop row_info, png_bytep row)
291{
292   png_debug(1, "in png_do_invert");
293
294  /* This test removed from libpng version 1.0.13 and 1.2.0:
295   *   if (row_info->bit_depth == 1 &&
296   */
297   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
298   {
299      png_bytep rp = row;
300      png_size_t i;
301      png_size_t istop = row_info->rowbytes;
302
303      for (i = 0; i < istop; i++)
304      {
305         *rp = (png_byte)(~(*rp));
306         rp++;
307      }
308   }
309
310   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
311      row_info->bit_depth == 8)
312   {
313      png_bytep rp = row;
314      png_size_t i;
315      png_size_t istop = row_info->rowbytes;
316
317      for (i = 0; i < istop; i += 2)
318      {
319         *rp = (png_byte)(~(*rp));
320         rp += 2;
321      }
322   }
323
324#ifdef PNG_16BIT_SUPPORTED
325   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
326      row_info->bit_depth == 16)
327   {
328      png_bytep rp = row;
329      png_size_t i;
330      png_size_t istop = row_info->rowbytes;
331
332      for (i = 0; i < istop; i += 4)
333      {
334         *rp = (png_byte)(~(*rp));
335         *(rp + 1) = (png_byte)(~(*(rp + 1)));
336         rp += 4;
337      }
338   }
339#endif
340}
341#endif
342
343#ifdef PNG_16BIT_SUPPORTED
344#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
345/* Swaps byte order on 16-bit depth images */
346void /* PRIVATE */
347png_do_swap(png_row_infop row_info, png_bytep row)
348{
349   png_debug(1, "in png_do_swap");
350
351   if (row_info->bit_depth == 16)
352   {
353      png_bytep rp = row;
354      png_uint_32 i;
355      png_uint_32 istop= row_info->width * row_info->channels;
356
357      for (i = 0; i < istop; i++, rp += 2)
358      {
359#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
360         /* Feature added to libpng-1.6.11 for testing purposes, not
361          * enabled by default.
362          */
363         *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
364#else
365         png_byte t = *rp;
366         *rp = *(rp + 1);
367         *(rp + 1) = t;
368#endif
369      }
370   }
371}
372#endif
373#endif
374
375#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
376static PNG_CONST png_byte onebppswaptable[256] = {
377   0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
378   0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
379   0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
380   0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
381   0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
382   0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
383   0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
384   0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
385   0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
386   0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
387   0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
388   0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
389   0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
390   0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
391   0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
392   0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
393   0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
394   0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
395   0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
396   0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
397   0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
398   0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
399   0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
400   0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
401   0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
402   0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
403   0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
404   0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
405   0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
406   0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
407   0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
408   0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
409};
410
411static PNG_CONST png_byte twobppswaptable[256] = {
412   0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
413   0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
414   0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
415   0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
416   0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
417   0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
418   0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
419   0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
420   0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
421   0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
422   0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
423   0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
424   0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
425   0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
426   0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
427   0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
428   0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
429   0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
430   0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
431   0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
432   0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
433   0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
434   0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
435   0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
436   0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
437   0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
438   0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
439   0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
440   0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
441   0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
442   0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
443   0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
444};
445
446static PNG_CONST png_byte fourbppswaptable[256] = {
447   0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
448   0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
449   0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
450   0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
451   0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
452   0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
453   0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
454   0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
455   0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
456   0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
457   0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
458   0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
459   0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
460   0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
461   0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
462   0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
463   0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
464   0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
465   0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
466   0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
467   0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
468   0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
469   0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
470   0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
471   0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
472   0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
473   0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
474   0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
475   0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
476   0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
477   0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
478   0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
479};
480
481/* Swaps pixel packing order within bytes */
482void /* PRIVATE */
483png_do_packswap(png_row_infop row_info, png_bytep row)
484{
485   png_debug(1, "in png_do_packswap");
486
487   if (row_info->bit_depth < 8)
488   {
489      png_bytep rp;
490      png_const_bytep end, table;
491
492      end = row + row_info->rowbytes;
493
494      if (row_info->bit_depth == 1)
495         table = onebppswaptable;
496
497      else if (row_info->bit_depth == 2)
498         table = twobppswaptable;
499
500      else if (row_info->bit_depth == 4)
501         table = fourbppswaptable;
502
503      else
504         return;
505
506      for (rp = row; rp < end; rp++)
507         *rp = table[*rp];
508   }
509}
510#endif /* PACKSWAP || WRITE_PACKSWAP */
511
512#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
513    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
514/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
515 * somewhat weird combination of flags to determine what to do.  All the calls
516 * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
517 * correct arguments.
518 *
519 * The routine isn't general - the channel must be the channel at the start or
520 * end (not in the middle) of each pixel.
521 */
522void /* PRIVATE */
523png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
524{
525   png_bytep sp = row; /* source pointer */
526   png_bytep dp = row; /* destination pointer */
527   png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
528
529   /* At the start sp will point to the first byte to copy and dp to where
530    * it is copied to.  ep always points just beyond the end of the row, so
531    * the loop simply copies (channels-1) channels until sp reaches ep.
532    *
533    * at_start:        0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
534    *            nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
535    */
536
537   /* GA, GX, XG cases */
538   if (row_info->channels == 2)
539   {
540      if (row_info->bit_depth == 8)
541      {
542         if (at_start != 0) /* Skip initial filler */
543            ++sp;
544         else          /* Skip initial channel and, for sp, the filler */
545            sp += 2, ++dp;
546
547         /* For a 1 pixel wide image there is nothing to do */
548         while (sp < ep)
549            *dp++ = *sp, sp += 2;
550
551         row_info->pixel_depth = 8;
552      }
553
554      else if (row_info->bit_depth == 16)
555      {
556         if (at_start != 0) /* Skip initial filler */
557            sp += 2;
558         else          /* Skip initial channel and, for sp, the filler */
559            sp += 4, dp += 2;
560
561         while (sp < ep)
562            *dp++ = *sp++, *dp++ = *sp, sp += 3;
563
564         row_info->pixel_depth = 16;
565      }
566
567      else
568         return; /* bad bit depth */
569
570      row_info->channels = 1;
571
572      /* Finally fix the color type if it records an alpha channel */
573      if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
574         row_info->color_type = PNG_COLOR_TYPE_GRAY;
575   }
576
577   /* RGBA, RGBX, XRGB cases */
578   else if (row_info->channels == 4)
579   {
580      if (row_info->bit_depth == 8)
581      {
582         if (at_start != 0) /* Skip initial filler */
583            ++sp;
584         else          /* Skip initial channels and, for sp, the filler */
585            sp += 4, dp += 3;
586
587         /* Note that the loop adds 3 to dp and 4 to sp each time. */
588         while (sp < ep)
589            *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
590
591         row_info->pixel_depth = 24;
592      }
593
594      else if (row_info->bit_depth == 16)
595      {
596         if (at_start != 0) /* Skip initial filler */
597            sp += 2;
598         else          /* Skip initial channels and, for sp, the filler */
599            sp += 8, dp += 6;
600
601         while (sp < ep)
602         {
603            /* Copy 6 bytes, skip 2 */
604            *dp++ = *sp++, *dp++ = *sp++;
605            *dp++ = *sp++, *dp++ = *sp++;
606            *dp++ = *sp++, *dp++ = *sp, sp += 3;
607         }
608
609         row_info->pixel_depth = 48;
610      }
611
612      else
613         return; /* bad bit depth */
614
615      row_info->channels = 3;
616
617      /* Finally fix the color type if it records an alpha channel */
618      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
619         row_info->color_type = PNG_COLOR_TYPE_RGB;
620   }
621
622   else
623      return; /* The filler channel has gone already */
624
625   /* Fix the rowbytes value. */
626   row_info->rowbytes = (unsigned int)(dp-row);
627}
628#endif
629
630#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
631/* Swaps red and blue bytes within a pixel */
632void /* PRIVATE */
633png_do_bgr(png_row_infop row_info, png_bytep row)
634{
635   png_debug(1, "in png_do_bgr");
636
637   if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
638   {
639      png_uint_32 row_width = row_info->width;
640      if (row_info->bit_depth == 8)
641      {
642         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
643         {
644            png_bytep rp;
645            png_uint_32 i;
646
647            for (i = 0, rp = row; i < row_width; i++, rp += 3)
648            {
649               png_byte save = *rp;
650               *rp = *(rp + 2);
651               *(rp + 2) = save;
652            }
653         }
654
655         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
656         {
657            png_bytep rp;
658            png_uint_32 i;
659
660            for (i = 0, rp = row; i < row_width; i++, rp += 4)
661            {
662               png_byte save = *rp;
663               *rp = *(rp + 2);
664               *(rp + 2) = save;
665            }
666         }
667      }
668
669#ifdef PNG_16BIT_SUPPORTED
670      else if (row_info->bit_depth == 16)
671      {
672         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
673         {
674            png_bytep rp;
675            png_uint_32 i;
676
677            for (i = 0, rp = row; i < row_width; i++, rp += 6)
678            {
679               png_byte save = *rp;
680               *rp = *(rp + 4);
681               *(rp + 4) = save;
682               save = *(rp + 1);
683               *(rp + 1) = *(rp + 5);
684               *(rp + 5) = save;
685            }
686         }
687
688         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
689         {
690            png_bytep rp;
691            png_uint_32 i;
692
693            for (i = 0, rp = row; i < row_width; i++, rp += 8)
694            {
695               png_byte save = *rp;
696               *rp = *(rp + 4);
697               *(rp + 4) = save;
698               save = *(rp + 1);
699               *(rp + 1) = *(rp + 5);
700               *(rp + 5) = save;
701            }
702         }
703      }
704#endif
705   }
706}
707#endif /* READ_BGR || WRITE_BGR */
708
709#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
710    defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
711/* Added at libpng-1.5.10 */
712void /* PRIVATE */
713png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
714{
715   if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
716      png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
717   {
718      /* Calculations moved outside switch in an attempt to stop different
719       * compiler warnings.  'padding' is in *bits* within the last byte, it is
720       * an 'int' because pixel_depth becomes an 'int' in the expression below,
721       * and this calculation is used because it avoids warnings that other
722       * forms produced on either GCC or MSVC.
723       */
724      int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
725      png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
726
727      switch (row_info->bit_depth)
728      {
729         case 1:
730         {
731            /* in this case, all bytes must be 0 so we don't need
732             * to unpack the pixels except for the rightmost one.
733             */
734            for (; rp > png_ptr->row_buf; rp--)
735            {
736              if ((*rp >> padding) != 0)
737                 png_ptr->num_palette_max = 1;
738              padding = 0;
739            }
740
741            break;
742         }
743
744         case 2:
745         {
746            for (; rp > png_ptr->row_buf; rp--)
747            {
748              int i = ((*rp >> padding) & 0x03);
749
750              if (i > png_ptr->num_palette_max)
751                 png_ptr->num_palette_max = i;
752
753              i = (((*rp >> padding) >> 2) & 0x03);
754
755              if (i > png_ptr->num_palette_max)
756                 png_ptr->num_palette_max = i;
757
758              i = (((*rp >> padding) >> 4) & 0x03);
759
760              if (i > png_ptr->num_palette_max)
761                 png_ptr->num_palette_max = i;
762
763              i = (((*rp >> padding) >> 6) & 0x03);
764
765              if (i > png_ptr->num_palette_max)
766                 png_ptr->num_palette_max = i;
767
768              padding = 0;
769            }
770
771            break;
772         }
773
774         case 4:
775         {
776            for (; rp > png_ptr->row_buf; rp--)
777            {
778              int i = ((*rp >> padding) & 0x0f);
779
780              if (i > png_ptr->num_palette_max)
781                 png_ptr->num_palette_max = i;
782
783              i = (((*rp >> padding) >> 4) & 0x0f);
784
785              if (i > png_ptr->num_palette_max)
786                 png_ptr->num_palette_max = i;
787
788              padding = 0;
789            }
790
791            break;
792         }
793
794         case 8:
795         {
796            for (; rp > png_ptr->row_buf; rp--)
797            {
798               if (*rp > png_ptr->num_palette_max)
799                  png_ptr->num_palette_max = (int) *rp;
800            }
801
802            break;
803         }
804
805         default:
806            break;
807      }
808   }
809}
810#endif /* CHECK_FOR_INVALID_INDEX */
811
812#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
813    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
814#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
815void PNGAPI
816png_set_user_transform_info(png_structrp png_ptr, png_voidp
817   user_transform_ptr, int user_transform_depth, int user_transform_channels)
818{
819   png_debug(1, "in png_set_user_transform_info");
820
821   if (png_ptr == NULL)
822      return;
823
824#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
825   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
826      (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
827   {
828      png_app_error(png_ptr,
829          "info change after png_start_read_image or png_read_update_info");
830      return;
831   }
832#endif
833
834   png_ptr->user_transform_ptr = user_transform_ptr;
835   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
836   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
837}
838#endif
839
840/* This function returns a pointer to the user_transform_ptr associated with
841 * the user transform functions.  The application should free any memory
842 * associated with this pointer before png_write_destroy and png_read_destroy
843 * are called.
844 */
845#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
846png_voidp PNGAPI
847png_get_user_transform_ptr(png_const_structrp png_ptr)
848{
849   if (png_ptr == NULL)
850      return (NULL);
851
852   return png_ptr->user_transform_ptr;
853}
854#endif
855
856#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
857png_uint_32 PNGAPI
858png_get_current_row_number(png_const_structrp png_ptr)
859{
860   /* See the comments in png.h - this is the sub-image row when reading an
861    * interlaced image.
862    */
863   if (png_ptr != NULL)
864      return png_ptr->row_number;
865
866   return PNG_UINT_32_MAX; /* help the app not to fail silently */
867}
868
869png_byte PNGAPI
870png_get_current_pass_number(png_const_structrp png_ptr)
871{
872   if (png_ptr != NULL)
873      return png_ptr->pass;
874   return 8; /* invalid */
875}
876#endif /* USER_TRANSFORM_INFO */
877#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
878#endif /* READ || WRITE */
879