pngwtran.c 16.9 KB
Newer Older
G
Guy Schalnat 已提交
1

A
Andreas Dilger 已提交
2
/* pngwtran.c - transforms the data in a row for PNG writers
3
 *
4
 * Last changed in libpng 1.5.6 [November 3, 2011]
5
 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 */
G
Guy Schalnat 已提交
13

14
#include "pngpriv.h"
G
Guy Schalnat 已提交
15

16 17
#ifdef PNG_WRITE_SUPPORTED

18
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
19
/* Transform the data according to the user's wishes.  The order of
20 21
 * transformations is significant.
 */
22
void /* PRIVATE */
23
png_do_write_transformations(png_structp png_ptr, png_row_infop row_info)
G
Guy Schalnat 已提交
24
{
25
   png_debug(1, "in png_do_write_transformations");
26

27 28 29
   if (png_ptr == NULL)
      return;

30
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
31
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
32
      if (png_ptr->write_user_transform_fn != NULL)
33
         (*(png_ptr->write_user_transform_fn)) /* User write transform
34
                                                 function */
35 36
             (png_ptr,  /* png_ptr */
             row_info,  /* row_info: */
37 38 39 40 41 42 43
                /*  png_uint_32 width;       width of row */
                /*  png_size_t rowbytes;     number of bytes in row */
                /*  png_byte color_type;     color type of pixels */
                /*  png_byte bit_depth;      bit depth of samples */
                /*  png_byte channels;       number of channels (1-4) */
                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
             png_ptr->row_buf + 1);      /* start of pixel data for row */
44
#endif
45

46
#ifdef PNG_WRITE_FILLER_SUPPORTED
47
   if (png_ptr->transformations & PNG_FILLER)
48
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
49
         !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
G
Guy Schalnat 已提交
50
#endif
51

52
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
53
   if (png_ptr->transformations & PNG_PACKSWAP)
54
      png_do_packswap(row_info, png_ptr->row_buf + 1);
55
#endif
56

57
#ifdef PNG_WRITE_PACK_SUPPORTED
G
Guy Schalnat 已提交
58
   if (png_ptr->transformations & PNG_PACK)
59
      png_do_pack(row_info, png_ptr->row_buf + 1,
60
          (png_uint_32)png_ptr->bit_depth);
G
Guy Schalnat 已提交
61
#endif
62

63
#ifdef PNG_WRITE_SWAP_SUPPORTED
64
   if (png_ptr->transformations & PNG_SWAP_BYTES)
65
      png_do_swap(row_info, png_ptr->row_buf + 1);
66
#endif
67

68
#ifdef PNG_WRITE_SHIFT_SUPPORTED
G
Guy Schalnat 已提交
69
   if (png_ptr->transformations & PNG_SHIFT)
70
      png_do_shift(row_info, png_ptr->row_buf + 1,
71
          &(png_ptr->shift));
G
Guy Schalnat 已提交
72
#endif
73

74
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
75
   if (png_ptr->transformations & PNG_SWAP_ALPHA)
76
      png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
77
#endif
78

79
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
80
   if (png_ptr->transformations & PNG_INVERT_ALPHA)
81
      png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
82
#endif
83

84
#ifdef PNG_WRITE_BGR_SUPPORTED
G
Guy Schalnat 已提交
85
   if (png_ptr->transformations & PNG_BGR)
86
      png_do_bgr(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
87
#endif
88

89
#ifdef PNG_WRITE_INVERT_SUPPORTED
G
Guy Schalnat 已提交
90
   if (png_ptr->transformations & PNG_INVERT_MONO)
91
      png_do_invert(row_info, png_ptr->row_buf + 1);
G
Guy Schalnat 已提交
92
#endif
G
Guy Schalnat 已提交
93 94
}

95
#ifdef PNG_WRITE_PACK_SUPPORTED
96 97 98 99
/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
 * row_info bit depth should be 8 (one pixel per byte).  The channels
 * should be 1 (this only happens on grayscale and paletted images).
 */
100
void /* PRIVATE */
A
Andreas Dilger 已提交
101
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
G
Guy Schalnat 已提交
102
{
103
   png_debug(1, "in png_do_pack");
104

A
Andreas Dilger 已提交
105
   if (row_info->bit_depth == 8 &&
G
Guy Schalnat 已提交
106 107
      row_info->channels == 1)
   {
A
Andreas Dilger 已提交
108
      switch ((int)bit_depth)
G
Guy Schalnat 已提交
109 110 111
      {
         case 1:
         {
A
Andreas Dilger 已提交
112 113
            png_bytep sp, dp;
            int mask, v;
114 115
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
116 117 118 119 120

            sp = row;
            dp = row;
            mask = 0x80;
            v = 0;
121

122
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
123
            {
A
Andreas Dilger 已提交
124
               if (*sp != 0)
G
Guy Schalnat 已提交
125
                  v |= mask;
126

G
Guy Schalnat 已提交
127
               sp++;
128

G
Guy Schalnat 已提交
129 130
               if (mask > 1)
                  mask >>= 1;
131

G
Guy Schalnat 已提交
132 133 134
               else
               {
                  mask = 0x80;
G
Guy Schalnat 已提交
135 136
                  *dp = (png_byte)v;
                  dp++;
G
Guy Schalnat 已提交
137 138 139
                  v = 0;
               }
            }
140

G
Guy Schalnat 已提交
141
            if (mask != 0x80)
G
Guy Schalnat 已提交
142
               *dp = (png_byte)v;
143

G
Guy Schalnat 已提交
144 145
            break;
         }
146

G
Guy Schalnat 已提交
147 148
         case 2:
         {
A
Andreas Dilger 已提交
149 150
            png_bytep sp, dp;
            int shift, v;
151 152
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
153 154 155 156 157

            sp = row;
            dp = row;
            shift = 6;
            v = 0;
158

159
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
160
            {
A
Andreas Dilger 已提交
161 162
               png_byte value;

163
               value = (png_byte)(*sp & 0x03);
G
Guy Schalnat 已提交
164
               v |= (value << shift);
165

G
Guy Schalnat 已提交
166 167 168
               if (shift == 0)
               {
                  shift = 6;
G
Guy Schalnat 已提交
169
                  *dp = (png_byte)v;
G
Guy Schalnat 已提交
170 171 172
                  dp++;
                  v = 0;
               }
173

G
Guy Schalnat 已提交
174 175
               else
                  shift -= 2;
176

G
Guy Schalnat 已提交
177 178
               sp++;
            }
179

G
Guy Schalnat 已提交
180
            if (shift != 6)
G
Guy Schalnat 已提交
181
               *dp = (png_byte)v;
182

G
Guy Schalnat 已提交
183 184
            break;
         }
185

G
Guy Schalnat 已提交
186 187
         case 4:
         {
A
Andreas Dilger 已提交
188 189
            png_bytep sp, dp;
            int shift, v;
190 191
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
192 193 194 195 196

            sp = row;
            dp = row;
            shift = 4;
            v = 0;
197

198
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
199
            {
A
Andreas Dilger 已提交
200 201
               png_byte value;

202
               value = (png_byte)(*sp & 0x0f);
G
Guy Schalnat 已提交
203 204 205 206 207
               v |= (value << shift);

               if (shift == 0)
               {
                  shift = 4;
G
Guy Schalnat 已提交
208
                  *dp = (png_byte)v;
G
Guy Schalnat 已提交
209 210 211
                  dp++;
                  v = 0;
               }
212

G
Guy Schalnat 已提交
213 214 215 216 217
               else
                  shift -= 4;

               sp++;
            }
218

G
Guy Schalnat 已提交
219
            if (shift != 4)
G
Guy Schalnat 已提交
220
               *dp = (png_byte)v;
221

G
Guy Schalnat 已提交
222 223
            break;
         }
224 225 226

         default:
            break;
G
Guy Schalnat 已提交
227
      }
228

A
Andreas Dilger 已提交
229 230
      row_info->bit_depth = (png_byte)bit_depth;
      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
231
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
232
          row_info->width);
G
Guy Schalnat 已提交
233 234
   }
}
G
Guy Schalnat 已提交
235
#endif
G
Guy Schalnat 已提交
236

237
#ifdef PNG_WRITE_SHIFT_SUPPORTED
238 239 240 241 242 243 244
/* Shift pixel values to take advantage of whole range.  Pass the
 * true number of bits in bit_depth.  The row should be packed
 * according to row_info->bit_depth.  Thus, if you had a row of
 * bit depth 4, but the pixels only had values from 0 to 7, you
 * would pass 3 as bit_depth, and this routine would translate the
 * data to 0 to 15.
 */
245
void /* PRIVATE */
246 247
png_do_shift(png_row_infop row_info, png_bytep row,
    png_const_color_8p bit_depth)
G
Guy Schalnat 已提交
248
{
249
   png_debug(1, "in png_do_shift");
250

251
   if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
252 253
   {
      int shift_start[4], shift_dec[4];
254
      int channels = 0;
G
Guy Schalnat 已提交
255 256 257 258 259 260

      if (row_info->color_type & PNG_COLOR_MASK_COLOR)
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->red;
         shift_dec[channels] = bit_depth->red;
         channels++;
261

G
Guy Schalnat 已提交
262 263 264
         shift_start[channels] = row_info->bit_depth - bit_depth->green;
         shift_dec[channels] = bit_depth->green;
         channels++;
265

G
Guy Schalnat 已提交
266 267 268 269
         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
         shift_dec[channels] = bit_depth->blue;
         channels++;
      }
270

G
Guy Schalnat 已提交
271 272 273 274 275 276
      else
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
         shift_dec[channels] = bit_depth->gray;
         channels++;
      }
277

G
Guy Schalnat 已提交
278 279 280 281 282 283 284
      if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
         shift_dec[channels] = bit_depth->alpha;
         channels++;
      }

285
      /* With low row depths, could only be grayscale, so one channel */
G
Guy Schalnat 已提交
286 287
      if (row_info->bit_depth < 8)
      {
288
         png_bytep bp = row;
289
         png_size_t i;
G
Guy Schalnat 已提交
290
         png_byte mask;
291
         png_size_t row_bytes = row_info->rowbytes;
G
Guy Schalnat 已提交
292 293 294

         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
            mask = 0x55;
295

G
Guy Schalnat 已提交
296 297
         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
            mask = 0x11;
298

G
Guy Schalnat 已提交
299 300 301
         else
            mask = 0xff;

302
         for (i = 0; i < row_bytes; i++, bp++)
G
Guy Schalnat 已提交
303
         {
A
Andreas Dilger 已提交
304 305
            png_uint_16 v;
            int j;
G
Guy Schalnat 已提交
306 307 308

            v = *bp;
            *bp = 0;
309

G
Guy Schalnat 已提交
310 311 312 313
            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
            {
               if (j > 0)
                  *bp |= (png_byte)((v << j) & 0xff);
314

G
Guy Schalnat 已提交
315 316 317 318 319
               else
                  *bp |= (png_byte)((v >> (-j)) & mask);
            }
         }
      }
320

G
Guy Schalnat 已提交
321 322
      else if (row_info->bit_depth == 8)
      {
323 324
         png_bytep bp = row;
         png_uint_32 i;
325
         png_uint_32 istop = channels * row_info->width;
G
Guy Schalnat 已提交
326

327
         for (i = 0; i < istop; i++, bp++)
G
Guy Schalnat 已提交
328 329
         {

330 331 332
            png_uint_16 v;
            int j;
            int c = (int)(i%channels);
G
Guy Schalnat 已提交
333

334 335
            v = *bp;
            *bp = 0;
336

337 338 339 340
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
            {
               if (j > 0)
                  *bp |= (png_byte)((v << j) & 0xff);
341

342 343
               else
                  *bp |= (png_byte)((v >> (-j)) & 0xff);
G
Guy Schalnat 已提交
344 345 346
            }
         }
      }
347

G
Guy Schalnat 已提交
348 349
      else
      {
G
Guy Schalnat 已提交
350
         png_bytep bp;
351
         png_uint_32 i;
352
         png_uint_32 istop = channels * row_info->width;
G
Guy Schalnat 已提交
353

354
         for (bp = row, i = 0; i < istop; i++)
G
Guy Schalnat 已提交
355
         {
356 357 358
            int c = (int)(i%channels);
            png_uint_16 value, v;
            int j;
G
Guy Schalnat 已提交
359

360
            v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
361
            value = 0;
362

363
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
G
Guy Schalnat 已提交
364
            {
365 366
               if (j > 0)
                  value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
367

368 369
               else
                  value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
G
Guy Schalnat 已提交
370
            }
371 372
            *bp++ = (png_byte)(value >> 8);
            *bp++ = (png_byte)(value & 0xff);
G
Guy Schalnat 已提交
373 374 375 376
         }
      }
   }
}
G
Guy Schalnat 已提交
377
#endif
G
Guy Schalnat 已提交
378

379
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
380
void /* PRIVATE */
A
Andreas Dilger 已提交
381
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
G
Guy Schalnat 已提交
382
{
383
   png_debug(1, "in png_do_write_swap_alpha");
384

G
Guy Schalnat 已提交
385
   {
A
Andreas Dilger 已提交
386
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
G
Guy Schalnat 已提交
387
      {
A
Andreas Dilger 已提交
388 389
         if (row_info->bit_depth == 8)
         {
390
            /* This converts from ARGB to RGBA */
A
Andreas Dilger 已提交
391
            png_bytep sp, dp;
392 393
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
394

395
            for (i = 0, sp = dp = row; i < row_width; i++)
A
Andreas Dilger 已提交
396
            {
397
               png_byte save = *(sp++);
A
Andreas Dilger 已提交
398 399 400 401 402 403
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save;
            }
         }
404

405
#ifdef PNG_WRITE_16BIT_SUPPORTED
A
Andreas Dilger 已提交
406
         else
G
Guy Schalnat 已提交
407
         {
408
            /* This converts from AARRGGBB to RRGGBBAA */
A
Andreas Dilger 已提交
409
            png_bytep sp, dp;
410 411
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
412

413
            for (i = 0, sp = dp = row; i < row_width; i++)
A
Andreas Dilger 已提交
414
            {
415
               png_byte save[2];
A
Andreas Dilger 已提交
416 417 418 419 420 421 422 423 424 425 426
               save[0] = *(sp++);
               save[1] = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save[0];
               *(dp++) = save[1];
            }
G
Guy Schalnat 已提交
427
         }
428
#endif /* PNG_WRITE_16BIT_SUPPORTED */
G
Guy Schalnat 已提交
429
      }
430

A
Andreas Dilger 已提交
431
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
G
Guy Schalnat 已提交
432
      {
A
Andreas Dilger 已提交
433 434
         if (row_info->bit_depth == 8)
         {
435
            /* This converts from AG to GA */
A
Andreas Dilger 已提交
436 437
            png_bytep sp, dp;
            png_uint_32 i;
438
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
439

440
            for (i = 0, sp = dp = row; i < row_width; i++)
A
Andreas Dilger 已提交
441
            {
442
               png_byte save = *(sp++);
A
Andreas Dilger 已提交
443 444 445 446
               *(dp++) = *(sp++);
               *(dp++) = save;
            }
         }
447

448
#ifdef PNG_WRITE_16BIT_SUPPORTED
A
Andreas Dilger 已提交
449
         else
G
Guy Schalnat 已提交
450
         {
451
            /* This converts from AAGG to GGAA */
A
Andreas Dilger 已提交
452 453
            png_bytep sp, dp;
            png_uint_32 i;
454
            png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
455

456
            for (i = 0, sp = dp = row; i < row_width; i++)
A
Andreas Dilger 已提交
457
            {
458
               png_byte save[2];
A
Andreas Dilger 已提交
459 460 461 462 463 464 465
               save[0] = *(sp++);
               save[1] = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save[0];
               *(dp++) = save[1];
            }
G
Guy Schalnat 已提交
466
         }
467
#endif /* PNG_WRITE_16BIT_SUPPORTED */
G
Guy Schalnat 已提交
468 469 470
      }
   }
}
G
Guy Schalnat 已提交
471
#endif
G
Guy Schalnat 已提交
472

473
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
474
void /* PRIVATE */
475 476
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
477
   png_debug(1, "in png_do_write_invert_alpha");
478

479 480 481 482 483
   {
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
484
            /* This inverts the alpha channel in RGBA */
485
            png_bytep sp, dp;
486 487
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
488

489
            for (i = 0, sp = dp = row; i < row_width; i++)
490
            {
491
               /* Does nothing
492 493 494
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
495 496
               */
               sp+=3; dp = sp;
497
               *(dp++) = (png_byte)(255 - *(sp++));
498 499
            }
         }
500

501
#ifdef PNG_WRITE_16BIT_SUPPORTED
502 503
         else
         {
504
            /* This inverts the alpha channel in RRGGBBAA */
505
            png_bytep sp, dp;
506 507
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
508

509
            for (i = 0, sp = dp = row; i < row_width; i++)
510
            {
511
               /* Does nothing
512 513 514 515 516 517
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
518 519
               */
               sp+=6; dp = sp;
520 521
               *(dp++) = (png_byte)(255 - *(sp++));
               *(dp++) = (png_byte)(255 - *(sp++));
522 523
            }
         }
524
#endif /* PNG_WRITE_16BIT_SUPPORTED */
525
      }
526

527 528 529 530
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
531
            /* This inverts the alpha channel in GA */
532
            png_bytep sp, dp;
533 534
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
535

536
            for (i = 0, sp = dp = row; i < row_width; i++)
537 538
            {
               *(dp++) = *(sp++);
539
               *(dp++) = (png_byte)(255 - *(sp++));
540 541
            }
         }
542

543
#ifdef PNG_WRITE_16BIT_SUPPORTED
544 545
         else
         {
546
            /* This inverts the alpha channel in GGAA */
547
            png_bytep sp, dp;
548 549
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
550

551
            for (i = 0, sp = dp = row; i < row_width; i++)
552
            {
553
               /* Does nothing
554 555
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
556 557
               */
               sp+=2; dp = sp;
558 559
               *(dp++) = (png_byte)(255 - *(sp++));
               *(dp++) = (png_byte)(255 - *(sp++));
560 561
            }
         }
562
#endif /* PNG_WRITE_16BIT_SUPPORTED */
563 564 565 566
      }
   }
}
#endif
567
#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
568

569
#ifdef PNG_MNG_FEATURES_SUPPORTED
570
/* Undoes intrapixel differencing  */
571 572 573
void /* PRIVATE */
png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
{
574
   png_debug(1, "in png_do_write_intrapixel");
575

576
   if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
577 578 579 580 581 582 583 584 585 586
   {
      int bytes_per_pixel;
      png_uint_32 row_width = row_info->width;
      if (row_info->bit_depth == 8)
      {
         png_bytep rp;
         png_uint_32 i;

         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
            bytes_per_pixel = 3;
587

588 589
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 4;
590

591 592 593 594 595
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
596 597
            *(rp)     = (png_byte)((*rp       - *(rp + 1)) & 0xff);
            *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff);
598 599
         }
      }
600

601
#ifdef PNG_WRITE_16BIT_SUPPORTED
602 603 604 605 606 607 608
      else if (row_info->bit_depth == 16)
      {
         png_bytep rp;
         png_uint_32 i;

         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
            bytes_per_pixel = 6;
609

610 611
         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            bytes_per_pixel = 8;
612

613 614 615 616 617
         else
            return;

         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
         {
618 619 620
            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
621 622
            png_uint_32 red  = (png_uint_32)((s0 - s1) & 0xffffL);
            png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
623 624 625 626
            *(rp    ) = (png_byte)((red >> 8) & 0xff);
            *(rp + 1) = (png_byte)(red & 0xff);
            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
            *(rp + 5) = (png_byte)(blue & 0xff);
627 628
         }
      }
629
#endif /* PNG_WRITE_16BIT_SUPPORTED */
630 631 632
   }
}
#endif /* PNG_MNG_FEATURES_SUPPORTED */
633
#endif /* PNG_WRITE_SUPPORTED */