📄 pngrtran.c
字号:
for (k = 0; k < num_palette; k++)
{
if (png_ptr->dither_index[k] ==
index_to_palette[j])
png_ptr->dither_index[k] =
index_to_palette[next_j];
if ((int)png_ptr->dither_index[k] ==
num_new_palette)
png_ptr->dither_index[k] =
index_to_palette[j];
}
}
index_to_palette[palette_to_index[num_new_palette]] =
index_to_palette[j];
palette_to_index[index_to_palette[j]] =
palette_to_index[num_new_palette];
index_to_palette[j] = (png_byte)num_new_palette;
palette_to_index[num_new_palette] = (png_byte)j;
}
if (num_new_palette <= maximum_colors)
break;
}
if (num_new_palette <= maximum_colors)
break;
}
}
for (i = 0; i < 769; i++)
{
if (hash[i] != NULL)
{
png_dsortp p = hash[i];
while (p)
{
png_dsortp t;
t = p->next;
png_free(png_ptr, p);
p = t;
}
}
hash[i] = 0;
}
max_d += 96;
}
png_free(png_ptr, hash);
png_free(png_ptr, palette_to_index);
png_free(png_ptr, index_to_palette);
}
num_palette = maximum_colors;
}
if (png_ptr->palette == NULL)
{
png_ptr->palette = palette;
}
png_ptr->num_palette = (png_uint_16)num_palette;
if (full_dither)
{
int i;
png_bytep distance;
int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
PNG_DITHER_BLUE_BITS;
int num_red = (1 << PNG_DITHER_RED_BITS);
int num_green = (1 << PNG_DITHER_GREEN_BITS);
int num_blue = (1 << PNG_DITHER_BLUE_BITS);
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.
*/
void
png_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.
*/
void
png_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)
void
png_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 same width. This allows us,
* for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
*/
void
png_set_rgb_to_gray(png_structp png_ptr, int error_action, float red,
float green)
{
png_debug(1, "in png_set_rgb_to_gray\n");
switch(error_action)
{
case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
break;
case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
break;
case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#if defined(PNG_READ_EXPAND_SUPPORTED)
png_ptr->transformations |= PNG_EXPAND;
#else
{
png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
}
#endif
{
png_byte red_byte = (png_byte)(red*255.0 + 0.5);
png_byte green_byte = (png_byte)(green*255.0 + 0.5);
if(red < 0.0 || green < 0.0)
{
red_byte = 54;
green_byte = 183;
}
else if(red_byte + green_byte > 255)
{
png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
red_byte = 54;
green_byte = 183;
}
png_ptr->rgb_to_gray_red_coeff = red_byte;
png_ptr->rgb_to_gray_green_coeff = green_byte;
png_ptr->rgb_to_gray_blue_coeff = 255 - red_byte - green_byte;
}
}
#endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
void
png_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.
*/
void
png_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_RGB_TO_GRAY))
{
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -