Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/LibPNG/pngrtran.c view on Meta::CPAN
/* Find the closest color to one we threw out */
d_index = png_ptr->quantize_index[i];
min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
for (k = 1, min_k = 0; k < maximum_colors; k++)
{
int d;
d = PNG_COLOR_DIST(palette[d_index], palette[k]);
if (d < min_d)
{
min_d = d;
min_k = k;
}
}
/* Point to closest color */
png_ptr->quantize_index[i] = (png_byte)min_k;
}
}
}
png_free(png_ptr, png_ptr->quantize_sort);
png_ptr->quantize_sort = NULL;
}
else
{
/* This is much harder to do simply (and quickly). Perhaps
* we need to go through a median cut routine, but those
* don't always behave themselves with only a few colors
* as input. So we will just find the closest two colors,
* and throw out one of them (chosen somewhat randomly).
* [We don't understand this at all, so if someone wants to
* work on improving it, be our guest - AED, GRP]
*/
int i;
int max_d;
int num_new_palette;
png_dsortp t;
png_dsortpp hash;
t = NULL;
/* Initialize palette index arrays */
png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
(png_uint_32)(num_palette * (sizeof (png_byte))));
png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
(png_uint_32)(num_palette * (sizeof (png_byte))));
/* Initialize the sort array */
for (i = 0; i < num_palette; i++)
{
png_ptr->index_to_palette[i] = (png_byte)i;
png_ptr->palette_to_index[i] = (png_byte)i;
}
hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
(sizeof (png_dsortp))));
num_new_palette = num_palette;
/* Initial wild guess at how far apart the farthest pixel
* pair we will be eliminating will be. Larger
* numbers mean more areas will be allocated, Smaller
* numbers run the risk of not saving enough data, and
* having to do this all over again.
*
* I have not done extensive checking on this number.
*/
max_d = 96;
while (num_new_palette > maximum_colors)
{
for (i = 0; i < num_new_palette - 1; i++)
{
int j;
for (j = i + 1; j < num_new_palette; j++)
{
int d;
d = PNG_COLOR_DIST(palette[i], palette[j]);
if (d <= max_d)
{
t = (png_dsortp)png_malloc_warn(png_ptr,
(png_uint_32)(sizeof (png_dsort)));
if (t == NULL)
break;
t->next = hash[d];
t->left = (png_byte)i;
t->right = (png_byte)j;
hash[d] = t;
}
}
if (t == NULL)
break;
}
if (t != NULL)
for (i = 0; i <= max_d; i++)
{
if (hash[i] != NULL)
{
png_dsortp p;
for (p = hash[i]; p; p = p->next)
{
if ((int)png_ptr->index_to_palette[p->left]
< num_new_palette &&
(int)png_ptr->index_to_palette[p->right]
< num_new_palette)
{
int j, next_j;
if (num_new_palette & 0x01)
{
j = p->left;
next_j = p->right;
src/Source/LibPNG/pngrtran.c view on Meta::CPAN
while (bp < bp_end)
{
int b = *bp >> shift[channel];
if (++channel >= channels)
channel = 0;
*bp++ = (png_byte)b;
}
break;
}
#ifdef PNG_READ_16BIT_SUPPORTED
case 16:
/* Double byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
png_bytep bp_end = bp + row_info->rowbytes;
int channel = 0;
while (bp < bp_end)
{
int value = (bp[0] << 8) + bp[1];
value >>= shift[channel];
if (++channel >= channels)
channel = 0;
*bp++ = (png_byte)(value >> 8);
*bp++ = (png_byte)(value & 0xff);
}
break;
}
#endif
}
}
}
#endif
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale rows of bit depth 16 down to 8 accurately */
static void
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_scale_16_to_8");
if (row_info->bit_depth == 16)
{
png_bytep sp = row; /* source */
png_bytep dp = row; /* destination */
png_bytep ep = sp + row_info->rowbytes; /* end+1 */
while (sp < ep)
{
/* The input is an array of 16 bit components, these must be scaled to
* 8 bits each. For a 16 bit value V the required value (from the PNG
* specification) is:
*
* (V * 255) / 65535
*
* This reduces to round(V / 257), or floor((V + 128.5)/257)
*
* Represent V as the two byte value vhi.vlo. Make a guess that the
* result is the top byte of V, vhi, then the correction to this value
* is:
*
* error = floor(((V-vhi.vhi) + 128.5) / 257)
* = floor(((vlo-vhi) + 128.5) / 257)
*
* This can be approximated using integer arithmetic (and a signed
* shift):
*
* error = (vlo-vhi+128) >> 8;
*
* The approximate differs from the exact answer only when (vlo-vhi) is
* 128; it then gives a correction of +1 when the exact correction is
* 0. This gives 128 errors. The exact answer (correct for all 16 bit
* input values) is:
*
* error = (vlo-vhi+128)*65535 >> 24;
*
* An alternative arithmetic calculation which also gives no errors is:
*
* (V * 255 + 32895) >> 16
*/
png_int_32 tmp = *sp++; /* must be signed! */
tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
*dp++ = (png_byte)tmp;
}
row_info->bit_depth = 8;
row_info->pixel_depth = (png_byte)(8 * row_info->channels);
row_info->rowbytes = row_info->width * row_info->channels;
}
}
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
static void
/* Simply discard the low byte. This was the default behavior prior
* to libpng-1.5.4.
*/
png_do_chop(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_chop");
if (row_info->bit_depth == 16)
{
png_bytep sp = row; /* source */
png_bytep dp = row; /* destination */
png_bytep ep = sp + row_info->rowbytes; /* end+1 */
while (sp < ep)
{
*dp++ = *sp;
sp += 2; /* skip low byte */
}
row_info->bit_depth = 8;
row_info->pixel_depth = (png_byte)(8 * row_info->channels);
row_info->rowbytes = row_info->width * row_info->channels;
}
( run in 0.328 second using v1.01-cache-2.11-cpan-e93a5daba3e )