📄 pngrtran.c
字号:
png_size_t num_entries = ((png_size_t)1 << total_bits); png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr, (png_uint_32)(num_entries * sizeof (png_byte))); png_memset(png_ptr->palette_lookup, 0, num_entries * sizeof (png_byte)); distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * sizeof(png_byte))); png_memset(distance, 0xff, num_entries * sizeof(png_byte)); for (i = 0; i < num_palette; i++) { int ir, ig, ib; int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); for (ir = 0; ir < num_red; ir++) { int dr = abs(ir - r); int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS)); for (ig = 0; ig < num_green; ig++) { int dg = abs(ig - g); int dt = dr + dg; int dm = ((dr > dg) ? dr : dg); int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); for (ib = 0; ib < num_blue; ib++) { int d_index = index_g | ib; int db = abs(ib - b); int dmax = ((dm > db) ? dm : db); int d = dmax + dt + db; if (d < (int)distance[d_index]) { distance[d_index] = (png_byte)d; png_ptr->palette_lookup[d_index] = (png_byte)i; } } } } } png_free(png_ptr, distance); }}#endif#if defined(PNG_READ_GAMMA_SUPPORTED)/* Transform the image from the file_gamma to the screen_gamma. We * only do transformations on images where the file_gamma and screen_gamma * are not close reciprocals, otherwise it slows things down slightly, and * also needlessly introduces small errors. */voidpng_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma){ png_debug(1, "in png_set_gamma\n"); if (fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) png_ptr->transformations |= PNG_GAMMA; png_ptr->gamma = (float)file_gamma; png_ptr->screen_gamma = (float)scrn_gamma;}#endif#if defined(PNG_READ_EXPAND_SUPPORTED)/* Expand paletted images to rgb, expand grayscale images of * less than 8 bit depth to 8 bit depth, and expand tRNS chunks * to alpha channels. */voidpng_set_expand(png_structp png_ptr){ png_debug(1, "in png_set_expand\n"); png_ptr->transformations |= PNG_EXPAND;}#endif#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)voidpng_set_gray_to_rgb(png_structp png_ptr){ png_debug(1, "in png_set_gray_to_rgb\n"); png_ptr->transformations |= PNG_GRAY_TO_RGB;}#endif#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)/* Convert a RGB image to a grayscale of the given width. This would * allow us, for example, to convert a 24 bpp RGB image into an 8 or * 16 bpp grayscale image. (Not yet implemented.) */voidpng_set_rgb_to_gray(png_structp png_ptr, int gray_bits){ png_debug(1, "in png_set_rgb_to_gray\n"); png_ptr->transformations |= PNG_RGB_TO_GRAY; /* Need to do something with gray_bits here. */ png_warning(png_ptr, "RGB to GRAY transformation is not yet implemented.");}#endif#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)voidpng_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr read_user_transform_fn){ png_debug(1, "in png_set_read_user_transform_fn\n"); png_ptr->transformations |= PNG_USER_TRANSFORM; png_ptr->read_user_transform_fn = read_user_transform_fn;}#endif/* Initialize everything needed for the read. This includes modifying * the palette. */voidpng_init_read_transformations(png_structp png_ptr){ png_debug(1, "in png_init_read_transformations\n");#if defined(PNG_USELESS_TESTS_SUPPORTED) if(png_ptr != NULL)#endif {#if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \ || defined(PNG_READ_GAMMA_SUPPORTED) int color_type = png_ptr->color_type;#endif#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) { if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ { /* expand background chunk. */ switch (png_ptr->bit_depth) { case 1: png_ptr->background.gray *= (png_uint_16)0xff; png_ptr->background.red = png_ptr->background.green = png_ptr->background.blue = png_ptr->background.gray; break; case 2: png_ptr->background.gray *= (png_uint_16)0x55; png_ptr->background.red = png_ptr->background.green = png_ptr->background.blue = png_ptr->background.gray; break; case 4: png_ptr->background.gray *= (png_uint_16)0x11; png_ptr->background.red = png_ptr->background.green = png_ptr->background.blue = png_ptr->background.gray; break; case 8: case 16: png_ptr->background.red = png_ptr->background.green = png_ptr->background.blue = png_ptr->background.gray; break; } } else if (color_type == PNG_COLOR_TYPE_PALETTE) { png_ptr->background.red = png_ptr->palette[png_ptr->background.index].red; png_ptr->background.green = png_ptr->palette[png_ptr->background.index].green; png_ptr->background.blue = png_ptr->palette[png_ptr->background.index].blue;#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) if (png_ptr->transformations & PNG_INVERT_ALPHA) {#if defined(PNG_READ_EXPAND_SUPPORTED) if (!(png_ptr->transformations & PNG_EXPAND))#endif { /* invert the alpha channel (in tRNS) unless the pixels are going to be expanded, in which case leave it for later */ int i,istop; istop=(int)png_ptr->num_trans; for (i=0; i<istop; i++) png_ptr->trans[i] = 255 - png_ptr->trans[i]; } }#endif } }#endif#if defined(PNG_READ_BACKGROUND_SUPPORTED) png_ptr->background_1 = png_ptr->background;#endif#if defined(PNG_READ_GAMMA_SUPPORTED) if (png_ptr->transformations & PNG_GAMMA) { png_build_gamma_table(png_ptr);#if defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->transformations & PNG_BACKGROUND) { if (color_type == PNG_COLOR_TYPE_PALETTE) { png_color back, back_1; png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) { back.red = png_ptr->gamma_table[png_ptr->background.red]; back.green = png_ptr->gamma_table[png_ptr->background.green]; back.blue = png_ptr->gamma_table[png_ptr->background.blue]; back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; } else { double g, gs; switch (png_ptr->background_gamma_type) { case PNG_BACKGROUND_GAMMA_SCREEN: g = (png_ptr->screen_gamma); gs = 1.0; break; case PNG_BACKGROUND_GAMMA_FILE: g = 1.0 / (png_ptr->gamma); gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); break; case PNG_BACKGROUND_GAMMA_UNIQUE: g = 1.0 / (png_ptr->background_gamma); gs = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); break; default: g = 1.0; /* back_1 */ gs = 1.0; /* back */ } if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD) { back.red = (png_byte)png_ptr->background.red; back.green = (png_byte)png_ptr->background.green; back.blue = (png_byte)png_ptr->background.blue; } else { back.red = (png_byte)(pow( (double)png_ptr->background.red/255, gs) * 255.0 + .5); back.green = (png_byte)(pow( (double)png_ptr->background.green/255, gs) * 255.0 + .5); back.blue = (png_byte)(pow( (double)png_ptr->background.blue/255, gs) * 255.0 + .5); } back_1.red = (png_byte)(pow( (double)png_ptr->background.red/255, g) * 255.0 + .5); back_1.green = (png_byte)(pow( (double)png_ptr->background.green/255, g) * 255.0 + .5); back_1.blue = (png_byte)(pow( (double)png_ptr->background.blue/255, g) * 255.0 + .5); } for (i = 0; i < num_palette; i++) { if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff) { if (png_ptr->trans[i] == 0) { palette[i] = back; } else /* if (png_ptr->trans[i] != 0xff) */ { png_byte v, w; v = png_ptr->gamma_to_1[palette[i].red]; png_composite(w, v, png_ptr->trans[i], back_1.red); palette[i].red = png_ptr->gamma_from_1[w]; v = png_ptr->gamma_to_1[palette[i].green]; png_composite(w, v, png_ptr->trans[i], back_1.green); palette[i].green = png_ptr->gamma_from_1[w]; v = png_ptr->gamma_to_1[palette[i].blue]; png_composite(w, v, png_ptr->trans[i], back_1.blue); palette[i].blue = png_ptr->gamma_from_1[w]; } } else { palette[i].red = png_ptr->gamma_table[palette[i].red]; palette[i].green = png_ptr->gamma_table[palette[i].green]; palette[i].blue = png_ptr->gamma_table[palette[i].blue]; } } } /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)*/ else /* color_type != PNG_COLOR_TYPE_PALETTE */ { double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1); double g = 1.0; double gs = 1.0; switch (png_ptr->background_gamma_type) { case PNG_BACKGROUND_GAMMA_SCREEN: g = (png_ptr->screen_gamma); gs = 1.0; break; case PNG_BACKGROUND_GAMMA_FILE: g = 1.0 / (png_ptr->gamma); gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma); break; case PNG_BACKGROUND_GAMMA_UNIQUE: g = 1.0 / (png_ptr->background_gamma); gs = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma); break; } if (color_type & PNG_COLOR_MASK_COLOR) { /* RGB or RGBA */ png_ptr->background_1.red = (png_uint_16)(pow( (double)png_ptr->background.red / m, g) * m + .5); png_ptr->background_1.green = (png_uint_16)(pow( (double)png_ptr->background.green / m, g) * m + .5); png_ptr->background_1.blue = (png_uint_16)(pow( (double)png_ptr->background.blue / m, g) * m + .5); png_ptr->background.red = (png_uint_16)(pow( (double)png_ptr->background.red / m, gs) * m + .5); png_ptr->background.green = (png_uint_16)(pow( (double)png_ptr->background.green / m, gs) * m + .5); png_ptr->background.blue = (png_uint_16)(pow( (double)png_ptr->background.blue / m, gs) * m + .5); } else { /* GRAY or GRAY ALPHA */ png_ptr->background_1.gray = (png_uint_16)(pow( (double)png_ptr->background.gray / m, g) * m + .5); png_ptr->background.gray = (png_uint_16)(pow( (double)png_ptr->background.gray / m, gs) * m + .5); } } } else /* transformation does not include PNG_BACKGROUND */#endif if (color_type == PNG_COLOR_TYPE_PALETTE) { png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; for (i = 0; i < num_palette; i++) { palette[i].red = png_ptr->gamma_table[palette[i].red]; palette[i].green = png_ptr->gamma_table[palette[i].green]; palette[i].blue = png_ptr->gamma_table[palette[i].blue]; } } }#if defined(PNG_READ_BACKGROUND_SUPPORTED) else#endif#endif#if defined(PNG_READ_BACKGROUND_SUPPORTED) /* No GAMMA transformation */ if (png_ptr->transformations & PNG_BACKGROUND && color_type == PNG_COLOR_TYPE_PALETTE) { int i; int istop = (int)png_ptr->num_trans; png_color back; png_colorp palette = png_ptr->palette; back.red = (png_byte)png_ptr->background.red; back.green = (png_byte)png_ptr->background.green; back.blue = (png_byte)png_ptr->background.blue; for (i = 0; i < istop; i++) { if (png_ptr->trans[i] == 0) { palette[i] = back; } else if (png_ptr->trans[i] != 0xff) { /* The png_composite() macro is defined in png.h */ png_composite(palette[i].red, palette[i].red, png_ptr->trans[i], back.red); png_composite(palette[i].green, palette[i].green,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -