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