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 /* pngwtran.c - transforms the data in a row for PNG 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.18 [July 23, 2015] 33 * Copyright (c) 1998-2002,2004,2006-2015 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 #ifdef PNG_WRITE_SUPPORTED 45 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED 46 47 #ifdef PNG_WRITE_PACK_SUPPORTED 48 /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The 49 * row_info bit depth should be 8 (one pixel per byte). The channels 50 * should be 1 (this only happens on grayscale and paletted images). 51 */ 52 static void 53 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) 54 { 55 png_debug(1, "in png_do_pack"); 56 57 if (row_info->bit_depth == 8 && 58 row_info->channels == 1) 59 { 60 switch ((int)bit_depth) 61 { 62 case 1: 63 { 64 png_bytep sp, dp; 65 int mask, v; 66 png_uint_32 i; 67 png_uint_32 row_width = row_info->width; 68 69 sp = row; 70 dp = row; 71 mask = 0x80; 72 v = 0; 73 74 for (i = 0; i < row_width; i++) 75 { 76 if (*sp != 0) 77 v |= mask; 78 79 sp++; 80 81 if (mask > 1) 82 mask >>= 1; 83 84 else 85 { 86 mask = 0x80; 87 *dp = (png_byte)v; 88 dp++; 89 v = 0; 90 } 91 } 92 93 if (mask != 0x80) 94 *dp = (png_byte)v; 95 96 break; 97 } 98 99 case 2: 100 { 101 png_bytep sp, dp; 102 unsigned int shift; 103 int v; 104 png_uint_32 i; 105 png_uint_32 row_width = row_info->width; 106 107 sp = row; 108 dp = row; 109 shift = 6; 110 v = 0; 111 112 for (i = 0; i < row_width; i++) 113 { 114 png_byte value; 115 116 value = (png_byte)(*sp & 0x03); 117 v |= (value << shift); 118 119 if (shift == 0) 120 { 121 shift = 6; 122 *dp = (png_byte)v; 123 dp++; 124 v = 0; 125 } 126 127 else 128 shift -= 2; 129 130 sp++; 131 } 132 133 if (shift != 6) 134 *dp = (png_byte)v; 135 136 break; 137 } 138 139 case 4: 140 { 141 png_bytep sp, dp; 142 unsigned int shift; 143 int v; 144 png_uint_32 i; 145 png_uint_32 row_width = row_info->width; 146 147 sp = row; 148 dp = row; 149 shift = 4; 150 v = 0; 151 152 for (i = 0; i < row_width; i++) 153 { 154 png_byte value; 155 156 value = (png_byte)(*sp & 0x0f); 157 v |= (value << shift); 158 159 if (shift == 0) 160 { 161 shift = 4; 162 *dp = (png_byte)v; 163 dp++; 164 v = 0; 165 } 166 167 else 168 shift -= 4; 169 170 sp++; 171 } 172 173 if (shift != 4) 174 *dp = (png_byte)v; 175 176 break; 177 } 178 179 default: 180 break; 181 } 182 183 row_info->bit_depth = (png_byte)bit_depth; 184 row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); 185 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 186 row_info->width); 187 } 188 } 189 #endif 190 191 #ifdef PNG_WRITE_SHIFT_SUPPORTED 192 /* Shift pixel values to take advantage of whole range. Pass the 193 * true number of bits in bit_depth. The row should be packed 194 * according to row_info->bit_depth. Thus, if you had a row of 195 * bit depth 4, but the pixels only had values from 0 to 7, you 196 * would pass 3 as bit_depth, and this routine would translate the 197 * data to 0 to 15. 198 */ 199 static void 200 png_do_shift(png_row_infop row_info, png_bytep row, 201 png_const_color_8p bit_depth) 202 { 203 png_debug(1, "in png_do_shift"); 204 205 if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) 206 { 207 int shift_start[4], shift_dec[4]; 208 int channels = 0; 209 210 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) 211 { 212 shift_start[channels] = row_info->bit_depth - bit_depth->red; 213 shift_dec[channels] = bit_depth->red; 214 channels++; 215 216 shift_start[channels] = row_info->bit_depth - bit_depth->green; 217 shift_dec[channels] = bit_depth->green; 218 channels++; 219 220 shift_start[channels] = row_info->bit_depth - bit_depth->blue; 221 shift_dec[channels] = bit_depth->blue; 222 channels++; 223 } 224 225 else 226 { 227 shift_start[channels] = row_info->bit_depth - bit_depth->gray; 228 shift_dec[channels] = bit_depth->gray; 229 channels++; 230 } 231 232 if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0) 233 { 234 shift_start[channels] = row_info->bit_depth - bit_depth->alpha; 235 shift_dec[channels] = bit_depth->alpha; 236 channels++; 237 } 238 239 /* With low row depths, could only be grayscale, so one channel */ 240 if (row_info->bit_depth < 8) 241 { 242 png_bytep bp = row; 243 png_size_t i; 244 unsigned int mask; 245 png_size_t row_bytes = row_info->rowbytes; 246 247 if (bit_depth->gray == 1 && row_info->bit_depth == 2) 248 mask = 0x55; 249 250 else if (row_info->bit_depth == 4 && bit_depth->gray == 3) 251 mask = 0x11; 252 253 else 254 mask = 0xff; 255 256 for (i = 0; i < row_bytes; i++, bp++) 257 { 258 int j; 259 unsigned int v, out; 260 261 v = *bp; 262 out = 0; 263 264 for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) 265 { 266 if (j > 0) 267 out |= v << j; 268 269 else 270 out |= (v >> (-j)) & mask; 271 } 272 273 *bp = (png_byte)(out & 0xff); 274 } 275 } 276 277 else if (row_info->bit_depth == 8) 278 { 279 png_bytep bp = row; 280 png_uint_32 i; 281 png_uint_32 istop = channels * row_info->width; 282 283 for (i = 0; i < istop; i++, bp++) 284 { 285 286 const unsigned int c = i%channels; 287 int j; 288 unsigned int v, out; 289 290 v = *bp; 291 out = 0; 292 293 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) 294 { 295 if (j > 0) 296 out |= v << j; 297 298 else 299 out |= v >> (-j); 300 } 301 302 *bp = (png_byte)(out & 0xff); 303 } 304 } 305 306 else 307 { 308 png_bytep bp; 309 png_uint_32 i; 310 png_uint_32 istop = channels * row_info->width; 311 312 for (bp = row, i = 0; i < istop; i++) 313 { 314 const unsigned int c = i%channels; 315 int j; 316 unsigned int value, v; 317 318 v = png_get_uint_16(bp); 319 value = 0; 320 321 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) 322 { 323 if (j > 0) 324 value |= v << j; 325 326 else 327 value |= v >> (-j); 328 } 329 *bp++ = (png_byte)((value >> 8) & 0xff); 330 *bp++ = (png_byte)(value & 0xff); 331 } 332 } 333 } 334 } 335 #endif 336 337 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED 338 static void 339 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) 340 { 341 png_debug(1, "in png_do_write_swap_alpha"); 342 343 { 344 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 345 { 346 if (row_info->bit_depth == 8) 347 { 348 /* This converts from ARGB to RGBA */ 349 png_bytep sp, dp; 350 png_uint_32 i; 351 png_uint_32 row_width = row_info->width; 352 353 for (i = 0, sp = dp = row; i < row_width; i++) 354 { 355 png_byte save = *(sp++); 356 *(dp++) = *(sp++); 357 *(dp++) = *(sp++); 358 *(dp++) = *(sp++); 359 *(dp++) = save; 360 } 361 } 362 363 #ifdef PNG_WRITE_16BIT_SUPPORTED 364 else 365 { 366 /* This converts from AARRGGBB to RRGGBBAA */ 367 png_bytep sp, dp; 368 png_uint_32 i; 369 png_uint_32 row_width = row_info->width; 370 371 for (i = 0, sp = dp = row; i < row_width; i++) 372 { 373 png_byte save[2]; 374 save[0] = *(sp++); 375 save[1] = *(sp++); 376 *(dp++) = *(sp++); 377 *(dp++) = *(sp++); 378 *(dp++) = *(sp++); 379 *(dp++) = *(sp++); 380 *(dp++) = *(sp++); 381 *(dp++) = *(sp++); 382 *(dp++) = save[0]; 383 *(dp++) = save[1]; 384 } 385 } 386 #endif /* WRITE_16BIT */ 387 } 388 389 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 390 { 391 if (row_info->bit_depth == 8) 392 { 393 /* This converts from AG to GA */ 394 png_bytep sp, dp; 395 png_uint_32 i; 396 png_uint_32 row_width = row_info->width; 397 398 for (i = 0, sp = dp = row; i < row_width; i++) 399 { 400 png_byte save = *(sp++); 401 *(dp++) = *(sp++); 402 *(dp++) = save; 403 } 404 } 405 406 #ifdef PNG_WRITE_16BIT_SUPPORTED 407 else 408 { 409 /* This converts from AAGG to GGAA */ 410 png_bytep sp, dp; 411 png_uint_32 i; 412 png_uint_32 row_width = row_info->width; 413 414 for (i = 0, sp = dp = row; i < row_width; i++) 415 { 416 png_byte save[2]; 417 save[0] = *(sp++); 418 save[1] = *(sp++); 419 *(dp++) = *(sp++); 420 *(dp++) = *(sp++); 421 *(dp++) = save[0]; 422 *(dp++) = save[1]; 423 } 424 } 425 #endif /* WRITE_16BIT */ 426 } 427 } 428 } 429 #endif 430 431 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 432 static void 433 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) 434 { 435 png_debug(1, "in png_do_write_invert_alpha"); 436 437 { 438 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 439 { 440 if (row_info->bit_depth == 8) 441 { 442 /* This inverts the alpha channel in RGBA */ 443 png_bytep sp, dp; 444 png_uint_32 i; 445 png_uint_32 row_width = row_info->width; 446 447 for (i = 0, sp = dp = row; i < row_width; i++) 448 { 449 /* Does nothing 450 *(dp++) = *(sp++); 451 *(dp++) = *(sp++); 452 *(dp++) = *(sp++); 453 */ 454 sp+=3; dp = sp; 455 *dp = (png_byte)(255 - *(sp++)); 456 } 457 } 458 459 #ifdef PNG_WRITE_16BIT_SUPPORTED 460 else 461 { 462 /* This inverts the alpha channel in RRGGBBAA */ 463 png_bytep sp, dp; 464 png_uint_32 i; 465 png_uint_32 row_width = row_info->width; 466 467 for (i = 0, sp = dp = row; i < row_width; i++) 468 { 469 /* Does nothing 470 *(dp++) = *(sp++); 471 *(dp++) = *(sp++); 472 *(dp++) = *(sp++); 473 *(dp++) = *(sp++); 474 *(dp++) = *(sp++); 475 *(dp++) = *(sp++); 476 */ 477 sp+=6; dp = sp; 478 *(dp++) = (png_byte)(255 - *(sp++)); 479 *dp = (png_byte)(255 - *(sp++)); 480 } 481 } 482 #endif /* WRITE_16BIT */ 483 } 484 485 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 486 { 487 if (row_info->bit_depth == 8) 488 { 489 /* This inverts the alpha channel in GA */ 490 png_bytep sp, dp; 491 png_uint_32 i; 492 png_uint_32 row_width = row_info->width; 493 494 for (i = 0, sp = dp = row; i < row_width; i++) 495 { 496 *(dp++) = *(sp++); 497 *(dp++) = (png_byte)(255 - *(sp++)); 498 } 499 } 500 501 #ifdef PNG_WRITE_16BIT_SUPPORTED 502 else 503 { 504 /* This inverts the alpha channel in GGAA */ 505 png_bytep sp, dp; 506 png_uint_32 i; 507 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 *(dp++) = *(sp++); 513 *(dp++) = *(sp++); 514 */ 515 sp+=2; dp = sp; 516 *(dp++) = (png_byte)(255 - *(sp++)); 517 *dp = (png_byte)(255 - *(sp++)); 518 } 519 } 520 #endif /* WRITE_16BIT */ 521 } 522 } 523 } 524 #endif 525 526 /* Transform the data according to the user's wishes. The order of 527 * transformations is significant. 528 */ 529 void /* PRIVATE */ 530 png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) 531 { 532 png_debug(1, "in png_do_write_transformations"); 533 534 if (png_ptr == NULL) 535 return; 536 537 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 538 if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0) 539 if (png_ptr->write_user_transform_fn != NULL) 540 (*(png_ptr->write_user_transform_fn)) /* User write transform 541 function */ 542 (png_ptr, /* png_ptr */ 543 row_info, /* row_info: */ 544 /* png_uint_32 width; width of row */ 545 /* png_size_t rowbytes; number of bytes in row */ 546 /* png_byte color_type; color type of pixels */ 547 /* png_byte bit_depth; bit depth of samples */ 548 /* png_byte channels; number of channels (1-4) */ 549 /* png_byte pixel_depth; bits per pixel (depth*channels) */ 550 png_ptr->row_buf + 1); /* start of pixel data for row */ 551 #endif 552 553 #ifdef PNG_WRITE_FILLER_SUPPORTED 554 if ((png_ptr->transformations & PNG_FILLER) != 0) 555 png_do_strip_channel(row_info, png_ptr->row_buf + 1, 556 !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); 557 #endif 558 559 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED 560 if ((png_ptr->transformations & PNG_PACKSWAP) != 0) 561 png_do_packswap(row_info, png_ptr->row_buf + 1); 562 #endif 563 564 #ifdef PNG_WRITE_PACK_SUPPORTED 565 if ((png_ptr->transformations & PNG_PACK) != 0) 566 png_do_pack(row_info, png_ptr->row_buf + 1, 567 (png_uint_32)png_ptr->bit_depth); 568 #endif 569 570 #ifdef PNG_WRITE_SWAP_SUPPORTED 571 # ifdef PNG_16BIT_SUPPORTED 572 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0) 573 png_do_swap(row_info, png_ptr->row_buf + 1); 574 # endif 575 #endif 576 577 #ifdef PNG_WRITE_SHIFT_SUPPORTED 578 if ((png_ptr->transformations & PNG_SHIFT) != 0) 579 png_do_shift(row_info, png_ptr->row_buf + 1, 580 &(png_ptr->shift)); 581 #endif 582 583 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED 584 if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0) 585 png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1); 586 #endif 587 588 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 589 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) 590 png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1); 591 #endif 592 593 #ifdef PNG_WRITE_BGR_SUPPORTED 594 if ((png_ptr->transformations & PNG_BGR) != 0) 595 png_do_bgr(row_info, png_ptr->row_buf + 1); 596 #endif 597 598 #ifdef PNG_WRITE_INVERT_SUPPORTED 599 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0) 600 png_do_invert(row_info, png_ptr->row_buf + 1); 601 #endif 602 } 603 #endif /* WRITE_TRANSFORMS */ 604 #endif /* WRITE */