📄 pngwutil.c
字号:
}
#endif
#if defined(PNG_WRITE_cHRM_SUPPORTED)
/* write the cHRM chunk */
void
png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
double red_x, double red_y, double green_x, double green_y,
double blue_x, double blue_y)
{
png_uint_32 itemp;
png_byte buf[32];
png_debug(1, "in png_write_cHRM\n");
/* each value is saved int 1/1000000ths */
if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
white_x + white_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM white point specified");
return;
}
itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
png_save_uint_32(buf, itemp);
itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
png_save_uint_32(buf + 4, itemp);
if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
red_x + red_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM red point specified");
return;
}
itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
png_save_uint_32(buf + 8, itemp);
itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
png_save_uint_32(buf + 12, itemp);
if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
green_x + green_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM green point specified");
return;
}
itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
png_save_uint_32(buf + 16, itemp);
itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
png_save_uint_32(buf + 20, itemp);
if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
blue_x + blue_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM blue point specified");
return;
}
itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
png_save_uint_32(buf + 24, itemp);
itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
png_save_uint_32(buf + 28, itemp);
png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
}
#endif
#if defined(PNG_WRITE_tRNS_SUPPORTED)
/* write the tRNS chunk */
void
png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
int num_trans, int color_type)
{
png_byte buf[6];
png_debug(1, "in png_write_tRNS\n");
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
{
png_warning(png_ptr,"Invalid number of transparent colors specified");
return;
}
/* write the chunk out as it is */
png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans);
}
else if (color_type == PNG_COLOR_TYPE_GRAY)
{
/* one 16 bit value */
png_save_uint_16(buf, tran->gray);
png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
}
else if (color_type == PNG_COLOR_TYPE_RGB)
{
/* three 16 bit values */
png_save_uint_16(buf, tran->red);
png_save_uint_16(buf + 2, tran->green);
png_save_uint_16(buf + 4, tran->blue);
png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
}
else
{
png_warning(png_ptr, "Can't write tRNS with an alpha channel");
}
}
#endif
#if defined(PNG_WRITE_bKGD_SUPPORTED)
/* write the background chunk */
void
png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
{
png_byte buf[6];
png_debug(1, "in png_write_bKGD\n");
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
if (back->index > png_ptr->num_palette)
{
png_warning(png_ptr, "Invalid background palette index");
return;
}
buf[0] = back->index;
png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
}
else if (color_type & PNG_COLOR_MASK_COLOR)
{
png_save_uint_16(buf, back->red);
png_save_uint_16(buf + 2, back->green);
png_save_uint_16(buf + 4, back->blue);
png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
}
else
{
png_save_uint_16(buf, back->gray);
png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
}
}
#endif
#if defined(PNG_WRITE_hIST_SUPPORTED)
/* write the histogram */
void
png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
{
int i;
png_byte buf[3];
png_debug(1, "in png_write_hIST\n");
if (num_hist > (int)png_ptr->num_palette)
{
png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
png_ptr->num_palette);
png_warning(png_ptr, "Invalid number of histogram entries specified");
return;
}
png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
for (i = 0; i < num_hist; i++)
{
png_save_uint_16(buf, hist[i]);
png_write_chunk_data(png_ptr, buf, (png_size_t)2);
}
png_write_chunk_end(png_ptr);
}
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) || \
defined(PNG_WRITE_pCAL_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
* and if invalid, correct the keyword rather than discarding the entire
* chunk. The PNG 1.0 specification requires keywords 1-79 characters in
* length, forbids leading or trailing whitespace, multiple internal spaces,
* and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
*
* The new_key is allocated to hold the corrected keyword and must be freed
* by the calling routine. This avoids problems with trying to write to
* static keywords without having to have duplicate copies of the strings.
*/
png_size_t
png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
{
png_size_t key_len;
png_charp kp, dp;
int kflag;
png_debug(1, "in png_check_keyword\n");
*new_key = NULL;
if (key == NULL || (key_len = png_strlen(key)) == 0)
{
png_chunk_warning(png_ptr, "zero length keyword");
return ((png_size_t)0);
}
png_debug1(2, "Keyword to be checked is '%s'\n", key);
*new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 1));
/* Replace non-printing characters with a blank and print a warning */
for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
{
if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
{
#if !defined(PNG_NO_STDIO)
char msg[40];
sprintf(msg, "invalid keyword character 0x%02X", *kp);
png_chunk_warning(png_ptr, msg);
#else
png_chunk_warning(png_ptr, "invalid character in keyword");
#endif
*dp = ' ';
}
else
{
*dp = *kp;
}
}
*dp = '\0';
/* Remove any trailing white space. */
kp = *new_key + key_len - 1;
if (*kp == ' ')
{
png_chunk_warning(png_ptr, "trailing spaces removed from keyword");
while (*kp == ' ')
{
*(kp--) = '\0';
key_len--;
}
}
/* Remove any leading white space. */
kp = *new_key;
if (*kp == ' ')
{
png_chunk_warning(png_ptr, "leading spaces removed from keyword");
while (*kp == ' ')
{
kp++;
key_len--;
}
}
png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
/* Remove multiple internal spaces. */
for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
{
if (*kp == ' ' && kflag == 0)
{
*(dp++) = *kp;
kflag = 1;
}
else if (*kp == ' ')
{
key_len--;
}
else
{
*(dp++) = *kp;
kflag = 0;
}
}
*dp = '\0';
if (key_len == 0)
{
png_chunk_warning(png_ptr, "zero length keyword");
}
if (key_len > 79)
{
png_chunk_warning(png_ptr, "keyword length must be 1 - 79 characters");
new_key[79] = '\0';
key_len = 79;
}
return (key_len);
}
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write a tEXt chunk */
void
png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
png_size_t text_len)
{
png_size_t key_len;
png_charp new_key;
png_debug(1, "in png_write_tEXt\n");
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
{
png_warning(png_ptr, "Empty keyword in tEXt chunk");
return;
}
if (text == NULL || *text == '\0')
text_len = 0;
/* make sure we include the 0 after the key */
png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1);
png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
if (text_len)
png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
png_write_chunk_end(png_ptr);
png_free(png_ptr, new_key);
}
#endif
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write a compressed text chunk */
void
png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
png_size_t text_len, int compression)
{
png_size_t key_len;
char buf[1];
png_charp new_key;
int i, ret;
png_charpp output_ptr = NULL; /* array of pointers to output */
int num_output_ptr = 0; /* number of output pointers used */
int max_output_ptr = 0; /* size of output_ptr */
png_debug(1, "in png_write_zTXt\n");
if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
{
png_warning(png_ptr, "Empty keyword in zTXt chunk");
return;
}
if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
{
png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
png_free(png_ptr, new_key);
return;
}
png_free(png_ptr, new_key);
if (compression >= PNG_TEXT_COMPRESSION_LAST)
{
#if !defined(PNG_NO_STDIO)
char msg[50];
sprintf(msg, "Unknown zTXt compression type %d", compression);
png_warning(png_ptr, msg);
#else
png_warning(png_ptr, "Unknown zTXt compression type");
#endif
compression = PNG_TEXT_COMPRESSION_zTXt;
}
/* We can't write the chunk until we find out how much data we have,
* which means we need to run the compressor first and save the
* output. This shouldn't be a problem, as the vast majority of
* comments should be reasonable, but we will set up an array of
* malloc'd pointers to be sure.
*
* If we knew the application was well behaved, we could simplify this
* greatly by assuming we can always malloc an output buffer large
* enough to hold the compressed text ((1001 * text_len / 1000) + 12)
* and malloc this directly. The only time this would be a bad idea is
* if we can't malloc more than 64K and we have 64K of random input
* data, or if the input string is incredibly large (although this
* wouldn't cause a failure, just a slowdown due to swapping).
*/
/* set up the compression buffers */
png_ptr->zstream.avail_in = (uInt)text_len;
png_ptr->zstream.next_in = (Bytef *)text;
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
/* this is the same compression loop as in png_write_row() */
do
{
/* compress the data */
ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
if (ret != Z_OK)
{
/* error */
if (png_ptr->zstream.msg != NULL)
png_error(png_ptr, png_ptr->zstream.msg);
else
png_error(png_ptr, "zlib error");
}
/* check to see if we need more room */
if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in)
{
/* make sure the output array has room */
if (num_output_ptr >= max_output_ptr)
{
int old_max;
old_max = max_output_ptr;
max_output_ptr = num_output_ptr + 4;
if (output_ptr != NULL)
{
png_charpp old_ptr;
old_ptr = output_ptr;
output_ptr = (png_charpp)png_malloc(png_ptr,
(png_uint_32)(max_output_ptr * sizeof (png_charpp)));
png_memcpy(output_ptr, old_ptr, old_max * sizeof (png_charp));
png_free(png_ptr, old_ptr);
}
else
output_ptr = (png_charpp)png_malloc(png_ptr,
(png_uint_32)(max_output_ptr * sizeof (png_charp)));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -