|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 00002 /* pngwtran.c - transforms the data in a row for PNG writers 00003 * 00004 * Last changed in libpng 1.2.37 [June 4, 2009] 00005 * Copyright (c) 1998-2009 Glenn Randers-Pehrson 00006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 00007 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 00008 * 00009 * This code is released under the libpng license. 00010 * For conditions of distribution and use, see the disclaimer 00011 * and license in png.h 00012 */ 00013 00014 #define PNG_INTERNAL 00015 #include "png.h" 00016 #ifdef PNG_WRITE_SUPPORTED 00017 00018 /* Transform the data according to the user's wishes. The order of 00019 * transformations is significant. 00020 */ 00021 void /* PRIVATE */ 00022 png_do_write_transformations(png_structp png_ptr) 00023 { 00024 png_debug(1, "in png_do_write_transformations"); 00025 00026 if (png_ptr == NULL) 00027 return; 00028 00029 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 00030 if (png_ptr->transformations & PNG_USER_TRANSFORM) 00031 if (png_ptr->write_user_transform_fn != NULL) 00032 (*(png_ptr->write_user_transform_fn)) /* User write transform function */ 00033 (png_ptr, /* png_ptr */ 00034 &(png_ptr->row_info), /* row_info: */ 00035 /* png_uint_32 width; width of row */ 00036 /* png_uint_32 rowbytes; number of bytes in row */ 00037 /* png_byte color_type; color type of pixels */ 00038 /* png_byte bit_depth; bit depth of samples */ 00039 /* png_byte channels; number of channels (1-4) */ 00040 /* png_byte pixel_depth; bits per pixel (depth*channels) */ 00041 png_ptr->row_buf + 1); /* start of pixel data for row */ 00042 #endif 00043 #if defined(PNG_WRITE_FILLER_SUPPORTED) 00044 if (png_ptr->transformations & PNG_FILLER) 00045 png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, 00046 png_ptr->flags); 00047 #endif 00048 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) 00049 if (png_ptr->transformations & PNG_PACKSWAP) 00050 png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); 00051 #endif 00052 #if defined(PNG_WRITE_PACK_SUPPORTED) 00053 if (png_ptr->transformations & PNG_PACK) 00054 png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, 00055 (png_uint_32)png_ptr->bit_depth); 00056 #endif 00057 #if defined(PNG_WRITE_SWAP_SUPPORTED) 00058 if (png_ptr->transformations & PNG_SWAP_BYTES) 00059 png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); 00060 #endif 00061 #if defined(PNG_WRITE_SHIFT_SUPPORTED) 00062 if (png_ptr->transformations & PNG_SHIFT) 00063 png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, 00064 &(png_ptr->shift)); 00065 #endif 00066 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) 00067 if (png_ptr->transformations & PNG_SWAP_ALPHA) 00068 png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 00069 #endif 00070 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) 00071 if (png_ptr->transformations & PNG_INVERT_ALPHA) 00072 png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); 00073 #endif 00074 #if defined(PNG_WRITE_BGR_SUPPORTED) 00075 if (png_ptr->transformations & PNG_BGR) 00076 png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); 00077 #endif 00078 #if defined(PNG_WRITE_INVERT_SUPPORTED) 00079 if (png_ptr->transformations & PNG_INVERT_MONO) 00080 png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); 00081 #endif 00082 } 00083 00084 #if defined(PNG_WRITE_PACK_SUPPORTED) 00085 /* Pack pixels into bytes. Pass the true bit depth in bit_depth. The 00086 * row_info bit depth should be 8 (one pixel per byte). The channels 00087 * should be 1 (this only happens on grayscale and paletted images). 00088 */ 00089 void /* PRIVATE */ 00090 png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) 00091 { 00092 png_debug(1, "in png_do_pack"); 00093 if (row_info->bit_depth == 8 && 00094 #if defined(PNG_USELESS_TESTS_SUPPORTED) 00095 row != NULL && row_info != NULL && 00096 #endif 00097 row_info->channels == 1) 00098 { 00099 switch ((int)bit_depth) 00100 { 00101 case 1: 00102 { 00103 png_bytep sp, dp; 00104 int mask, v; 00105 png_uint_32 i; 00106 png_uint_32 row_width = row_info->width; 00107 00108 sp = row; 00109 dp = row; 00110 mask = 0x80; 00111 v = 0; 00112 00113 for (i = 0; i < row_width; i++) 00114 { 00115 if (*sp != 0) 00116 v |= mask; 00117 sp++; 00118 if (mask > 1) 00119 mask >>= 1; 00120 else 00121 { 00122 mask = 0x80; 00123 *dp = (png_byte)v; 00124 dp++; 00125 v = 0; 00126 } 00127 } 00128 if (mask != 0x80) 00129 *dp = (png_byte)v; 00130 break; 00131 } 00132 case 2: 00133 { 00134 png_bytep sp, dp; 00135 int shift, v; 00136 png_uint_32 i; 00137 png_uint_32 row_width = row_info->width; 00138 00139 sp = row; 00140 dp = row; 00141 shift = 6; 00142 v = 0; 00143 for (i = 0; i < row_width; i++) 00144 { 00145 png_byte value; 00146 00147 value = (png_byte)(*sp & 0x03); 00148 v |= (value << shift); 00149 if (shift == 0) 00150 { 00151 shift = 6; 00152 *dp = (png_byte)v; 00153 dp++; 00154 v = 0; 00155 } 00156 else 00157 shift -= 2; 00158 sp++; 00159 } 00160 if (shift != 6) 00161 *dp = (png_byte)v; 00162 break; 00163 } 00164 case 4: 00165 { 00166 png_bytep sp, dp; 00167 int shift, v; 00168 png_uint_32 i; 00169 png_uint_32 row_width = row_info->width; 00170 00171 sp = row; 00172 dp = row; 00173 shift = 4; 00174 v = 0; 00175 for (i = 0; i < row_width; i++) 00176 { 00177 png_byte value; 00178 00179 value = (png_byte)(*sp & 0x0f); 00180 v |= (value << shift); 00181 00182 if (shift == 0) 00183 { 00184 shift = 4; 00185 *dp = (png_byte)v; 00186 dp++; 00187 v = 0; 00188 } 00189 else 00190 shift -= 4; 00191 00192 sp++; 00193 } 00194 if (shift != 4) 00195 *dp = (png_byte)v; 00196 break; 00197 } 00198 } 00199 row_info->bit_depth = (png_byte)bit_depth; 00200 row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); 00201 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 00202 row_info->width); 00203 } 00204 } 00205 #endif 00206 00207 #if defined(PNG_WRITE_SHIFT_SUPPORTED) 00208 /* Shift pixel values to take advantage of whole range. Pass the 00209 * true number of bits in bit_depth. The row should be packed 00210 * according to row_info->bit_depth. Thus, if you had a row of 00211 * bit depth 4, but the pixels only had values from 0 to 7, you 00212 * would pass 3 as bit_depth, and this routine would translate the 00213 * data to 0 to 15. 00214 */ 00215 void /* PRIVATE */ 00216 png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) 00217 { 00218 png_debug(1, "in png_do_shift"); 00219 #if defined(PNG_USELESS_TESTS_SUPPORTED) 00220 if (row != NULL && row_info != NULL && 00221 #else 00222 if ( 00223 #endif 00224 row_info->color_type != PNG_COLOR_TYPE_PALETTE) 00225 { 00226 int shift_start[4], shift_dec[4]; 00227 int channels = 0; 00228 00229 if (row_info->color_type & PNG_COLOR_MASK_COLOR) 00230 { 00231 shift_start[channels] = row_info->bit_depth - bit_depth->red; 00232 shift_dec[channels] = bit_depth->red; 00233 channels++; 00234 shift_start[channels] = row_info->bit_depth - bit_depth->green; 00235 shift_dec[channels] = bit_depth->green; 00236 channels++; 00237 shift_start[channels] = row_info->bit_depth - bit_depth->blue; 00238 shift_dec[channels] = bit_depth->blue; 00239 channels++; 00240 } 00241 else 00242 { 00243 shift_start[channels] = row_info->bit_depth - bit_depth->gray; 00244 shift_dec[channels] = bit_depth->gray; 00245 channels++; 00246 } 00247 if (row_info->color_type & PNG_COLOR_MASK_ALPHA) 00248 { 00249 shift_start[channels] = row_info->bit_depth - bit_depth->alpha; 00250 shift_dec[channels] = bit_depth->alpha; 00251 channels++; 00252 } 00253 00254 /* With low row depths, could only be grayscale, so one channel */ 00255 if (row_info->bit_depth < 8) 00256 { 00257 png_bytep bp = row; 00258 png_uint_32 i; 00259 png_byte mask; 00260 png_uint_32 row_bytes = row_info->rowbytes; 00261 00262 if (bit_depth->gray == 1 && row_info->bit_depth == 2) 00263 mask = 0x55; 00264 else if (row_info->bit_depth == 4 && bit_depth->gray == 3) 00265 mask = 0x11; 00266 else 00267 mask = 0xff; 00268 00269 for (i = 0; i < row_bytes; i++, bp++) 00270 { 00271 png_uint_16 v; 00272 int j; 00273 00274 v = *bp; 00275 *bp = 0; 00276 for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) 00277 { 00278 if (j > 0) 00279 *bp |= (png_byte)((v << j) & 0xff); 00280 else 00281 *bp |= (png_byte)((v >> (-j)) & mask); 00282 } 00283 } 00284 } 00285 else if (row_info->bit_depth == 8) 00286 { 00287 png_bytep bp = row; 00288 png_uint_32 i; 00289 png_uint_32 istop = channels * row_info->width; 00290 00291 for (i = 0; i < istop; i++, bp++) 00292 { 00293 00294 png_uint_16 v; 00295 int j; 00296 int c = (int)(i%channels); 00297 00298 v = *bp; 00299 *bp = 0; 00300 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) 00301 { 00302 if (j > 0) 00303 *bp |= (png_byte)((v << j) & 0xff); 00304 else 00305 *bp |= (png_byte)((v >> (-j)) & 0xff); 00306 } 00307 } 00308 } 00309 else 00310 { 00311 png_bytep bp; 00312 png_uint_32 i; 00313 png_uint_32 istop = channels * row_info->width; 00314 00315 for (bp = row, i = 0; i < istop; i++) 00316 { 00317 int c = (int)(i%channels); 00318 png_uint_16 value, v; 00319 int j; 00320 00321 v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); 00322 value = 0; 00323 for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) 00324 { 00325 if (j > 0) 00326 value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); 00327 else 00328 value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); 00329 } 00330 *bp++ = (png_byte)(value >> 8); 00331 *bp++ = (png_byte)(value & 0xff); 00332 } 00333 } 00334 } 00335 } 00336 #endif 00337 00338 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) 00339 void /* PRIVATE */ 00340 png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) 00341 { 00342 png_debug(1, "in png_do_write_swap_alpha"); 00343 #if defined(PNG_USELESS_TESTS_SUPPORTED) 00344 if (row != NULL && row_info != NULL) 00345 #endif 00346 { 00347 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 00348 { 00349 /* This converts from ARGB to RGBA */ 00350 if (row_info->bit_depth == 8) 00351 { 00352 png_bytep sp, dp; 00353 png_uint_32 i; 00354 png_uint_32 row_width = row_info->width; 00355 for (i = 0, sp = dp = row; i < row_width; i++) 00356 { 00357 png_byte save = *(sp++); 00358 *(dp++) = *(sp++); 00359 *(dp++) = *(sp++); 00360 *(dp++) = *(sp++); 00361 *(dp++) = save; 00362 } 00363 } 00364 /* This converts from AARRGGBB to RRGGBBAA */ 00365 else 00366 { 00367 png_bytep sp, dp; 00368 png_uint_32 i; 00369 png_uint_32 row_width = row_info->width; 00370 00371 for (i = 0, sp = dp = row; i < row_width; i++) 00372 { 00373 png_byte save[2]; 00374 save[0] = *(sp++); 00375 save[1] = *(sp++); 00376 *(dp++) = *(sp++); 00377 *(dp++) = *(sp++); 00378 *(dp++) = *(sp++); 00379 *(dp++) = *(sp++); 00380 *(dp++) = *(sp++); 00381 *(dp++) = *(sp++); 00382 *(dp++) = save[0]; 00383 *(dp++) = save[1]; 00384 } 00385 } 00386 } 00387 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 00388 { 00389 /* This converts from AG to GA */ 00390 if (row_info->bit_depth == 8) 00391 { 00392 png_bytep sp, dp; 00393 png_uint_32 i; 00394 png_uint_32 row_width = row_info->width; 00395 00396 for (i = 0, sp = dp = row; i < row_width; i++) 00397 { 00398 png_byte save = *(sp++); 00399 *(dp++) = *(sp++); 00400 *(dp++) = save; 00401 } 00402 } 00403 /* This converts from AAGG to GGAA */ 00404 else 00405 { 00406 png_bytep sp, dp; 00407 png_uint_32 i; 00408 png_uint_32 row_width = row_info->width; 00409 00410 for (i = 0, sp = dp = row; i < row_width; i++) 00411 { 00412 png_byte save[2]; 00413 save[0] = *(sp++); 00414 save[1] = *(sp++); 00415 *(dp++) = *(sp++); 00416 *(dp++) = *(sp++); 00417 *(dp++) = save[0]; 00418 *(dp++) = save[1]; 00419 } 00420 } 00421 } 00422 } 00423 } 00424 #endif 00425 00426 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) 00427 void /* PRIVATE */ 00428 png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) 00429 { 00430 png_debug(1, "in png_do_write_invert_alpha"); 00431 #if defined(PNG_USELESS_TESTS_SUPPORTED) 00432 if (row != NULL && row_info != NULL) 00433 #endif 00434 { 00435 if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 00436 { 00437 /* This inverts the alpha channel in RGBA */ 00438 if (row_info->bit_depth == 8) 00439 { 00440 png_bytep sp, dp; 00441 png_uint_32 i; 00442 png_uint_32 row_width = row_info->width; 00443 for (i = 0, sp = dp = row; i < row_width; i++) 00444 { 00445 /* Does nothing 00446 *(dp++) = *(sp++); 00447 *(dp++) = *(sp++); 00448 *(dp++) = *(sp++); 00449 */ 00450 sp+=3; dp = sp; 00451 *(dp++) = (png_byte)(255 - *(sp++)); 00452 } 00453 } 00454 /* This inverts the alpha channel in RRGGBBAA */ 00455 else 00456 { 00457 png_bytep sp, dp; 00458 png_uint_32 i; 00459 png_uint_32 row_width = row_info->width; 00460 00461 for (i = 0, sp = dp = row; i < row_width; i++) 00462 { 00463 /* Does nothing 00464 *(dp++) = *(sp++); 00465 *(dp++) = *(sp++); 00466 *(dp++) = *(sp++); 00467 *(dp++) = *(sp++); 00468 *(dp++) = *(sp++); 00469 *(dp++) = *(sp++); 00470 */ 00471 sp+=6; dp = sp; 00472 *(dp++) = (png_byte)(255 - *(sp++)); 00473 *(dp++) = (png_byte)(255 - *(sp++)); 00474 } 00475 } 00476 } 00477 else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 00478 { 00479 /* This inverts the alpha channel in GA */ 00480 if (row_info->bit_depth == 8) 00481 { 00482 png_bytep sp, dp; 00483 png_uint_32 i; 00484 png_uint_32 row_width = row_info->width; 00485 00486 for (i = 0, sp = dp = row; i < row_width; i++) 00487 { 00488 *(dp++) = *(sp++); 00489 *(dp++) = (png_byte)(255 - *(sp++)); 00490 } 00491 } 00492 /* This inverts the alpha channel in GGAA */ 00493 else 00494 { 00495 png_bytep sp, dp; 00496 png_uint_32 i; 00497 png_uint_32 row_width = row_info->width; 00498 00499 for (i = 0, sp = dp = row; i < row_width; i++) 00500 { 00501 /* Does nothing 00502 *(dp++) = *(sp++); 00503 *(dp++) = *(sp++); 00504 */ 00505 sp+=2; dp = sp; 00506 *(dp++) = (png_byte)(255 - *(sp++)); 00507 *(dp++) = (png_byte)(255 - *(sp++)); 00508 } 00509 } 00510 } 00511 } 00512 } 00513 #endif 00514 00515 #if defined(PNG_MNG_FEATURES_SUPPORTED) 00516 /* Undoes intrapixel differencing */ 00517 void /* PRIVATE */ 00518 png_do_write_intrapixel(png_row_infop row_info, png_bytep row) 00519 { 00520 png_debug(1, "in png_do_write_intrapixel"); 00521 if ( 00522 #if defined(PNG_USELESS_TESTS_SUPPORTED) 00523 row != NULL && row_info != NULL && 00524 #endif 00525 (row_info->color_type & PNG_COLOR_MASK_COLOR)) 00526 { 00527 int bytes_per_pixel; 00528 png_uint_32 row_width = row_info->width; 00529 if (row_info->bit_depth == 8) 00530 { 00531 png_bytep rp; 00532 png_uint_32 i; 00533 00534 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 00535 bytes_per_pixel = 3; 00536 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 00537 bytes_per_pixel = 4; 00538 else 00539 return; 00540 00541 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 00542 { 00543 *(rp) = (png_byte)((*rp - *(rp+1))&0xff); 00544 *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff); 00545 } 00546 } 00547 else if (row_info->bit_depth == 16) 00548 { 00549 png_bytep rp; 00550 png_uint_32 i; 00551 00552 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 00553 bytes_per_pixel = 6; 00554 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 00555 bytes_per_pixel = 8; 00556 else 00557 return; 00558 00559 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 00560 { 00561 png_uint_32 s0 = (*(rp ) << 8) | *(rp+1); 00562 png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3); 00563 png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5); 00564 png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); 00565 png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); 00566 *(rp ) = (png_byte)((red >> 8) & 0xff); 00567 *(rp+1) = (png_byte)(red & 0xff); 00568 *(rp+4) = (png_byte)((blue >> 8) & 0xff); 00569 *(rp+5) = (png_byte)(blue & 0xff); 00570 } 00571 } 00572 } 00573 } 00574 #endif /* PNG_MNG_FEATURES_SUPPORTED */ 00575 #endif /* PNG_WRITE_SUPPORTED */