diff options
Diffstat (limited to 'pngwutil.c')
-rw-r--r-- | pngwutil.c | 710 |
1 files changed, 534 insertions, 176 deletions
diff --git a/pngwutil.c b/pngwutil.c index 2b08369ca..2ac333242 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -1,7 +1,7 @@ /* pngwutil.c - utilities to write a PNG file * - * libpng 1.0.5d - November 29, 1999 + * libpng 1.0.5h - December 10, 1999 * For conditions of distribution and use, see copyright notice in png.h * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1996, 1997 Andreas Dilger @@ -133,6 +133,223 @@ png_write_sig(png_structp png_ptr) (png_size_t)8 - png_ptr->sig_bytes); } +#if defined(PNG_WRITE_TEXT_SUPPORTED) +/* + * This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + char *input; /* the uncompressed input data */ + int input_len; /* its length */ + int num_output_ptr; /* number of output pointers used */ + int max_output_ptr; /* size of output_ptr */ + png_charpp output_ptr; /* array of pointers to output */ +} compression_state; + +/* compress given text into storage in the png_ptr structure */ +static int +png_text_compress(png_structp png_ptr, + png_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + + /* we may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = text; + comp->input_len = text_len; + return(text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#if !defined(PNG_NO_STDIO) + char msg[50]; + sprintf(msg, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown 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 (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charp))); + } + + /* save the data */ + comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* finish the compression */ + do + { + /* tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* we got an 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) && ret == Z_OK) + { + /* check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_charpp old_ptr; + + old_ptr = comp->output_ptr; + /* This could be optimized to realloc() */ + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp))); + png_memcpy(comp->output_ptr, old_ptr, + old_max * sizeof (png_charp)); + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_charpp)png_malloc(png_ptr, + (png_uint_32)(comp->max_output_ptr * sizeof (png_charp))); + } + + /* save off the data */ + comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr, + (png_uint_32)png_ptr->zbuf_size); + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } while (ret != Z_STREAM_END); + + /* text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return(text_len); +} + +/* ship the compressed text out via chunk writes */ +static void +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, (png_bytep)comp->input, comp->input_len); + return; + } + + /* write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],png_ptr->zbuf_size); + png_free(png_ptr, comp->output_ptr[i]); + } + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + /* write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + /* reset zlib for another zTXt/iTXt or the image data */ + deflateReset(&png_ptr->zstream); + +} +#endif + /* Write the IHDR chunk, and update the png_struct with the necessary * information. Note that the rest of this code depends upon this * information being correct. @@ -349,6 +566,7 @@ png_write_IEND(png_structp png_ptr) #if defined(PNG_WRITE_gAMA_SUPPORTED) /* write a gAMA chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED void png_write_gAMA(png_structp png_ptr, double file_gamma) { @@ -365,6 +583,22 @@ png_write_gAMA(png_structp png_ptr, double file_gamma) png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); } #endif +void +#ifdef PNG_FIXED_POINT_SUPPORTED +png_write_gAMA_fixed(png_structp png_ptr, png_uint_32 file_gamma) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_gAMA; +#endif + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA\n"); + /* file_gamma is saved in 1/1000000ths */ + png_save_uint_32(buf, file_gamma); + png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); +} +#endif +#endif #if defined(PNG_WRITE_sRGB_SUPPORTED) /* write a sRGB chunk */ @@ -385,6 +619,104 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent) } #endif +#if defined(PNG_WRITE_iCCP_SUPPORTED) +/* write an iCCP chunk */ +void +png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, + png_charp profile, int profile_len) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iCCP; +#endif + png_size_t name_len; + png_charp new_name; + compression_state comp; + + png_debug(1, "in png_write_iCCP\n"); + if (name == NULL || (name_len = png_check_keyword(png_ptr, name, + &new_name)) == 0) + { + png_warning(png_ptr, "Empty keyword in iCCP chunk"); + return; + } + + if (compression_type) + /* ignore */ ; + + if (profile == NULL || *profile == '\0') + profile_len = 0; + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, profile_len, + PNG_TEXT_COMPRESSION_zTXt, &comp); + + /* make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, + (png_uint_32)name_len+profile_len+2); + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +/* write a sPLT chunk */ +void +png_write_sPLT(png_structp png_ptr, png_spalette_p spalette) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sPLT; +#endif + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + int entry_size = (spalette->depth == 8 ? 6 : 10); + int palette_size = entry_size * spalette->nentries; + png_spalette_entryp ep; + + png_debug(1, "in png_write_sPLT\n"); + if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr, spalette->name, &new_name))==0) + { + png_warning(png_ptr, "Empty keyword in sPLT chunk"); + return; + } + + /* make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, (png_bytep) png_sPLT, + (png_uint_32)(name_len + 1 + palette_size)); + png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1); + + /* loop through each palette entry, writing appropriately */ + for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + png_write_chunk_data(png_ptr, entrybuf, entry_size); + } + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + #if defined(PNG_WRITE_sBIT_SUPPORTED) /* write the sBIT chunk */ void @@ -443,6 +775,7 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) #if defined(PNG_WRITE_cHRM_SUPPORTED) /* write the cHRM chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED 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, @@ -455,7 +788,7 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, png_byte buf[32]; png_debug(1, "in png_write_cHRM\n"); - /* each value is saved int 1/1000000ths */ + /* each value is saved in 1/1000000ths */ if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 || white_x + white_y > 1.0) { @@ -503,6 +836,57 @@ png_write_cHRM(png_structp png_ptr, double white_x, double white_y, png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); } #endif +#ifdef PNG_FIXED_POINT_SUPPORTED +void +png_write_cHRM_fixed(png_structp png_ptr, png_uint_32 white_x, + png_uint_32 white_y, png_uint_32 red_x, png_uint_32 red_y, + png_uint_32 green_x, png_uint_32 green_y, png_uint_32 blue_x, + png_uint_32 blue_y) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_cHRM; +#endif + 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 > 80000L || white_y > 80000L || white_x + white_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM white point specified"); + return; + } + png_save_uint_32(buf, white_x); + png_save_uint_32(buf + 4, white_y); + + if (red_x > 80000L || red_y > 80000L || red_x + red_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM red point specified"); + return; + } + png_save_uint_32(buf + 8, red_x); + png_save_uint_32(buf + 12, red_y); + + if (green_x > 80000L || green_y > 80000L || green_x + green_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM green point specified"); + return; + } + png_save_uint_32(buf + 16, green_x); + png_save_uint_32(buf + 20, green_y); + + if (blue_x > 80000L || blue_y > 80000L || blue_x + blue_y > 100000L) + { + png_warning(png_ptr, "Invalid cHRM blue point specified"); + return; + } + png_save_uint_32(buf + 24, blue_x); + png_save_uint_32(buf + 28, blue_y); + + png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); +} +#endif +#endif #if defined(PNG_WRITE_tRNS_SUPPORTED) /* write the tRNS chunk */ @@ -618,8 +1002,8 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) } #endif -#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) || \ - defined(PNG_WRITE_pCAL_SUPPORTED) +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_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 @@ -766,6 +1150,7 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, * We leave it to the application to meet PNG-1.0 requirements on the * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. */ png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); if (text_len) @@ -788,10 +1173,7 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, 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 */ + compression_state comp; png_debug(1, "in png_write_zTXt\n"); @@ -810,178 +1192,101 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, 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; + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, &comp); - /* 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; + /* write start of chunk */ + png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32) + (key_len+text_len+2)); + /* write key */ + png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1); + buf[0] = (png_byte)compression; + /* write compression */ + png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + /* write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); - old_max = max_output_ptr; - max_output_ptr = num_output_ptr + 4; - if (output_ptr != NULL) - { - png_charpp old_ptr; + /* close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif - 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))); - } +#if defined(PNG_WRITE_iTXt_SUPPORTED) +/* write an iTXt chunk */ +void +png_write_iTXt(png_structp png_ptr, int compression, png_charp key, + png_charp lang, png_charp translated_key, png_charp text) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_iTXt; +#endif + png_size_t lang_len, key_len, translated_key_len, text_len; + png_charp new_lang, new_key; + png_byte cbuf[2]; + compression_state comp; - /* save the data */ - output_ptr[num_output_ptr] = (png_charp)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - num_output_ptr++; + png_debug(1, "in png_write_iTXt\n"); - /* and reset the buffer */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - /* continue until we don't have any more to compress */ - } while (png_ptr->zstream.avail_in); + translated_key_len = png_strlen(translated_key); + text_len = png_strlen(text); - /* finish the compression */ - do + if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, + &new_lang))==0) { - /* tell zlib we are finished */ - ret = deflate(&png_ptr->zstream, Z_FINISH); - if (ret != Z_OK && ret != Z_STREAM_END) - { - /* we got an 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) && ret == Z_OK) - { - /* check to make sure our output array has room */ - if (num_output_ptr >= max_output_ptr) - { - int old_max; + png_warning(png_ptr, "Empty language field in iTXt chunk"); + return; + } + if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0) + { + png_warning(png_ptr, "Empty keyword in iTXt chunk"); + return; + } - old_max = max_output_ptr; - max_output_ptr = num_output_ptr + 4; - if (output_ptr != NULL) - { - png_charpp old_ptr; + if (text == NULL || *text == '\0') + text_len = 0; - old_ptr = output_ptr; - /* This could be optimized to realloc() */ - 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))); - } + /* compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, &comp); - /* save off the data */ - output_ptr[num_output_ptr] = (png_charp)png_malloc(png_ptr, - (png_uint_32)png_ptr->zbuf_size); - png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf, - png_ptr->zbuf_size); - num_output_ptr++; + /* make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and translated_key parts */ + png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, + (png_uint_32)(2 + lang_len+1 + key_len+1 + translated_key_len + + text_len)); - /* and reset the buffer pointers */ - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - png_ptr->zstream.next_out = png_ptr->zbuf; - } - } while (ret != Z_STREAM_END); + /* set the compression bits */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + cbuf[0] = 0; + cbuf[1] = 0; + } + else /* compression == PNG_TEXT_COMPRESSION_zTXt */ + { + cbuf[0] = 1; + cbuf[1] = 0; + } + png_write_chunk_data(png_ptr, cbuf, 2); - /* text length is number of buffers plus last buffer */ - text_len = png_ptr->zbuf_size * num_output_ptr; - if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) - text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1); + png_write_chunk_data(png_ptr, (png_bytep)new_lang, lang_len + 1); + png_write_chunk_data(png_ptr, (png_bytep)translated_key, + translated_key_len); + png_write_chunk_data(png_ptr, '\0', 1); - /* write start of chunk */ - png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32)(key_len+text_len+2)); - /* write key */ - png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1); - buf[0] = (png_byte)compression; - /* write compression */ - png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); + png_write_compressed_data_out(png_ptr, &comp); - /* write saved output buffers, if any */ - for (i = 0; i < num_output_ptr; i++) - { - png_write_chunk_data(png_ptr,(png_bytep)output_ptr[i],png_ptr->zbuf_size); - png_free(png_ptr, output_ptr[i]); - } - if (max_output_ptr != 0) - png_free(png_ptr, output_ptr); - /* write anything left in zbuf */ - if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) - png_write_chunk_data(png_ptr, png_ptr->zbuf, - png_ptr->zbuf_size - png_ptr->zstream.avail_out); - /* close the chunk */ png_write_chunk_end(png_ptr); - - /* reset zlib for another zTXt or the image data */ - deflateReset(&png_ptr->zstream); + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); } #endif - #if defined(PNG_WRITE_oFFs_SUPPORTED) /* write the oFFs chunk */ void @@ -1066,6 +1371,59 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, } #endif +#if defined(PNG_WRITE_sCAL_SUPPORTED) +/* write the sCAL chunk */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void +png_write_sCAL(png_structp png_ptr, png_charp unit, double width,double height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_size_t total_len; + char wbuf[32], hbuf[32]; + + png_debug(1, "in png_write_sCAL\n"); + + sprintf(wbuf, "%12.12e", width); + sprintf(hbuf, "%12.12e", height); + total_len = png_strlen(unit)+1 + png_strlen(wbuf)+1 + png_strlen(hbuf); + + png_debug1(3, "sCAL total length = %d\n", total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)unit, png_strlen(unit)+1); + png_write_chunk_data(png_ptr, (png_bytep)wbuf, strlen(wbuf)+1); + png_write_chunk_data(png_ptr, (png_bytep)hbuf, strlen(hbuf)); + + png_write_chunk_end(png_ptr); +} +#endif +void +png_write_sCAL_s(png_structp png_ptr, png_charp unit, png_charp width, + png_charp height) +{ +#ifdef PNG_USE_LOCAL_ARRAYS + PNG_sCAL; +#endif + png_size_t total_len; + char wbuf[32], hbuf[32]; + + png_debug(1, "in png_write_sCAL\n"); + + sprintf(wbuf, "%s", width); + sprintf(hbuf, "%s", height); + total_len = png_strlen(unit)+1 + png_strlen(wbuf)+1 + png_strlen(hbuf); + + png_debug1(3, "sCAL total length = %d\n", total_len); + png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_bytep)unit, png_strlen(unit)+1); + png_write_chunk_data(png_ptr, (png_bytep)wbuf, strlen(wbuf)+1); + png_write_chunk_data(png_ptr, (png_bytep)hbuf, strlen(hbuf)); + + png_write_chunk_end(png_ptr); +} +#endif + #if defined(PNG_WRITE_pHYs_SUPPORTED) /* write the pHYs chunk */ void @@ -1128,20 +1486,20 @@ png_write_start_row(png_structp png_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - + /* start of interlace block */ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - + /* offset to next interlace block */ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - + /* start of interlace block in the y direction */ int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - + /* offset to next interlace block in the y direction */ int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif - + png_size_t buf_size; png_debug(1, "in png_write_start_row\n"); @@ -1222,20 +1580,20 @@ png_write_finish_row(png_structp png_ptr) { #ifdef PNG_USE_LOCAL_ARRAYS /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - + /* start of interlace block */ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - + /* offset to next interlace block */ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - + /* start of interlace block in the y direction */ int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - + /* offset to next interlace block in the y direction */ int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif - + int ret; png_debug(1, "in png_write_finish_row\n"); @@ -1336,14 +1694,14 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { #ifdef PNG_USE_LOCAL_ARRAYS /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - + /* start of interlace block */ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - + /* offset to next interlace block */ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; #endif - + png_debug(1, "in png_do_write_interlace\n"); /* we don't have to do anything on the last pass (6) */ #if defined(PNG_USELESS_TESTS_SUPPORTED) @@ -2170,5 +2528,5 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) { png_write_flush(png_ptr); } -#endif /* PNG_WRITE_FLUSH_SUPPORTED */ +#endif } |