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