📄 pngrtran.c
字号:
#if defined(PNG_READ_SWAP_SUPPORTED)
if (png_ptr->transformations & PNG_SWAP_BYTES)
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
if (png_ptr->transformations & PNG_USER_TRANSFORM)
{
if (png_ptr->read_user_transform_fn != NULL)
(*(png_ptr->read_user_transform_fn)) /* user read transform function */
(png_ptr, /* png_ptr */
&(png_ptr->row_info), /* row_info: */
/* png_uint_32 width; width of row */
/* png_uint_32 rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */
/* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr->row_buf + 1); /* start of pixel data for row */
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
if (png_ptr->user_transform_depth)
png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
if (png_ptr->user_transform_channels)
png_ptr->row_info.channels = png_ptr->user_transform_channels;
#endif
png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
png_ptr->row_info.channels);
png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
png_ptr->row_info.width);
}
#endif
}
#if defined(PNG_READ_PACK_SUPPORTED)
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
* without changing the actual values. Thus, if you had a row with
* a bit depth of 1, you would end up with bytes that only contained
* the numbers 0 or 1. If you would rather they contain 0 and 255, use
* png_do_shift() after this.
*/
void /* PRIVATE */
png_do_unpack(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_unpack");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
#else
if (row_info->bit_depth < 8)
#endif
{
png_uint_32 i;
png_uint_32 row_width=row_info->width;
switch (row_info->bit_depth)
{
case 1:
{
png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
png_bytep dp = row + (png_size_t)row_width - 1;
png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
for (i = 0; i < row_width; i++)
{
*dp = (png_byte)((*sp >> shift) & 0x01);
if (shift == 7)
{
shift = 0;
sp--;
}
else
shift++;
dp--;
}
break;
}
case 2:
{
png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
png_bytep dp = row + (png_size_t)row_width - 1;
png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
for (i = 0; i < row_width; i++)
{
*dp = (png_byte)((*sp >> shift) & 0x03);
if (shift == 6)
{
shift = 0;
sp--;
}
else
shift += 2;
dp--;
}
break;
}
case 4:
{
png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
png_bytep dp = row + (png_size_t)row_width - 1;
png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
for (i = 0; i < row_width; i++)
{
*dp = (png_byte)((*sp >> shift) & 0x0f);
if (shift == 4)
{
shift = 0;
sp--;
}
else
shift = 4;
dp--;
}
break;
}
}
row_info->bit_depth = 8;
row_info->pixel_depth = (png_byte)(8 * row_info->channels);
row_info->rowbytes = row_width * row_info->channels;
}
}
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED)
/* Reverse the effects of png_do_shift. This routine merely shifts the
* pixels back to their significant bits values. Thus, if you have
* a row of bit depth 8, but only 5 are significant, this will shift
* the values back to 0 through 31.
*/
void /* PRIVATE */
png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
{
png_debug(1, "in png_do_unshift");
if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
row != NULL && row_info != NULL && sig_bits != NULL &&
#endif
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
{
int shift[4];
int channels = 0;
int c;
png_uint_16 value = 0;
png_uint_32 row_width = row_info->width;
if (row_info->color_type & PNG_COLOR_MASK_COLOR)
{
shift[channels++] = row_info->bit_depth - sig_bits->red;
shift[channels++] = row_info->bit_depth - sig_bits->green;
shift[channels++] = row_info->bit_depth - sig_bits->blue;
}
else
{
shift[channels++] = row_info->bit_depth - sig_bits->gray;
}
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
{
shift[channels++] = row_info->bit_depth - sig_bits->alpha;
}
for (c = 0; c < channels; c++)
{
if (shift[c] <= 0)
shift[c] = 0;
else
value = 1;
}
if (!value)
return;
switch (row_info->bit_depth)
{
case 2:
{
png_bytep bp;
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
for (bp = row, i = 0; i < istop; i++)
{
*bp >>= 1;
*bp++ &= 0x55;
}
break;
}
case 4:
{
png_bytep bp = row;
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
(png_byte)((int)0xf >> shift[0]));
for (i = 0; i < istop; i++)
{
*bp >>= shift[0];
*bp++ &= mask;
}
break;
}
case 8:
{
png_bytep bp = row;
png_uint_32 i;
png_uint_32 istop = row_width * channels;
for (i = 0; i < istop; i++)
{
*bp++ >>= shift[i%channels];
}
break;
}
case 16:
{
png_bytep bp = row;
png_uint_32 i;
png_uint_32 istop = channels * row_width;
for (i = 0; i < istop; i++)
{
value = (png_uint_16)((*bp << 8) + *(bp + 1));
value >>= shift[i%channels];
*bp++ = (png_byte)(value >> 8);
*bp++ = (png_byte)(value & 0xff);
}
break;
}
}
}
}
#endif
#if defined(PNG_READ_16_TO_8_SUPPORTED)
/* chop rows of bit depth 16 down to 8 */
void /* PRIVATE */
png_do_chop(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_chop");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
#else
if (row_info->bit_depth == 16)
#endif
{
png_bytep sp = row;
png_bytep dp = row;
png_uint_32 i;
png_uint_32 istop = row_info->width * row_info->channels;
for (i = 0; i<istop; i++, sp += 2, dp++)
{
#if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
/* This does a more accurate scaling of the 16-bit color
* value, rather than a simple low-byte truncation.
*
* What the ideal calculation should be:
* *dp = (((((png_uint_32)(*sp) << 8) |
* (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
*
* GRR: no, I think this is what it really should be:
* *dp = (((((png_uint_32)(*sp) << 8) |
* (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
*
* GRR: here's the exact calculation with shifts:
* temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
* *dp = (temp - (temp >> 8)) >> 8;
*
* Approximate calculation with shift/add instead of multiply/divide:
* *dp = ((((png_uint_32)(*sp) << 8) |
* (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
*
* What we actually do to avoid extra shifting and conversion:
*/
*dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
#else
/* Simply discard the low order byte */
*dp = *sp;
#endif
}
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
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
void /* PRIVATE */
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_read_swap_alpha");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
if (row != NULL && row_info != NULL)
#endif
{
png_uint_32 row_width = row_info->width;
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
/* This converts from RGBA to ARGB */
if (row_info->bit_depth == 8)
{
png_bytep sp = row + row_info->rowbytes;
png_bytep dp = sp;
png_byte save;
png_uint_32 i;
for (i = 0; i < row_width; i++)
{
save = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = save;
}
}
/* This converts from RRGGBBAA to AARRGGBB */
else
{
png_bytep sp = row + row_info->rowbytes;
png_bytep dp = sp;
png_byte save[2];
png_uint_32 i;
for (i = 0; i < row_width; i++)
{
save[0] = *(--sp);
save[1] = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = save[0];
*(--dp) = save[1];
}
}
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
/* This converts from GA to AG */
if (row_info->bit_depth == 8)
{
png_bytep sp = row + row_info->rowbytes;
png_bytep dp = sp;
png_byte save;
png_uint_32 i;
for (i = 0; i < row_width; i++)
{
save = *(--sp);
*(--dp) = *(--sp);
*(--dp) = save;
}
}
/* This converts from GGAA to AAGG */
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -