Initial revision
[rrdtool.git] / libraries / libpng-1.0.9 / pngtrans.c
1
2 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
3  *
4  * libpng 1.0.9 - January 31, 2001
5  * For conditions of distribution and use, see copyright notice in png.h
6  * Copyright (c) 1998-2001 Glenn Randers-Pehrson
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9  */
10
11 #define PNG_INTERNAL
12 #include "png.h"
13
14 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
15 /* turn on BGR-to-RGB mapping */
16 void PNGAPI
17 png_set_bgr(png_structp png_ptr)
18 {
19    png_debug(1, "in png_set_bgr\n");
20    png_ptr->transformations |= PNG_BGR;
21 }
22 #endif
23
24 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
25 /* turn on 16 bit byte swapping */
26 void PNGAPI
27 png_set_swap(png_structp png_ptr)
28 {
29    png_debug(1, "in png_set_swap\n");
30    if (png_ptr->bit_depth == 16)
31       png_ptr->transformations |= PNG_SWAP_BYTES;
32 }
33 #endif
34
35 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
36 /* turn on pixel packing */
37 void PNGAPI
38 png_set_packing(png_structp png_ptr)
39 {
40    png_debug(1, "in png_set_packing\n");
41    if (png_ptr->bit_depth < 8)
42    {
43       png_ptr->transformations |= PNG_PACK;
44       png_ptr->usr_bit_depth = 8;
45    }
46 }
47 #endif
48
49 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
50 /* turn on packed pixel swapping */
51 void PNGAPI
52 png_set_packswap(png_structp png_ptr)
53 {
54    png_debug(1, "in png_set_packswap\n");
55    if (png_ptr->bit_depth < 8)
56       png_ptr->transformations |= PNG_PACKSWAP;
57 }
58 #endif
59
60 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
61 void PNGAPI
62 png_set_shift(png_structp png_ptr, png_color_8p true_bits)
63 {
64    png_debug(1, "in png_set_shift\n");
65    png_ptr->transformations |= PNG_SHIFT;
66    png_ptr->shift = *true_bits;
67 }
68 #endif
69
70 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
71     defined(PNG_WRITE_INTERLACING_SUPPORTED)
72 int PNGAPI
73 png_set_interlace_handling(png_structp png_ptr)
74 {
75    png_debug(1, "in png_set_interlace handling\n");
76    if (png_ptr->interlaced)
77    {
78       png_ptr->transformations |= PNG_INTERLACE;
79       return (7);
80    }
81
82    return (1);
83 }
84 #endif
85
86 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
87 /* Add a filler byte on read, or remove a filler or alpha byte on write.
88  * The filler type has changed in v0.95 to allow future 2-byte fillers
89  * for 48-bit input data, as well as to avoid problems with some compilers
90  * that don't like bytes as parameters.
91  */
92 void PNGAPI
93 png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
94 {
95    png_debug(1, "in png_set_filler\n");
96    png_ptr->transformations |= PNG_FILLER;
97    png_ptr->filler = (png_byte)filler;
98    if (filler_loc == PNG_FILLER_AFTER)
99       png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
100    else
101       png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
102
103    /* This should probably go in the "do_filler" routine.
104     * I attempted to do that in libpng-1.0.1a but that caused problems
105     * so I restored it in libpng-1.0.2a
106    */
107
108    if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
109    {
110       png_ptr->usr_channels = 4;
111    }
112
113    /* Also I added this in libpng-1.0.2a (what happens when we expand
114     * a less-than-8-bit grayscale to GA? */
115
116    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
117    {
118       png_ptr->usr_channels = 2;
119    }
120 }
121 #endif
122
123 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
124     defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
125 void PNGAPI
126 png_set_swap_alpha(png_structp png_ptr)
127 {
128    png_debug(1, "in png_set_swap_alpha\n");
129    png_ptr->transformations |= PNG_SWAP_ALPHA;
130 }
131 #endif
132
133 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
134     defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
135 void PNGAPI
136 png_set_invert_alpha(png_structp png_ptr)
137 {
138    png_debug(1, "in png_set_invert_alpha\n");
139    png_ptr->transformations |= PNG_INVERT_ALPHA;
140 }
141 #endif
142
143 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
144 void PNGAPI
145 png_set_invert_mono(png_structp png_ptr)
146 {
147    png_debug(1, "in png_set_invert_mono\n");
148    png_ptr->transformations |= PNG_INVERT_MONO;
149 }
150
151 /* invert monochrome grayscale data */
152 void /* PRIVATE */
153 png_do_invert(png_row_infop row_info, png_bytep row)
154 {
155    png_debug(1, "in png_do_invert\n");
156    if (row_info->bit_depth == 1 &&
157 #if defined(PNG_USELESS_TESTS_SUPPORTED)
158        row != NULL && row_info != NULL &&
159 #endif
160        row_info->color_type == PNG_COLOR_TYPE_GRAY)
161    {
162       png_bytep rp = row;
163       png_uint_32 i;
164       png_uint_32 istop = row_info->rowbytes;
165
166       for (i = 0; i < istop; i++)
167       {
168          *rp = (png_byte)(~(*rp));
169          rp++;
170       }
171    }
172 }
173 #endif
174
175 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
176 /* swaps byte order on 16 bit depth images */
177 void /* PRIVATE */
178 png_do_swap(png_row_infop row_info, png_bytep row)
179 {
180    png_debug(1, "in png_do_swap\n");
181    if (
182 #if defined(PNG_USELESS_TESTS_SUPPORTED)
183        row != NULL && row_info != NULL &&
184 #endif
185        row_info->bit_depth == 16)
186    {
187       png_bytep rp = row;
188       png_uint_32 i;
189       png_uint_32 istop= row_info->width * row_info->channels;
190
191       for (i = 0; i < istop; i++, rp += 2)
192       {
193          png_byte t = *rp;
194          *rp = *(rp + 1);
195          *(rp + 1) = t;
196       }
197    }
198 }
199 #endif
200
201 #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
202 static png_byte onebppswaptable[256] = {
203    0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
204    0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
205    0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
206    0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
207    0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
208    0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
209    0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
210    0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
211    0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
212    0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
213    0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
214    0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
215    0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
216    0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
217    0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
218    0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
219    0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
220    0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
221    0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
222    0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
223    0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
224    0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
225    0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
226    0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
227    0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
228    0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
229    0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
230    0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
231    0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
232    0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
233    0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
234    0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
235 };
236
237 static png_byte twobppswaptable[256] = {
238    0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
239    0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
240    0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
241    0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
242    0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
243    0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
244    0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
245    0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
246    0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
247    0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
248    0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
249    0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
250    0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
251    0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
252    0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
253    0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
254    0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
255    0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
256    0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
257    0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
258    0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
259    0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
260    0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
261    0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
262    0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
263    0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
264    0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
265    0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
266    0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
267    0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
268    0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
269    0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
270 };
271
272 static png_byte fourbppswaptable[256] = {
273    0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
274    0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
275    0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
276    0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
277    0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
278    0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
279    0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
280    0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
281    0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
282    0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
283    0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
284    0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
285    0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
286    0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
287    0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
288    0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
289    0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
290    0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
291    0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
292    0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
293    0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
294    0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
295    0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
296    0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
297    0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
298    0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
299    0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
300    0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
301    0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
302    0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
303    0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
304    0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
305 };
306
307 /* swaps pixel packing order within bytes */
308 void /* PRIVATE */
309 png_do_packswap(png_row_infop row_info, png_bytep row)
310 {
311    png_debug(1, "in png_do_packswap\n");
312    if (
313 #if defined(PNG_USELESS_TESTS_SUPPORTED)
314        row != NULL && row_info != NULL &&
315 #endif
316        row_info->bit_depth < 8)
317    {
318       png_bytep rp, end, table;
319
320       end = row + row_info->rowbytes;
321
322       if (row_info->bit_depth == 1)
323          table = onebppswaptable;
324       else if (row_info->bit_depth == 2)
325          table = twobppswaptable;
326       else if (row_info->bit_depth == 4)
327          table = fourbppswaptable;
328       else
329          return;
330
331       for (rp = row; rp < end; rp++)
332          *rp = table[*rp];
333    }
334 }
335 #endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
336
337 #if defined(PNG_WRITE_FILLER_SUPPORTED) || \
338     defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
339 /* remove filler or alpha byte(s) */
340 void /* PRIVATE */
341 png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
342 {
343    png_debug(1, "in png_do_strip_filler\n");
344 #if defined(PNG_USELESS_TESTS_SUPPORTED)
345    if (row != NULL && row_info != NULL)
346 #endif
347    {
348 /*
349       if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
350           row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
351 */
352       png_bytep sp=row;
353       png_bytep dp=row;
354       png_uint_32 row_width=row_info->width;
355       png_uint_32 i;
356
357       if (row_info->channels == 4)
358       {
359          if (row_info->bit_depth == 8)
360          {
361             /* This converts from RGBX or RGBA to RGB */
362             if (flags & PNG_FLAG_FILLER_AFTER)
363             {
364                dp+=3; sp+=4;
365                for (i = 1; i < row_width; i++)
366                {
367                   *dp++ = *sp++;
368                   *dp++ = *sp++;
369                   *dp++ = *sp++;
370                   sp++;
371                }
372             }
373             /* This converts from XRGB or ARGB to RGB */
374             else
375             {
376                for (i = 0; i < row_width; i++)
377                {
378                   sp++;
379                   *dp++ = *sp++;
380                   *dp++ = *sp++;
381                   *dp++ = *sp++;
382                }
383             }
384             row_info->pixel_depth = 24;
385             row_info->rowbytes = row_width * 3;
386          }
387          else /* if (row_info->bit_depth == 16) */
388          {
389             if (flags & PNG_FLAG_FILLER_AFTER)
390             {
391                /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
392                sp += 8; dp += 6;
393                for (i = 1; i < row_width; i++)
394                {
395                   /* This could be (although memcpy is probably slower):
396                   png_memcpy(dp, sp, 6);
397                   sp += 8;
398                   dp += 6;
399                   */
400                   *dp++ = *sp++;
401                   *dp++ = *sp++;
402                   *dp++ = *sp++;
403                   *dp++ = *sp++;
404                   *dp++ = *sp++;
405                   *dp++ = *sp++;
406                   sp += 2;
407                }
408             }
409             else
410             {
411                /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
412                for (i = 0; i < row_width; i++)
413                {
414                   /* This could be (although memcpy is probably slower):
415                   png_memcpy(dp, sp, 6);
416                   sp += 8;
417                   dp += 6;
418                   */
419                   sp+=2;
420                   *dp++ = *sp++;
421                   *dp++ = *sp++;
422                   *dp++ = *sp++;
423                   *dp++ = *sp++;
424                   *dp++ = *sp++;
425                   *dp++ = *sp++;
426                }
427             }
428             row_info->pixel_depth = 48;
429             row_info->rowbytes = row_width * 6;
430          }
431          row_info->channels = 3;
432          row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
433       }
434 /*
435       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
436                row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
437 */
438       else if (row_info->channels == 2)
439       {
440          if (row_info->bit_depth == 8)
441          {
442             /* This converts from GX or GA to G */
443             if (flags & PNG_FLAG_FILLER_AFTER)
444             {
445                for (i = 0; i < row_width; i++)
446                {
447                   *dp++ = *sp++;
448                   sp++;
449                }
450             }
451             /* This converts from XG or AG to G */
452             else
453             {
454                for (i = 0; i < row_width; i++)
455                {
456                   sp++;
457                   *dp++ = *sp++;
458                }
459             }
460             row_info->pixel_depth = 8;
461             row_info->rowbytes = row_width;
462          }
463          else /* if (row_info->bit_depth == 16) */
464          {
465             if (flags & PNG_FLAG_FILLER_AFTER)
466             {
467                /* This converts from GGXX or GGAA to GG */
468                sp += 4; dp += 2;
469                for (i = 1; i < row_width; i++)
470                {
471                   *dp++ = *sp++;
472                   *dp++ = *sp++;
473                   sp += 2;
474                }
475             }
476             else
477             {
478                /* This converts from XXGG or AAGG to GG */
479                for (i = 0; i < row_width; i++)
480                {
481                   sp += 2;
482                   *dp++ = *sp++;
483                   *dp++ = *sp++;
484                }
485             }
486             row_info->pixel_depth = 16;
487             row_info->rowbytes = row_width * 2;
488          }
489          row_info->channels = 1;
490          row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
491       }
492    }
493 }
494 #endif
495
496 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
497 /* swaps red and blue bytes within a pixel */
498 void /* PRIVATE */
499 png_do_bgr(png_row_infop row_info, png_bytep row)
500 {
501    png_debug(1, "in png_do_bgr\n");
502    if (
503 #if defined(PNG_USELESS_TESTS_SUPPORTED)
504        row != NULL && row_info != NULL &&
505 #endif
506        (row_info->color_type & PNG_COLOR_MASK_COLOR))
507    {
508       png_uint_32 row_width = row_info->width;
509       if (row_info->bit_depth == 8)
510       {
511          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
512          {
513             png_bytep rp;
514             png_uint_32 i;
515
516             for (i = 0, rp = row; i < row_width; i++, rp += 3)
517             {
518                png_byte save = *rp;
519                *rp = *(rp + 2);
520                *(rp + 2) = save;
521             }
522          }
523          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
524          {
525             png_bytep rp;
526             png_uint_32 i;
527
528             for (i = 0, rp = row; i < row_width; i++, rp += 4)
529             {
530                png_byte save = *rp;
531                *rp = *(rp + 2);
532                *(rp + 2) = save;
533             }
534          }
535       }
536       else if (row_info->bit_depth == 16)
537       {
538          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
539          {
540             png_bytep rp;
541             png_uint_32 i;
542
543             for (i = 0, rp = row; i < row_width; i++, rp += 6)
544             {
545                png_byte save = *rp;
546                *rp = *(rp + 4);
547                *(rp + 4) = save;
548                save = *(rp + 1);
549                *(rp + 1) = *(rp + 5);
550                *(rp + 5) = save;
551             }
552          }
553          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
554          {
555             png_bytep rp;
556             png_uint_32 i;
557
558             for (i = 0, rp = row; i < row_width; i++, rp += 8)
559             {
560                png_byte save = *rp;
561                *rp = *(rp + 4);
562                *(rp + 4) = save;
563                save = *(rp + 1);
564                *(rp + 1) = *(rp + 5);
565                *(rp + 5) = save;
566             }
567          }
568       }
569    }
570 }
571 #endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
572
573 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
574     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
575     defined(PNG_LEGACY_SUPPORTED)
576 void PNGAPI
577 png_set_user_transform_info(png_structp png_ptr, png_voidp
578    user_transform_ptr, int user_transform_depth, int user_transform_channels)
579 {
580    png_debug(1, "in png_set_user_transform_info\n");
581 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
582    png_ptr->user_transform_ptr = user_transform_ptr;
583    png_ptr->user_transform_depth = (png_byte)user_transform_depth;
584    png_ptr->user_transform_channels = (png_byte)user_transform_channels;
585 #else
586    if(user_transform_ptr || user_transform_depth || user_transform_channels)
587       png_warning(png_ptr,
588         "This version of libpng does not support user transform info");
589 #endif
590 }
591 #endif
592
593 /* This function returns a pointer to the user_transform_ptr associated with
594  * the user transform functions.  The application should free any memory
595  * associated with this pointer before png_write_destroy and png_read_destroy
596  * are called.
597  */
598 png_voidp PNGAPI
599 png_get_user_transform_ptr(png_structp png_ptr)
600 {
601 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
602    return ((png_voidp)png_ptr->user_transform_ptr);
603 #else
604    if(png_ptr)
605      return (NULL);
606    return (NULL);
607 #endif
608 }
609