pngwtran.c 16.4 KB
Newer Older
D
duke 已提交
1 2 3 4 5
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
6
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
7
 * particular file as subject to the "Classpath" exception as provided
8
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
20 21 22
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
23 24 25 26 27 28 29 30 31
 */

/* pngwtran.c - transforms the data in a row for PNG writers
 *
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file and, per its terms, should not be removed:
 *
32 33
 * Last changed in libpng 1.6.18 [July 23, 2015]
 * Copyright (c) 1998-2015 Glenn Randers-Pehrson
D
duke 已提交
34 35
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
B
bae 已提交
36 37 38 39
 *
 * This code is released under the libpng license.
 * For conditions of distribution and use, see the disclaimer
 * and license in png.h
D
duke 已提交
40 41
 */

B
bae 已提交
42 43
#include "pngpriv.h"

D
duke 已提交
44
#ifdef PNG_WRITE_SUPPORTED
B
bae 已提交
45
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
D
duke 已提交
46

B
bae 已提交
47
#ifdef PNG_WRITE_PACK_SUPPORTED
D
duke 已提交
48 49 50 51
/* 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).
 */
52
static void
D
duke 已提交
53 54
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
B
bae 已提交
55 56
   png_debug(1, "in png_do_pack");

D
duke 已提交
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
   if (row_info->bit_depth == 8 &&
      row_info->channels == 1)
   {
      switch ((int)bit_depth)
      {
         case 1:
         {
            png_bytep sp, dp;
            int mask, v;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

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

            for (i = 0; i < row_width; i++)
            {
               if (*sp != 0)
                  v |= mask;
B
bae 已提交
78

D
duke 已提交
79
               sp++;
B
bae 已提交
80

D
duke 已提交
81 82
               if (mask > 1)
                  mask >>= 1;
B
bae 已提交
83

D
duke 已提交
84 85 86 87 88 89 90 91
               else
               {
                  mask = 0x80;
                  *dp = (png_byte)v;
                  dp++;
                  v = 0;
               }
            }
B
bae 已提交
92

D
duke 已提交
93 94
            if (mask != 0x80)
               *dp = (png_byte)v;
B
bae 已提交
95

D
duke 已提交
96 97
            break;
         }
B
bae 已提交
98

D
duke 已提交
99 100 101
         case 2:
         {
            png_bytep sp, dp;
102 103
            unsigned int shift;
            int v;
D
duke 已提交
104 105 106 107 108 109 110
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            sp = row;
            dp = row;
            shift = 6;
            v = 0;
B
bae 已提交
111

D
duke 已提交
112 113 114 115 116 117
            for (i = 0; i < row_width; i++)
            {
               png_byte value;

               value = (png_byte)(*sp & 0x03);
               v |= (value << shift);
B
bae 已提交
118

D
duke 已提交
119 120 121 122 123 124 125
               if (shift == 0)
               {
                  shift = 6;
                  *dp = (png_byte)v;
                  dp++;
                  v = 0;
               }
B
bae 已提交
126

D
duke 已提交
127 128
               else
                  shift -= 2;
B
bae 已提交
129

D
duke 已提交
130 131
               sp++;
            }
B
bae 已提交
132

D
duke 已提交
133 134
            if (shift != 6)
               *dp = (png_byte)v;
B
bae 已提交
135

D
duke 已提交
136 137
            break;
         }
B
bae 已提交
138

D
duke 已提交
139 140 141
         case 4:
         {
            png_bytep sp, dp;
142 143
            unsigned int shift;
            int v;
D
duke 已提交
144 145 146 147 148 149 150
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            sp = row;
            dp = row;
            shift = 4;
            v = 0;
B
bae 已提交
151

D
duke 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165
            for (i = 0; i < row_width; i++)
            {
               png_byte value;

               value = (png_byte)(*sp & 0x0f);
               v |= (value << shift);

               if (shift == 0)
               {
                  shift = 4;
                  *dp = (png_byte)v;
                  dp++;
                  v = 0;
               }
B
bae 已提交
166

D
duke 已提交
167 168 169 170 171
               else
                  shift -= 4;

               sp++;
            }
B
bae 已提交
172

D
duke 已提交
173 174
            if (shift != 4)
               *dp = (png_byte)v;
B
bae 已提交
175

D
duke 已提交
176 177
            break;
         }
B
bae 已提交
178 179 180

         default:
            break;
D
duke 已提交
181
      }
B
bae 已提交
182

D
duke 已提交
183 184 185
      row_info->bit_depth = (png_byte)bit_depth;
      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
B
bae 已提交
186
          row_info->width);
D
duke 已提交
187 188 189 190
   }
}
#endif

B
bae 已提交
191
#ifdef PNG_WRITE_SHIFT_SUPPORTED
D
duke 已提交
192 193 194 195 196 197 198
/* 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.
 */
199
static void
B
bae 已提交
200 201
png_do_shift(png_row_infop row_info, png_bytep row,
    png_const_color_8p bit_depth)
D
duke 已提交
202
{
B
bae 已提交
203 204 205
   png_debug(1, "in png_do_shift");

   if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
D
duke 已提交
206 207 208 209
   {
      int shift_start[4], shift_dec[4];
      int channels = 0;

210
      if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
D
duke 已提交
211 212 213 214
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->red;
         shift_dec[channels] = bit_depth->red;
         channels++;
B
bae 已提交
215

D
duke 已提交
216 217 218
         shift_start[channels] = row_info->bit_depth - bit_depth->green;
         shift_dec[channels] = bit_depth->green;
         channels++;
B
bae 已提交
219

D
duke 已提交
220 221 222 223
         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
         shift_dec[channels] = bit_depth->blue;
         channels++;
      }
B
bae 已提交
224

D
duke 已提交
225 226 227 228 229 230
      else
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
         shift_dec[channels] = bit_depth->gray;
         channels++;
      }
B
bae 已提交
231

232
      if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
D
duke 已提交
233 234 235 236 237 238
      {
         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
         shift_dec[channels] = bit_depth->alpha;
         channels++;
      }

B
bae 已提交
239
      /* With low row depths, could only be grayscale, so one channel */
D
duke 已提交
240 241 242
      if (row_info->bit_depth < 8)
      {
         png_bytep bp = row;
B
bae 已提交
243
         png_size_t i;
244
         unsigned int mask;
B
bae 已提交
245
         png_size_t row_bytes = row_info->rowbytes;
D
duke 已提交
246 247 248

         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
            mask = 0x55;
B
bae 已提交
249

D
duke 已提交
250 251
         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
            mask = 0x11;
B
bae 已提交
252

D
duke 已提交
253 254 255 256 257 258
         else
            mask = 0xff;

         for (i = 0; i < row_bytes; i++, bp++)
         {
            int j;
259
            unsigned int v, out;
D
duke 已提交
260 261

            v = *bp;
262
            out = 0;
B
bae 已提交
263

D
duke 已提交
264 265 266
            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
            {
               if (j > 0)
267
                  out |= v << j;
B
bae 已提交
268

D
duke 已提交
269
               else
270
                  out |= (v >> (-j)) & mask;
D
duke 已提交
271
            }
272 273

            *bp = (png_byte)(out & 0xff);
D
duke 已提交
274 275
         }
      }
B
bae 已提交
276

D
duke 已提交
277 278 279 280 281 282 283 284 285
      else if (row_info->bit_depth == 8)
      {
         png_bytep bp = row;
         png_uint_32 i;
         png_uint_32 istop = channels * row_info->width;

         for (i = 0; i < istop; i++, bp++)
         {

286
            const unsigned int c = i%channels;
D
duke 已提交
287
            int j;
288
            unsigned int v, out;
D
duke 已提交
289 290

            v = *bp;
291
            out = 0;
B
bae 已提交
292

D
duke 已提交
293 294 295
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
            {
               if (j > 0)
296
                  out |= v << j;
B
bae 已提交
297

D
duke 已提交
298
               else
299
                  out |= v >> (-j);
D
duke 已提交
300
            }
301 302

            *bp = (png_byte)(out & 0xff);
D
duke 已提交
303 304
         }
      }
B
bae 已提交
305

D
duke 已提交
306 307 308 309 310 311 312 313
      else
      {
         png_bytep bp;
         png_uint_32 i;
         png_uint_32 istop = channels * row_info->width;

         for (bp = row, i = 0; i < istop; i++)
         {
314
            const unsigned int c = i%channels;
D
duke 已提交
315
            int j;
316
            unsigned int value, v;
D
duke 已提交
317

318
            v = png_get_uint_16(bp);
D
duke 已提交
319
            value = 0;
B
bae 已提交
320

D
duke 已提交
321 322 323
            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
            {
               if (j > 0)
324
                  value |= v << j;
B
bae 已提交
325

D
duke 已提交
326
               else
327
                  value |= v >> (-j);
D
duke 已提交
328
            }
329
            *bp++ = (png_byte)((value >> 8) & 0xff);
D
duke 已提交
330 331 332 333 334 335 336
            *bp++ = (png_byte)(value & 0xff);
         }
      }
   }
}
#endif

B
bae 已提交
337
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
338
static void
D
duke 已提交
339 340
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
B
bae 已提交
341 342
   png_debug(1, "in png_do_write_swap_alpha");

D
duke 已提交
343 344 345 346 347
   {
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
B
bae 已提交
348
            /* This converts from ARGB to RGBA */
D
duke 已提交
349 350 351
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
B
bae 已提交
352

D
duke 已提交
353 354 355 356 357 358 359 360 361
            for (i = 0, sp = dp = row; i < row_width; i++)
            {
               png_byte save = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save;
            }
         }
B
bae 已提交
362 363

#ifdef PNG_WRITE_16BIT_SUPPORTED
D
duke 已提交
364 365
         else
         {
B
bae 已提交
366
            /* This converts from AARRGGBB to RRGGBBAA */
D
duke 已提交
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            for (i = 0, sp = dp = row; i < row_width; i++)
            {
               png_byte save[2];
               save[0] = *(sp++);
               save[1] = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save[0];
               *(dp++) = save[1];
            }
         }
386
#endif /* WRITE_16BIT */
D
duke 已提交
387
      }
B
bae 已提交
388

D
duke 已提交
389 390 391 392
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
B
bae 已提交
393
            /* This converts from AG to GA */
D
duke 已提交
394 395 396 397 398 399 400 401 402 403 404
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            for (i = 0, sp = dp = row; i < row_width; i++)
            {
               png_byte save = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save;
            }
         }
B
bae 已提交
405 406

#ifdef PNG_WRITE_16BIT_SUPPORTED
D
duke 已提交
407 408
         else
         {
B
bae 已提交
409
            /* This converts from AAGG to GGAA */
D
duke 已提交
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            for (i = 0, sp = dp = row; i < row_width; i++)
            {
               png_byte save[2];
               save[0] = *(sp++);
               save[1] = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = save[0];
               *(dp++) = save[1];
            }
         }
425
#endif /* WRITE_16BIT */
D
duke 已提交
426 427 428 429 430
      }
   }
}
#endif

B
bae 已提交
431
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
432
static void
D
duke 已提交
433 434
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
B
bae 已提交
435 436
   png_debug(1, "in png_do_write_invert_alpha");

D
duke 已提交
437 438 439 440 441
   {
      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
B
bae 已提交
442
            /* This inverts the alpha channel in RGBA */
D
duke 已提交
443 444 445
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
B
bae 已提交
446

D
duke 已提交
447 448
            for (i = 0, sp = dp = row; i < row_width; i++)
            {
B
bae 已提交
449
               /* Does nothing
D
duke 已提交
450 451 452 453 454
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               */
               sp+=3; dp = sp;
455
               *dp = (png_byte)(255 - *(sp++));
D
duke 已提交
456 457
            }
         }
B
bae 已提交
458 459

#ifdef PNG_WRITE_16BIT_SUPPORTED
D
duke 已提交
460 461
         else
         {
B
bae 已提交
462
            /* This inverts the alpha channel in RRGGBBAA */
D
duke 已提交
463 464 465 466 467 468
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            for (i = 0, sp = dp = row; i < row_width; i++)
            {
B
bae 已提交
469
               /* Does nothing
D
duke 已提交
470 471 472 473 474 475 476 477 478
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               */
               sp+=6; dp = sp;
               *(dp++) = (png_byte)(255 - *(sp++));
479
               *dp     = (png_byte)(255 - *(sp++));
D
duke 已提交
480 481
            }
         }
482
#endif /* WRITE_16BIT */
D
duke 已提交
483
      }
B
bae 已提交
484

D
duke 已提交
485 486 487 488
      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      {
         if (row_info->bit_depth == 8)
         {
B
bae 已提交
489
            /* This inverts the alpha channel in GA */
D
duke 已提交
490 491 492 493 494 495 496 497 498 499
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            for (i = 0, sp = dp = row; i < row_width; i++)
            {
               *(dp++) = *(sp++);
               *(dp++) = (png_byte)(255 - *(sp++));
            }
         }
B
bae 已提交
500 501

#ifdef PNG_WRITE_16BIT_SUPPORTED
D
duke 已提交
502 503
         else
         {
B
bae 已提交
504
            /* This inverts the alpha channel in GGAA */
D
duke 已提交
505 506 507 508 509 510
            png_bytep sp, dp;
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;

            for (i = 0, sp = dp = row; i < row_width; i++)
            {
B
bae 已提交
511
               /* Does nothing
D
duke 已提交
512 513 514 515 516
               *(dp++) = *(sp++);
               *(dp++) = *(sp++);
               */
               sp+=2; dp = sp;
               *(dp++) = (png_byte)(255 - *(sp++));
517
               *dp     = (png_byte)(255 - *(sp++));
D
duke 已提交
518 519
            }
         }
520
#endif /* WRITE_16BIT */
D
duke 已提交
521 522 523 524 525
      }
   }
}
#endif

526 527 528
/* Transform the data according to the user's wishes.  The order of
 * transformations is significant.
 */
D
duke 已提交
529
void /* PRIVATE */
530
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
D
duke 已提交
531
{
532
   png_debug(1, "in png_do_write_transformations");
B
bae 已提交
533

534 535
   if (png_ptr == NULL)
      return;
B
bae 已提交
536

537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
      if (png_ptr->write_user_transform_fn != NULL)
         (*(png_ptr->write_user_transform_fn)) /* User write transform
                                                 function */
             (png_ptr,  /* png_ptr */
             row_info,  /* row_info: */
                /*  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 */
#endif
B
bae 已提交
552

553 554 555 556 557
#ifdef PNG_WRITE_FILLER_SUPPORTED
   if ((png_ptr->transformations & PNG_FILLER) != 0)
      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
         !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
#endif
D
duke 已提交
558

559 560 561 562
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
      png_do_packswap(row_info, png_ptr->row_buf + 1);
#endif
B
bae 已提交
563

564 565 566 567 568
#ifdef PNG_WRITE_PACK_SUPPORTED
   if ((png_ptr->transformations & PNG_PACK) != 0)
      png_do_pack(row_info, png_ptr->row_buf + 1,
          (png_uint_32)png_ptr->bit_depth);
#endif
A
azvegint 已提交
569

570 571 572 573 574 575
#ifdef PNG_WRITE_SWAP_SUPPORTED
#  ifdef PNG_16BIT_SUPPORTED
   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
      png_do_swap(row_info, png_ptr->row_buf + 1);
#  endif
#endif
D
duke 已提交
576

577 578 579 580 581
#ifdef PNG_WRITE_SHIFT_SUPPORTED
   if ((png_ptr->transformations & PNG_SHIFT) != 0)
      png_do_shift(row_info, png_ptr->row_buf + 1,
          &(png_ptr->shift));
#endif
B
bae 已提交
582

583 584 585 586
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
      png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
#endif
B
bae 已提交
587

588 589 590 591
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
      png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
#endif
D
duke 已提交
592

593 594 595 596 597 598 599 600 601
#ifdef PNG_WRITE_BGR_SUPPORTED
   if ((png_ptr->transformations & PNG_BGR) != 0)
      png_do_bgr(row_info, png_ptr->row_buf + 1);
#endif

#ifdef PNG_WRITE_INVERT_SUPPORTED
   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
      png_do_invert(row_info, png_ptr->row_buf + 1);
#endif
D
duke 已提交
602
}
603 604
#endif /* WRITE_TRANSFORMS */
#endif /* WRITE */