/* Allocate memory for a png_struct or a png_info. The malloc and memset can be replaced by a single call to calloc() if this is thought to improve performance noticably. */ png_voidp /* PRIVATE */ png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr) { #endif /* PNG_USER_MEM_SUPPORTED */ png_size_t size; png_voidp struct_ptr; if (type == PNG_STRUCT_INFO) size = png_sizeof(png_info); else if (type == PNG_STRUCT_PNG) size = png_sizeof(png_struct); else return (NULL); #ifdef PNG_USER_MEM_SUPPORTED if(malloc_fn != NULL) { png_struct dummy_struct; png_structp png_ptr = &dummy_struct; png_ptr->mem_ptr=mem_ptr; struct_ptr = (*(malloc_fn))(png_ptr, size); if (struct_ptr != NULL) png_memset(struct_ptr, 0, size); return (struct_ptr); } #endif /* PNG_USER_MEM_SUPPORTED */ if (g_png_default_malloc_ptr) struct_ptr = (png_voidp)(*g_png_default_malloc_ptr)(size); else struct_ptr = (png_voidp)malloc(size); if (struct_ptr != NULL) png_memset(struct_ptr, 0, size); return (struct_ptr); }
png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size) { /* png_malloc has already tested for NULL; png_create_struct calls * png_debug_malloc directly, with png_ptr == NULL which is OK */ if (size == 0) return (NULL); /* This calls the library allocator twice, once to get the requested buffer and once to get a new free list entry. */ { /* Disable malloc_fn and free_fn */ memory_infop pinfo; png_set_mem_fn(png_ptr, NULL, NULL, NULL); pinfo = (memory_infop)png_malloc(png_ptr, (png_uint_32)png_sizeof(*pinfo)); pinfo->size = size; current_allocation += size; total_allocation += size; num_allocations ++; if (current_allocation > maximum_allocation) maximum_allocation = current_allocation; pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); /* Restore malloc_fn and free_fn */ png_set_mem_fn(png_ptr, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); if (size != 0 && pinfo->pointer == NULL) { current_allocation -= size; total_allocation -= size; png_error(png_ptr, "out of memory in pngtest->png_debug_malloc."); } pinfo->next = pinformation; pinformation = pinfo; /* Make sure the caller isn't assuming zeroed memory. */ png_memset(pinfo->pointer, 0xdd, pinfo->size); if (verbose) printf("png_malloc %lu bytes at %x\n", (unsigned long)size, pinfo->pointer); return (png_voidp)(pinfo->pointer); } }
// write 24-bit image data to a file int writePng(FILE * fp, int w, int h, char * data) { // set up row pointers png_byte ** row_pointers = (png_byte**)malloc(h*png_sizeof(png_bytep)); if( !row_pointers ) { return -1; } for( int i=0; i<h; i++ ) { row_pointers[i] = (png_byte*)(data + i*w*3); } // set up png structures png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, NULL, NULL); if(!png_ptr) return -1; png_infop info_ptr = png_create_info_struct(png_ptr); if(!info_ptr) { png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return -1; } // set up error-handling if( setjmp(png_jmpbuf(png_ptr)) ) { png_destroy_write_struct(&png_ptr, &info_ptr); return -1; } png_init_io(png_ptr, fp); // set up width, height, RGB with 8-bits/color png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); // clean up png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); return 0; }
png_info * png_create_info_struct_2(png_struct * png_ptr) { png_info * info_ptr; //png_debug(1, "in png_create_info_struct"); if (png_ptr == NULL) return (NULL); #ifdef PNG_USER_MEM_SUPPORTED info_ptr = (png_info *)png_create_struct_3(PNG_STRUCT_INFO, png_ptr->malloc_fn, png_ptr->mem_ptr); #endif Uart_Printf("init info struct\n"); if (info_ptr != NULL) png_info_init_4(&info_ptr, png_sizeof(png_info)); Uart_Printf("initialized\n"); return info_ptr; }
void png_info_init_4(png_info ** ptr_ptr, png_size_t png_info_struct_size) { png_info * info_ptr = * ptr_ptr; //png_debug(1, "in png_info_init_3"); if (info_ptr == NULL) return; /*if (png_sizeof(png_info) > png_info_struct_size) { png_destroy_struct_4(info_ptr); info_ptr = (png_info *)png_create_struct(PNG_STRUCT_INFO); *ptr_ptr = info_ptr; }*/ memset(info_ptr, 0, png_sizeof(png_info)); }
/* Allocate the memory for an info_struct for the application. We don't * really need the png_ptr, but it could potentially be useful in the * future. This should be used in favour of malloc(png_sizeof(png_info)) * and png_info_init() so that applications that want to use a shared * libpng don't have to be recompiled if png_info changes size. */ png_infop PNGAPI png_create_info_struct(png_structp png_ptr) { png_infop info_ptr; png_debug(1, "in png_create_info_struct\n"); if(png_ptr == NULL) return (NULL); #ifdef PNG_USER_MEM_SUPPORTED info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, png_ptr->malloc_fn, png_ptr->mem_ptr); #else info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); #endif if (info_ptr != NULL) png_info_init_3(&info_ptr, png_sizeof(png_info)); return (info_ptr); }
/* This is an internal routine to free any memory that the info struct is * pointing to before re-using it or freeing the struct itself. Recall * that png_free() checks for NULL pointers for us. */ void /* PRIVATE */ png_info_destroy(png_structp png_ptr, png_infop info_ptr) { png_debug(1, "in png_info_destroy\n"); png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) if (png_ptr->num_chunk_list) { png_free(png_ptr, png_ptr->chunk_list); png_ptr->chunk_list=NULL; png_ptr->num_chunk_list=0; } #endif png_info_init_3(&info_ptr, png_sizeof(png_info)); }
void PNGAPI png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time) { png_debug1(1, "in %s storage function", "tIME"); if (png_ptr == NULL || info_ptr == NULL || (png_ptr->mode & PNG_WROTE_tIME)) return; if (mod_time->month == 0 || mod_time->month > 12 || mod_time->day == 0 || mod_time->day > 31 || mod_time->hour > 23 || mod_time->minute > 59 || mod_time->second > 60) { png_warning(png_ptr, "Ignoring invalid time value"); return; } png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); info_ptr->valid |= PNG_INFO_tIME; }
void PNGAPI png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist) { int i; png_debug1(1, "in %s storage function", "hIST"); if (png_ptr == NULL || info_ptr == NULL) return; if (info_ptr->num_palette == 0 || info_ptr->num_palette > PNG_MAX_PALETTE_LENGTH) { png_warning(png_ptr, "Invalid palette size, hIST allocation skipped"); return; } png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in * version 1.2.1 */ png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)); if (png_ptr->hist == NULL) { png_warning(png_ptr, "Insufficient memory for hIST chunk data"); return; } for (i = 0; i < info_ptr->num_palette; i++) png_ptr->hist[i] = hist[i]; info_ptr->hist = png_ptr->hist; info_ptr->valid |= PNG_INFO_hIST; info_ptr->free_me |= PNG_FREE_HIST; }
void wrPng(BYTE *bits, int w, int h, int line, FILE *f) { png_structp png_ptr; png_infop info_ptr; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(png_ptr){ info_ptr = png_create_info_struct(png_ptr); if(info_ptr){ if(!setjmp(png_jmpbuf(png_ptr))){ png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, w, h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); BYTE **row_pointers = (BYTE**)png_malloc(png_ptr, h*png_sizeof(png_bytep)); for(int i=0; i<h; i++){ row_pointers[i]= bits+(h-i-1)*line; } png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_BGR, 0); png_free(png_ptr, row_pointers); } } png_destroy_write_struct(&png_ptr, &info_ptr); } }
void /* PRIVATE */ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { png_size_t text_size; if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) text_size = png_ptr->buffer_size; else text_size = png_ptr->current_text_left; png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { png_textp text_ptr; png_charp text; png_charp key; int ret; png_size_t text_size, key_size; if (png_ptr->buffer_size < 4) { png_push_save_buffer(png_ptr); return; } png_push_crc_finish(png_ptr); key = png_ptr->current_text; for (text = key; *text; text++) /* empty loop */ ; /* zTXt can't have zero text */ if (text >= key + png_ptr->current_text_size) { png_ptr->current_text = NULL; png_free(png_ptr, key); return; } text++; if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */ { png_ptr->current_text = NULL; png_free(png_ptr, key); return; } text++; png_ptr->zstream.next_in = (png_bytep )text; png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - (text - key)); png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; key_size = text - key; text_size = 0; text = NULL; ret = Z_STREAM_END; while (png_ptr->zstream.avail_in) { ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); if (ret != Z_OK && ret != Z_STREAM_END) { inflateReset(&png_ptr->zstream); png_ptr->zstream.avail_in = 0; png_ptr->current_text = NULL; png_free(png_ptr, key); png_free(png_ptr, text); return; } if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) { if (text == NULL) { text = (png_charp)png_malloc(png_ptr, (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + key_size + 1)); png_memcpy(text + key_size, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); png_memcpy(text, key, key_size); text_size = key_size + png_ptr->zbuf_size - png_ptr->zstream.avail_out; *(text + text_size) = '\0'; } else { png_charp tmp; tmp = text; text = (png_charp)png_malloc(png_ptr, text_size + (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1)); png_memcpy(text, tmp, text_size); png_free(png_ptr, tmp); png_memcpy(text + text_size, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; *(text + text_size) = '\0'; } if (ret != Z_STREAM_END) { png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } } else { break; } if (ret == Z_STREAM_END) break; } inflateReset(&png_ptr->zstream); png_ptr->zstream.avail_in = 0; if (ret != Z_STREAM_END) { png_ptr->current_text = NULL; png_free(png_ptr, key); png_free(png_ptr, text); return; } png_ptr->current_text = NULL; png_free(png_ptr, key); key = text; text += key_size; text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)png_sizeof(png_text)); text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; text_ptr->key = key; #ifdef PNG_iTXt_SUPPORTED text_ptr->lang = NULL; text_ptr->lang_key = NULL; #endif text_ptr->text = text; ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); png_free(png_ptr, key); png_free(png_ptr, text_ptr); if (ret) png_warning(png_ptr, "Insufficient memory to store text chunk."); } }
void /* PRIVATE */ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { png_size_t text_size; if (png_ptr->buffer_size < png_ptr->current_text_left) text_size = png_ptr->buffer_size; else text_size = png_ptr->current_text_left; png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { png_textp text_ptr; png_charp text; png_charp key; int ret; if (png_ptr->buffer_size < 4) { png_push_save_buffer(png_ptr); return; } png_push_crc_finish(png_ptr); #if defined(PNG_MAX_MALLOC_64K) if (png_ptr->skip_length) return; #endif key = png_ptr->current_text; for (text = key; *text; text++) /* empty loop */ ; if (text < key + png_ptr->current_text_size) text++; text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)png_sizeof(png_text)); text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; text_ptr->key = key; #ifdef PNG_iTXt_SUPPORTED text_ptr->lang = NULL; text_ptr->lang_key = NULL; #endif text_ptr->text = text; ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); png_free(png_ptr, key); png_free(png_ptr, text_ptr); png_ptr->current_text = NULL; if (ret) png_warning(png_ptr, "Insufficient memory to store text chunk."); } }
void PNGAPI png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, png_size_t png_struct_size) { #ifdef PNG_SETJMP_SUPPORTED jmp_buf tmp_jmp; /* to save current jump buffer */ #endif int i=0; png_structp png_ptr=*ptr_ptr; if(png_ptr == NULL) return; do { if(user_png_ver[i] != png_libpng_ver[i]) { #ifdef PNG_LEGACY_SUPPORTED png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; #else png_ptr->warning_fn=NULL; png_warning(png_ptr, "Application uses deprecated png_read_init() and should be recompiled."); break; #endif } } while (png_libpng_ver[i++]); png_debug(1, "in png_read_init_3\n"); #ifdef PNG_SETJMP_SUPPORTED /* save jump buffer and error functions */ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf)); #endif if(png_sizeof(png_struct) > png_struct_size) { png_destroy_struct(png_ptr); *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); png_ptr = *ptr_ptr; } /* reset all variables to 0 */ png_memset(png_ptr, 0, png_sizeof (png_struct)); #ifdef PNG_SETJMP_SUPPORTED /* restore jump buffer */ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf)); #endif /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break; case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break; default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); }
/* Alternate create PNG structure for reading, and allocate any memory needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ png_structp png_ptr; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif int i; png_debug(1, "in png_create_read_struct\n"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif if (png_ptr == NULL) return (NULL); #if !defined(PNG_1_0_X) #ifdef PNG_ASSEMBLER_CODE_SUPPORTED png_init_mmx_flags(png_ptr); /* 1.2.0 addition */ #endif #endif /* PNG_1_0_X */ /* added at libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED png_ptr->user_width_max=PNG_USER_WIDTH_MAX; png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; #endif #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_ptr->jmpbuf)) #endif { png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf=NULL; #ifdef PNG_USER_MEM_SUPPORTED png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else png_destroy_struct((png_voidp)png_ptr); #endif return (NULL); } #ifdef USE_FAR_KEYWORD png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #endif #endif #ifdef PNG_USER_MEM_SUPPORTED png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); i=0; do { if(user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) char msg[80]; if (user_png_ver) { sprintf(msg, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } sprintf(msg, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags=0; #endif png_error(png_ptr, "Incompatible libpng version in application and library"); } } /* initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size); png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break; default: png_error(png_ptr, "Unknown zlib error"); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) PNG_ABORT(); png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf)); #else if (setjmp(png_ptr->jmpbuf)) PNG_ABORT(); #endif #endif return (png_ptr); }
/* Test one file */ int test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) { static png_FILE_p fpin; static png_FILE_p fpout; /* "static" prevents setjmp corruption */ png_structp read_ptr; png_infop read_info_ptr, end_info_ptr; #ifdef PNG_WRITE_SUPPORTED png_structp write_ptr; png_infop write_info_ptr; png_infop write_end_info_ptr; #else png_structp write_ptr = NULL; png_infop write_info_ptr = NULL; png_infop write_end_info_ptr = NULL; #endif png_bytep row_buf; png_uint_32 y; png_uint_32 width, height; int num_pass, pass; int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif #if defined(_WIN32_WCE) TCHAR path[MAX_PATH]; #endif char inbuf[256], outbuf[256]; row_buf = NULL; #if defined(_WIN32_WCE) MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) #else if ((fpin = fopen(inname, "rb")) == NULL) #endif { fprintf(STDERR, "Could not find input file %s\n", inname); return (1); } #if defined(_WIN32_WCE) MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE) #else if ((fpout = fopen(outname, "wb")) == NULL) #endif { fprintf(STDERR, "Could not open output file %s\n", outname); FCLOSE(fpin); return (1); } png_debug(0, "Allocating read and write structures\n"); #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); #endif #ifdef PNG_WRITE_SUPPORTED #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); #else write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, png_error_ptr_NULL, png_error_ptr_NULL); #endif #if defined(PNG_NO_STDIO) png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, pngtest_warning); #endif #endif png_debug(0, "Allocating read_info, write_info and end_info structures\n"); read_info_ptr = png_create_info_struct(read_ptr); end_info_ptr = png_create_info_struct(read_ptr); #ifdef PNG_WRITE_SUPPORTED write_info_ptr = png_create_info_struct(write_ptr); write_end_info_ptr = png_create_info_struct(write_ptr); #endif #ifdef PNG_SETJMP_SUPPORTED png_debug(0, "Setting jmpbuf for read struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(read_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); if (row_buf) png_free(read_ptr, row_buf); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); #ifdef PNG_WRITE_SUPPORTED png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif FCLOSE(fpin); FCLOSE(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf)); #endif #ifdef PNG_WRITE_SUPPORTED png_debug(0, "Setting jmpbuf for write struct\n"); #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(write_ptr))) #endif { fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr); #ifdef PNG_WRITE_SUPPORTED png_destroy_write_struct(&write_ptr, &write_info_ptr); #endif FCLOSE(fpin); FCLOSE(fpout); return (1); } #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf)); #endif #endif #endif png_debug(0, "Initializing input and output streams\n"); #if !defined(PNG_NO_STDIO) png_init_io(read_ptr, fpin); # ifdef PNG_WRITE_SUPPORTED png_init_io(write_ptr, fpout); # endif #else png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); # ifdef PNG_WRITE_SUPPORTED png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, # if defined(PNG_WRITE_FLUSH_SUPPORTED) pngtest_flush); # else NULL); # endif # endif #endif if(status_dots_requested == 1) { #ifdef PNG_WRITE_SUPPORTED png_set_write_status_fn(write_ptr, write_row_callback); #endif png_set_read_status_fn(read_ptr, read_row_callback); } else { #ifdef PNG_WRITE_SUPPORTED png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); #endif png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); } #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) { int i; for(i=0; i<256; i++) filters_used[i]=0; png_set_read_user_transform_fn(read_ptr, count_filters); } #endif #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) zero_samples=0; png_set_write_user_transform_fn(write_ptr, count_zero_samples); #endif #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) # ifndef PNG_HANDLE_CHUNK_ALWAYS # define PNG_HANDLE_CHUNK_ALWAYS 3 # endif png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, png_bytep_NULL, 0); #endif #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) # ifndef PNG_HANDLE_CHUNK_IF_SAFE # define PNG_HANDLE_CHUNK_IF_SAFE 2 # endif png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, png_bytep_NULL, 0); #endif png_debug(0, "Reading info struct\n"); png_read_info(read_ptr, read_info_ptr); png_debug(0, "Transferring info struct\n"); { int interlace_type, compression_type, filter_type; if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, &filter_type)) { png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, #if defined(PNG_WRITE_INTERLACING_SUPPORTED) color_type, interlace_type, compression_type, filter_type); #else color_type, PNG_INTERLACE_NONE, compression_type, filter_type); #endif } }
void PNGAPI png_read_png(png_structp png_ptr, png_infop info_ptr, int transforms, voidp params) { int row; if (png_ptr == NULL) return; /* png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error(png_ptr, "Image is too high to process with png_read_png()"); /* -------------- image transformations start here ------------------- */ #ifdef PNG_READ_16_TO_8_SUPPORTED /* Tell libpng to strip 16 bit/color files down to 8 bits per color. */ if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); #endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED /* Strip alpha bytes from the input data without combining with * the background (not recommended). */ if (transforms & PNG_TRANSFORM_STRIP_ALPHA) png_set_strip_alpha(png_ptr); #endif #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single * byte into separate bytes (useful for paletted and grayscale images). */ if (transforms & PNG_TRANSFORM_PACKING) png_set_packing(png_ptr); #endif #ifdef PNG_READ_PACKSWAP_SUPPORTED /* Change the order of packed pixels to least significant bit first * (not useful if you are using png_set_packing). */ if (transforms & PNG_TRANSFORM_PACKSWAP) png_set_packswap(png_ptr); #endif #ifdef PNG_READ_EXPAND_SUPPORTED /* Expand paletted colors into true RGB triplets * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel * Expand paletted or RGB images with transparency to full alpha * channels so the data will be available as RGBA quartets. */ if (transforms & PNG_TRANSFORM_EXPAND) if ((png_ptr->bit_depth < 8) || (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) png_set_expand(png_ptr); #endif /* We don't handle background color or gamma transformation or quantizing. */ #ifdef PNG_READ_INVERT_SUPPORTED /* Invert monochrome files to have 0 as white and 1 as black */ if (transforms & PNG_TRANSFORM_INVERT_MONO) png_set_invert_mono(png_ptr); #endif #ifdef PNG_READ_SHIFT_SUPPORTED /* If you want to shift the pixel values from the range [0,255] or * [0,65535] to the original [0,7] or [0,31], or whatever range the * colors were originally in: */ if ((transforms & PNG_TRANSFORM_SHIFT) && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { png_color_8p sig_bit; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); } #endif #ifdef PNG_READ_BGR_SUPPORTED /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ if (transforms & PNG_TRANSFORM_BGR) png_set_bgr(png_ptr); #endif #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ if (transforms & PNG_TRANSFORM_SWAP_ALPHA) png_set_swap_alpha(png_ptr); #endif #ifdef PNG_READ_SWAP_SUPPORTED /* Swap bytes of 16 bit files to least significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif /* Added at libpng-1.2.41 */ #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED /* Invert the alpha channel from opacity to transparency */ if (transforms & PNG_TRANSFORM_INVERT_ALPHA) png_set_invert_alpha(png_ptr); #endif /* Added at libpng-1.2.41 */ #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* Expand grayscale image to RGB */ if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) png_set_gray_to_rgb(png_ptr); #endif /* We don't handle adding filler bytes */ /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (i.e., you selected such a transform above). */ png_read_update_info(png_ptr, info_ptr); /* -------------- image transformations end here ------------------- */ png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); if (info_ptr->row_pointers == NULL) { png_uint_32 iptr; info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, info_ptr->height * png_sizeof(png_bytep)); for (iptr=0; iptr<info_ptr->height; iptr++) info_ptr->row_pointers[iptr] = NULL; info_ptr->free_me |= PNG_FREE_ROWS; for (row = 0; row < (int)info_ptr->height; row++) info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, info_ptr->row_pointers); info_ptr->valid |= PNG_INFO_IDAT; /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ png_read_end(png_ptr, info_ptr); transforms = transforms; /* Quiet compiler warnings */ params = params; }
// Write a png file; size of image: (width * nbytes) * height bool write_png(char *file_name, int width, int height, int nbytes, UCHAR *image) { int bit_depth = 8; FILE *fp; png_structp png_ptr; png_infop info_ptr; fp = fopen(file_name, "wb"); if (fp == NULL) return false; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return false; } // Allocate/initialize the image information data info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, png_infopp_NULL); return false; } // Set error handling. REQUIRED if you aren't supplying your own // error handling functions in the png_create_write_struct() call. if (setjmp(png_jmpbuf(png_ptr))) { fclose(fp); // If we get here, we had a problem writing the file png_destroy_write_struct(&png_ptr, &info_ptr); return false; } // I/O initialization method: using standard C streams png_init_io(png_ptr, fp); // Set the image information here. Width and height are up to 2^31, // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED if (nbytes == 4) png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32)height, bit_depth, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); else if (nbytes == 3) png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32)height, bit_depth, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); else if (nbytes == 1) png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32)height, bit_depth, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_write_info(png_ptr, info_ptr); // Write the file header information. png_bytep *row_pointers = NULL; row_pointers = (png_bytep*)malloc( height * sizeof(png_bytep) ); if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) png_error (png_ptr, "Image is too tall to process in memory"); for (int k = 0; k < height; k++) row_pointers[k] = (png_bytep)(image + k * width * nbytes); //for (int k = 0; k < height; k++) // for (int i = 0; i < width; i++) { // memset(row_pointers[k] + nbytes * i + 0, 55, 1); // memset(row_pointers[k] + nbytes * i + 1, 55, 1); // } // Write a few rows of image data // png_write_rows(png_ptr, row_pointers, height); // Write out the entire image data in one call png_write_image(png_ptr, row_pointers); // It is REQUIRED to call this to finish writing the rest of the file png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); free(row_pointers); row_pointers = NULL; fclose(fp); return true; }
void PNGAPI png_set_sPLT(png_structp png_ptr, png_infop info_ptr, png_const_sPLT_tp entries, int nentries) /* * entries - array of png_sPLT_t structures * to be added to the list of palettes * in the info structure. * * nentries - number of palette structures to be * added. */ { png_sPLT_tp np; int i; if (png_ptr == NULL || info_ptr == NULL) return; if (nentries < 0 || nentries > INT_MAX-info_ptr->splt_palettes_num || (unsigned int)/*SAFE*/(nentries +/*SAFE*/ info_ptr->splt_palettes_num) >= PNG_SIZE_MAX/png_sizeof(png_sPLT_t)) np=NULL; else np = (png_sPLT_tp)png_malloc_warn(png_ptr, (info_ptr->splt_palettes_num + nentries) * (png_size_t)png_sizeof(png_sPLT_t)); if (np == NULL) { png_warning(png_ptr, "No memory for sPLT palettes"); return; } png_memcpy(np, info_ptr->splt_palettes, info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); png_free(png_ptr, info_ptr->splt_palettes); info_ptr->splt_palettes=NULL; for (i = 0; i < nentries; i++) { png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; png_const_sPLT_tp from = entries + i; png_size_t length; length = png_strlen(from->name) + 1; to->name = (png_charp)png_malloc_warn(png_ptr, length); if (to->name == NULL) { png_warning(png_ptr, "Out of memory while processing sPLT chunk"); continue; } png_memcpy(to->name, from->name, length); to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, from->nentries * png_sizeof(png_sPLT_entry)); if (to->entries == NULL) { png_warning(png_ptr, "Out of memory while processing sPLT chunk"); png_free(png_ptr, to->name); to->name = NULL; continue; } png_memcpy(to->entries, from->entries, from->nentries * png_sizeof(png_sPLT_entry)); to->nentries = from->nentries; to->depth = from->depth; } info_ptr->splt_palettes = np; info_ptr->splt_palettes_num += nentries; info_ptr->valid |= PNG_INFO_sPLT; info_ptr->free_me |= PNG_FREE_SPLT; }
int /* PRIVATE */ png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr, int num_text) { int i; png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : (unsigned long)png_ptr->chunk_name); if (png_ptr == NULL || info_ptr == NULL || num_text == 0) return(0); /* Make sure we have enough space in the "text" array in info_struct * to hold all of the incoming text_ptr objects. */ if (num_text < 0 || num_text > INT_MAX - info_ptr->num_text - 8 || (unsigned int)/*SAFE*/(num_text +/*SAFE*/ info_ptr->num_text + 8) >= PNG_SIZE_MAX/png_sizeof(png_text)) { png_warning(png_ptr, "too many text chunks"); return(0); } if (info_ptr->num_text + num_text > info_ptr->max_text) { int old_max_text = info_ptr->max_text; int old_num_text = info_ptr->num_text; if (info_ptr->text != NULL) { png_textp old_text; info_ptr->max_text = info_ptr->num_text + num_text + 8; old_text = info_ptr->text; info_ptr->text = (png_textp)png_malloc_warn(png_ptr, (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); if (info_ptr->text == NULL) { /* Restore to previous condition */ info_ptr->max_text = old_max_text; info_ptr->text = old_text; return(1); } png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text * png_sizeof(png_text))); png_free(png_ptr, old_text); } else { info_ptr->max_text = num_text + 8; info_ptr->num_text = 0; info_ptr->text = (png_textp)png_malloc_warn(png_ptr, (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); if (info_ptr->text == NULL) { /* Restore to previous condition */ info_ptr->num_text = old_num_text; info_ptr->max_text = old_max_text; return(1); } info_ptr->free_me |= PNG_FREE_TEXT; } png_debug1(3, "allocated %d entries for info_ptr->text", info_ptr->max_text); } for (i = 0; i < num_text; i++) { png_size_t text_length, key_len; png_size_t lang_len, lang_key_len; png_textp textp = &(info_ptr->text[info_ptr->num_text]); if (text_ptr[i].key == NULL) continue; if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) { png_warning(png_ptr, "text compression mode is out of range"); continue; } key_len = png_strlen(text_ptr[i].key); if (text_ptr[i].compression <= 0) { lang_len = 0; lang_key_len = 0; } else # ifdef PNG_iTXt_SUPPORTED { /* Set iTXt data */ if (text_ptr[i].lang != NULL) lang_len = png_strlen(text_ptr[i].lang); else lang_len = 0; if (text_ptr[i].lang_key != NULL) lang_key_len = png_strlen(text_ptr[i].lang_key); else lang_key_len = 0; } # else /* PNG_iTXt_SUPPORTED */ { png_warning(png_ptr, "iTXt chunk not supported"); continue; } # endif if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') { text_length = 0; # ifdef PNG_iTXt_SUPPORTED if (text_ptr[i].compression > 0) textp->compression = PNG_ITXT_COMPRESSION_NONE; else # endif textp->compression = PNG_TEXT_COMPRESSION_NONE; } else { text_length = png_strlen(text_ptr[i].text); textp->compression = text_ptr[i].compression; } textp->key = (png_charp)png_malloc_warn(png_ptr, (png_size_t) (key_len + text_length + lang_len + lang_key_len + 4)); if (textp->key == NULL) return(1); png_debug2(2, "Allocated %lu bytes at %p in png_set_text", (unsigned long)(png_uint_32) (key_len + lang_len + lang_key_len + text_length + 4), textp->key); png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); *(textp->key + key_len) = '\0'; if (text_ptr[i].compression > 0) { textp->lang = textp->key + key_len + 1; png_memcpy(textp->lang, text_ptr[i].lang, lang_len); *(textp->lang + lang_len) = '\0'; textp->lang_key = textp->lang + lang_len + 1; png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); *(textp->lang_key + lang_key_len) = '\0'; textp->text = textp->lang_key + lang_key_len + 1; } else { textp->lang=NULL; textp->lang_key=NULL; textp->text = textp->key + key_len + 1; } if (text_length) png_memcpy(textp->text, text_ptr[i].text, (png_size_t)(text_length)); *(textp->text + text_length) = '\0'; # ifdef PNG_iTXt_SUPPORTED if (textp->compression > 0) { textp->text_length = 0; textp->itxt_length = text_length; } else # endif { textp->text_length = text_length; textp->itxt_length = 0; } info_ptr->num_text++; png_debug1(3, "transferred text chunk %d", info_ptr->num_text); } return(0); }
void PNGAPI png_set_pCAL(png_structp png_ptr, png_infop info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_const_charp units, png_charpp params) { png_size_t length; int i; png_debug1(1, "in %s storage function", "pCAL"); if (png_ptr == NULL || info_ptr == NULL) return; length = png_strlen(purpose) + 1; png_debug1(3, "allocating purpose for info (%lu bytes)", (unsigned long)length); /* TODO: validate format of calibration name and unit name */ /* Check that the type matches the specification. */ if (type < 0 || type > 3) png_error(png_ptr, "Invalid pCAL equation type"); /* Validate params[nparams] */ for (i=0; i<nparams; ++i) if (!png_check_fp_string(params[i], png_strlen(params[i]))) png_error(png_ptr, "Invalid format for pCAL parameter"); info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_purpose == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL purpose"); return; } png_memcpy(info_ptr->pcal_purpose, purpose, length); png_debug(3, "storing X0, X1, type, and nparams in info"); info_ptr->pcal_X0 = X0; info_ptr->pcal_X1 = X1; info_ptr->pcal_type = (png_byte)type; info_ptr->pcal_nparams = (png_byte)nparams; length = png_strlen(units) + 1; png_debug1(3, "allocating units for info (%lu bytes)", (unsigned long)length); info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_units == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL units"); return; } png_memcpy(info_ptr->pcal_units, units, length); info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, (png_size_t)((nparams + 1) * png_sizeof(png_charp))); if (info_ptr->pcal_params == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL params"); return; } png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); for (i = 0; i < nparams; i++) { length = png_strlen(params[i]) + 1; png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, (unsigned long)length); info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_params[i] == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL parameter"); return; } png_memcpy(info_ptr->pcal_params[i], params[i], length); } info_ptr->valid |= PNG_INFO_pCAL; info_ptr->free_me |= PNG_FREE_PCAL; }
void PNGAPI png_set_unknown_chunks(png_structp png_ptr, png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) { png_unknown_chunkp np; int i; if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) return; if (num_unknowns < 0 || num_unknowns > INT_MAX-info_ptr->unknown_chunks_num || (unsigned int)/*SAFE*/(num_unknowns +/*SAFE*/ info_ptr->unknown_chunks_num) >= PNG_SIZE_MAX/png_sizeof(png_unknown_chunk)) np=NULL; else np = (png_unknown_chunkp)png_malloc_warn(png_ptr, (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) * png_sizeof(png_unknown_chunk)); if (np == NULL) { png_warning(png_ptr, "Out of memory while processing unknown chunk"); return; } png_memcpy(np, info_ptr->unknown_chunks, (png_size_t)info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk)); png_free(png_ptr, info_ptr->unknown_chunks); info_ptr->unknown_chunks = NULL; for (i = 0; i < num_unknowns; i++) { png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; png_const_unknown_chunkp from = unknowns + i; png_memcpy(to->name, from->name, png_sizeof(from->name)); to->name[png_sizeof(to->name)-1] = '\0'; to->size = from->size; /* Note our location in the read or write sequence */ to->location = (png_byte)(png_ptr->mode & 0xff); if (from->size == 0) to->data=NULL; else { to->data = (png_bytep)png_malloc_warn(png_ptr, (png_size_t)from->size); if (to->data == NULL) { png_warning(png_ptr, "Out of memory while processing unknown chunk"); to->size = 0; } else png_memcpy(to->data, from->data, from->size); } } info_ptr->unknown_chunks = np; info_ptr->unknown_chunks_num += num_unknowns; info_ptr->free_me |= PNG_FREE_UNKN; }
ImageReaderPNG::ImageType ImageReaderPNG::readData(const std::string& filePath, PNGInfra& infra, bool wantAlpha) { if (filePath.empty()) return eInvalid; infra.pFile = fopen(filePath.c_str(), "rb"); if (!infra.pFile) { fprintf(stderr, "Error opening file: %s\n", filePath.c_str()); return eInvalid; } unsigned char sig[8]; // check the signature fread(sig, 1, 8, infra.pFile); if (!png_check_sig(sig, 8)) { fprintf(stderr, "Cannot open file: %s - not a valid PNG file.\n", filePath.c_str()); fclose(infra.pFile); return eInvalid; } infra.pPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!infra.pPNG) { fclose(infra.pFile); return eInvalid; } infra.pInfo = png_create_info_struct(infra.pPNG); if (!infra.pInfo) { png_destroy_read_struct(&infra.pPNG, NULL, NULL); fclose(infra.pFile); return eInvalid; } if (setjmp(png_jmpbuf(infra.pPNG))) { png_destroy_read_struct(&infra.pPNG, &infra.pInfo, NULL); fclose(infra.pFile); return eInvalid; } png_init_io(infra.pPNG, infra.pFile); png_set_sig_bytes(infra.pPNG, 8); png_read_info(infra.pPNG, infra.pInfo); int colorType; int bitDepth, interlaceType, compressionType; png_get_IHDR(infra.pPNG, infra.pInfo, &infra.width, &infra.height, &bitDepth, &colorType, &interlaceType, &compressionType, NULL); if (colorType == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(infra.pPNG); if (png_get_valid(infra.pPNG, infra.pInfo, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(infra.pPNG); } if (bitDepth == 16) png_set_strip_16(infra.pPNG); ImageType type = eInvalid; if (!wantAlpha) { // add black Alpha if ((colorType & PNG_COLOR_MASK_ALPHA) == 0) png_set_add_alpha(infra.pPNG, 0xFF, PNG_FILLER_AFTER); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(infra.pPNG); else if (colorType != PNG_COLOR_TYPE_RGB && colorType != PNG_COLOR_TYPE_RGB_ALPHA) return eInvalid; type = eRGBA; } else { if (colorType == PNG_COLOR_TYPE_RGB_ALPHA) type = eRGBA; else if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) type = eA; else return eInvalid; } png_read_update_info(infra.pPNG, infra.pInfo); infra.pRows = new png_bytep[infra.height * png_sizeof(png_bytep)]; png_set_rows(infra.pPNG, infra.pInfo, infra.pRows); for (unsigned int i = 0; i < infra.height; i++) { infra.pRows[i] = new png_byte[png_get_rowbytes(infra.pPNG, infra.pInfo)]; } png_read_image(infra.pPNG, infra.pRows); png_read_end(infra.pPNG, infra.pInfo); return type; }
void /* PRIVATE */ png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) { if (png_ptr->buffer_size && png_ptr->current_text_left) { png_size_t text_size; if (png_ptr->buffer_size < png_ptr->current_text_left) text_size = png_ptr->buffer_size; else text_size = png_ptr->current_text_left; png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); png_ptr->current_text_left -= text_size; png_ptr->current_text_ptr += text_size; } if (!(png_ptr->current_text_left)) { png_textp text_ptr; png_charp key; int comp_flag; png_charp lang; png_charp lang_key; png_charp text; int ret; if (png_ptr->buffer_size < 4) { png_push_save_buffer(png_ptr); return; } png_push_crc_finish(png_ptr); #if defined(PNG_MAX_MALLOC_64K) if (png_ptr->skip_length) return; #endif key = png_ptr->current_text; for (lang = key; *lang; lang++) /* empty loop */ ; if (lang < key + png_ptr->current_text_size - 3) lang++; comp_flag = *lang++; lang++; /* skip comp_type, always zero */ for (lang_key = lang; *lang_key; lang_key++) /* empty loop */ ; lang_key++; /* skip NUL separator */ text=lang_key; if (lang_key < key + png_ptr->current_text_size - 1) { for (; *text; text++) /* empty loop */ ; } if (text < key + png_ptr->current_text_size) text++; text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)png_sizeof(png_text)); text_ptr->compression = comp_flag + 2; text_ptr->key = key; text_ptr->lang = lang; text_ptr->lang_key = lang_key; text_ptr->text = text; text_ptr->text_length = 0; text_ptr->itxt_length = png_strlen(text); ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); png_ptr->current_text = NULL; png_free(png_ptr, text_ptr); if (ret) png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); } }
/* This function is called when we haven't found a handler for this * chunk. If there isn't a problem with the chunk itself (ie a bad chunk * name or a critical chunk), the chunk is (currently) silently ignored. */ void /* PRIVATE */ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_uint_32 skip = 0; if (!(png_ptr->chunk_name[0] & 0x20)) { #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != PNG_HANDLE_CHUNK_ALWAYS #ifdef PNG_READ_USER_CHUNKS_SUPPORTED && png_ptr->read_user_chunk_fn == NULL #endif ) #endif png_chunk_error(png_ptr, "unknown critical chunk"); info_ptr = info_ptr; /* To quiet some compiler warnings */ } #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) { #ifdef PNG_MAX_MALLOC_64K if (length > (png_uint_32)65535L) { png_warning(png_ptr, "unknown chunk too large to fit in memory"); skip = length - (png_uint_32)65535L; length = (png_uint_32)65535L; } #endif png_memcpy((png_charp)png_ptr->unknown_chunk.name, (png_charp)png_ptr->chunk_name, png_sizeof(png_ptr->unknown_chunk.name)); png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] = '\0'; png_ptr->unknown_chunk.size = (png_size_t)length; if (length == 0) png_ptr->unknown_chunk.data = NULL; else { png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, (png_uint_32)length); png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); } #ifdef PNG_READ_USER_CHUNKS_SUPPORTED if (png_ptr->read_user_chunk_fn != NULL) { /* Callback to user unknown chunk handler */ int ret; ret = (*(png_ptr->read_user_chunk_fn)) (png_ptr, &png_ptr->unknown_chunk); if (ret < 0) png_chunk_error(png_ptr, "error in user chunk"); if (ret == 0) { if (!(png_ptr->chunk_name[0] & 0x20)) if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != PNG_HANDLE_CHUNK_ALWAYS) png_chunk_error(png_ptr, "unknown critical chunk"); png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); } } else #endif png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); png_free(png_ptr, png_ptr->unknown_chunk.data); png_ptr->unknown_chunk.data = NULL; } else #endif skip=length; png_push_crc_skip(png_ptr, skip); }
/** * @brief Write image data to file as PNG * @param filename Name of output file. * @param img Image data. * @param width Width of image. * @param height Height of image. */ static void WritePNG(const std::string &filename, const byte *img, const int width, const int height) { FILE *fp; png_structp png_ptr; png_infop info_ptr; /* open the file */ fp = fopen(filename.c_str(), "wb"); if (fp == NULL) { throw std::string("Cannot create file \"") + filename + std::string("\""); } /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, * you can supply NULL for the last three parameters. We also check that * the library version is compatible with the one used at compile time, * in case we are using dynamically linked libraries. REQUIRED. */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); throw std::string("Cannot create PNG write structure for file \"") + filename + std::string("\""); } /* Allocate/initialize the image information data. REQUIRED */ info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, png_infopp_NULL); throw std::string("Out of memory in RGBA::PNG::Write()"); } /* Set error handling. REQUIRED if you aren't supplying your own * error handling functions in the png_create_write_struct() call. */ if (setjmp(png_jmpbuf(png_ptr))) { /* If we get here, we had a problem reading the file */ fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw std::string("Could not set up error handling for PNG"); } /* set up the output control if you are using standard C streams */ png_init_io(png_ptr, fp); /* This is the easy way. Use it if you already have all the * image info living info in the structure. You could "|" many * PNG_TRANSFORM flags into the png_transforms integer here. */ // png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL); /* This is the hard way */ /* Set the image information here. Width and height are up to 2^31, * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED */ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); /* Write the file header information. REQUIRED */ png_write_info(png_ptr, info_ptr); /* If you want, you can write the info in two steps, in case you need to * write your private chunk ahead of PLTE: * * png_write_info_before_PLTE(write_ptr, write_info_ptr); * write_my_chunk(); * png_write_info(png_ptr, info_ptr); * * However, given the level of known- and unknown-chunk support in 1.1.0 * and up, this should no longer be necessary. */ /* Once we write out the header, the compression type on the text * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again * at the end. */ /* set up the transformations you want. Note that these are * all optional. Only call them if you want them. */ /* The easiest way to write the image (you may have a different memory * layout, however, so choose what fits your needs best). You need to * use the first method if you aren't handling interlacing yourself. */ png_bytep *row_pointers = new png_bytep[height]; if( (png_uint_32)height > (png_uint_32)(PNG_UINT_32_MAX/png_sizeof(png_bytep)) ) { fclose(fp); png_destroy_write_struct(&png_ptr, &info_ptr); throw std::string("Image is too tall to process in memory"); } for(int k = 0; k < height; k++) row_pointers[k] = (byte*)img + k*width*4; /* write out the entire image data in one call */ png_write_image(png_ptr, row_pointers); /* You can write optional chunks like tEXt, zTXt, and tIME at the end * as well. Shouldn't be necessary in 1.1.0 and up as all the public * chunks are supported and you can use png_set_unknown_chunks() to * register unknown chunks into the info structure to be written out. */ /* It is REQUIRED to call this to finish writing the rest of the file */ png_write_end(png_ptr, info_ptr); /* clean up after the write, and free any memory allocated */ png_destroy_write_struct(&png_ptr, &info_ptr); delete[] row_pointers; row_pointers = NULL; /* close the file */ fclose(fp); }
bool save_heightmap_png(long double lat, long double lon, long double span_h, long double span_w, const char *outfile) { int x1, x2, y1, y2; bool ret = false; FILE *fp = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; size_t x, y, w, h, skip; png_bytepp row_pointers; png_bytep row; int16_t elevation, height; /* Pointer to humongous (7GB) S_MAPW x S_MAPH 16-bit map data (see map.c) */ int16_t *mapp = (int16_t *)map[0]; /* Map longitude/latidude to pixel coordinates in source image */ x1 = ((lon + 180.0) / (long double)360) * S_MAPW; x2 = (((lon + span_w) + 180.0) / (long double)360) * S_MAPW - 1; y1 = ((90 - lat) / (long double)180) * S_MAPH; y2 = ((90 - (lat - span_h)) / (long double)180) * S_MAPH - 1; w = x2 - x1 + 1; h = y2 - y1 + 1; printf("%s: %dx%d ... ", outfile, (int)w, (int)h); fflush(stdout); /* Advance mapp to first pixel */ mapp += (uint64_t)x1 + (uint64_t)S_MAPW * (uint64_t)y1; /* Skip this many int16_t:s to get to next line */ skip = S_MAPW - w; /* libpng stuff below */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { goto out; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); goto out; } if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); goto out; } /* Specify 16-bit grayscale in png header */ png_set_IHDR(png_ptr, info_ptr, w, h, 16, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Alloc mem for png image data */ row_pointers = (png_bytepp)png_malloc(png_ptr, h * png_sizeof(png_bytep)); for (y = 0; y < h; y++) { row_pointers[y] = png_malloc(png_ptr, w * 2); } /* Copy image data from mapp to row_pointers */ for (y = 0; y < h; y++) { row = row_pointers[y]; for (x = 0; x < w; x++) { /* Read 2 big endian source bytes */ elevation = *mapp++; /* Clamp negative heights to 0 */ height = ntohs(elevation); /* swap bytes if little endian */ if (height < 0) { elevation = 0; } /* Write 2 bytes to destination */ *row++ = (png_byte)(elevation & 0xff); *row++ = (png_byte)(elevation >> 8); } mapp += skip; } /* Write image data to fp */ if (!(fp = fopen(outfile, "w"))) { perror(outfile); goto out2; } png_init_io(png_ptr, fp); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); ret = true; out2: /* Cleanup. */ for (y = 0; y < h; y++) { png_free(png_ptr, row_pointers[y]); } png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); if (fp) { fclose(fp); } out: if (ret) { puts("ok"); } else { puts("fail"); } return ret; }
/* Free all memory used by the read (old method) */ void /* PRIVATE */ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr) { #ifdef PNG_SETJMP_SUPPORTED jmp_buf tmp_jmp; #endif png_error_ptr error_fn; png_error_ptr warning_fn; png_voidp error_ptr; #ifdef PNG_USER_MEM_SUPPORTED png_free_ptr free_fn; #endif png_debug(1, "in png_read_destroy"); if (info_ptr != NULL) png_info_destroy(png_ptr, info_ptr); if (end_info_ptr != NULL) png_info_destroy(png_ptr, end_info_ptr); png_free(png_ptr, png_ptr->zbuf); png_free(png_ptr, png_ptr->big_row_buf); png_free(png_ptr, png_ptr->prev_row); png_free(png_ptr, png_ptr->chunkdata); #ifdef PNG_READ_QUANTIZE_SUPPORTED png_free(png_ptr, png_ptr->palette_lookup); png_free(png_ptr, png_ptr->quantize_index); #endif #ifdef PNG_READ_GAMMA_SUPPORTED png_free(png_ptr, png_ptr->gamma_table); #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED png_free(png_ptr, png_ptr->gamma_from_1); png_free(png_ptr, png_ptr->gamma_to_1); #endif if (png_ptr->free_me & PNG_FREE_PLTE) png_zfree(png_ptr, png_ptr->palette); png_ptr->free_me &= ~PNG_FREE_PLTE; #if defined(PNG_tRNS_SUPPORTED) || \ defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) if (png_ptr->free_me & PNG_FREE_TRNS) png_free(png_ptr, png_ptr->trans_alpha); png_ptr->free_me &= ~PNG_FREE_TRNS; #endif #ifdef PNG_READ_hIST_SUPPORTED if (png_ptr->free_me & PNG_FREE_HIST) png_free(png_ptr, png_ptr->hist); png_ptr->free_me &= ~PNG_FREE_HIST; #endif #ifdef PNG_READ_GAMMA_SUPPORTED if (png_ptr->gamma_16_table != NULL) { int i; int istop = (1 << (8 - png_ptr->gamma_shift)); for (i = 0; i < istop; i++) { png_free(png_ptr, png_ptr->gamma_16_table[i]); } png_free(png_ptr, png_ptr->gamma_16_table); } #ifdef PNG_READ_BACKGROUND_SUPPORTED if (png_ptr->gamma_16_from_1 != NULL) { int i; int istop = (1 << (8 - png_ptr->gamma_shift)); for (i = 0; i < istop; i++) { png_free(png_ptr, png_ptr->gamma_16_from_1[i]); } png_free(png_ptr, png_ptr->gamma_16_from_1); } if (png_ptr->gamma_16_to_1 != NULL) { int i; int istop = (1 << (8 - png_ptr->gamma_shift)); for (i = 0; i < istop; i++) { png_free(png_ptr, png_ptr->gamma_16_to_1[i]); } png_free(png_ptr, png_ptr->gamma_16_to_1); } #endif #endif #ifdef PNG_TIME_RFC1123_SUPPORTED png_free(png_ptr, png_ptr->time_buffer); #endif inflateEnd(&png_ptr->zstream); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED png_free(png_ptr, png_ptr->save_buffer); #endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED #ifdef PNG_TEXT_SUPPORTED png_free(png_ptr, png_ptr->current_text); #endif /* PNG_TEXT_SUPPORTED */ #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ /* Save the important info out of the png_struct, in case it is * being used again. */ #ifdef PNG_SETJMP_SUPPORTED png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); #endif error_fn = png_ptr->error_fn; warning_fn = png_ptr->warning_fn; error_ptr = png_ptr->error_ptr; #ifdef PNG_USER_MEM_SUPPORTED free_fn = png_ptr->free_fn; #endif png_memset(png_ptr, 0, png_sizeof(png_struct)); png_ptr->error_fn = error_fn; png_ptr->warning_fn = warning_fn; png_ptr->error_ptr = error_ptr; #ifdef PNG_USER_MEM_SUPPORTED png_ptr->free_fn = free_fn; #endif #ifdef PNG_SETJMP_SUPPORTED png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); #endif }
png_voidp PNGAPI png_malloc_default(png_structp png_ptr, png_uint_32 size) { png_voidp ret; #endif /* PNG_USER_MEM_SUPPORTED */ if (png_ptr == NULL || size == 0) return (NULL); #ifdef PNG_MAX_MALLOC_64K if (size > (png_uint_32)65536L) { png_warning(png_ptr, "Cannot Allocate > 64K"); ret = NULL; } else #endif if (size != (size_t)size) ret = NULL; else if (size == (png_uint_32)65536L) { if (png_ptr->offset_table == NULL) { /* Try to see if we need to do any of this fancy stuff */ ret = farmalloc(size); if (ret == NULL || ((png_size_t)ret & 0xffff)) { int num_blocks; png_uint_32 total_size; png_bytep table; int i; png_byte huge * hptr; if (ret != NULL) { farfree(ret); ret = NULL; } if (png_ptr->zlib_window_bits > 14) num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); else num_blocks = 1; if (png_ptr->zlib_mem_level >= 7) num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); else num_blocks++; total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; table = farmalloc(total_size); if (table == NULL) { #ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out Of Memory."); /* Note "O", "M" */ else png_warning(png_ptr, "Out Of Memory."); #endif return (NULL); } if ((png_size_t)table & 0xfff0) { #ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Farmalloc didn't return normalized pointer"); else png_warning(png_ptr, "Farmalloc didn't return normalized pointer"); #endif return (NULL); } png_ptr->offset_table = table; png_ptr->offset_table_ptr = farmalloc(num_blocks * png_sizeof(png_bytep)); if (png_ptr->offset_table_ptr == NULL) { #ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out Of memory."); /* Note "O", "m" */ else png_warning(png_ptr, "Out Of memory."); #endif return (NULL); } hptr = (png_byte huge *)table; if ((png_size_t)hptr & 0xf) { hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ } for (i = 0; i < num_blocks; i++) { png_ptr->offset_table_ptr[i] = (png_bytep)hptr; hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ } png_ptr->offset_table_number = num_blocks; png_ptr->offset_table_count = 0; png_ptr->offset_table_count_free = 0; } } if (png_ptr->offset_table_count >= png_ptr->offset_table_number) { #ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */ else png_warning(png_ptr, "Out of Memory."); #endif return (NULL); } ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; } else ret = farmalloc(size); #ifndef PNG_USER_MEM_SUPPORTED if (ret == NULL) { if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */ else png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */ } #endif return (ret); }
/* Alternate create PNG structure for reading, and allocate any memory * needed. */ png_structp PNGAPI png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn) { #endif /* PNG_USER_MEM_SUPPORTED */ #ifdef PNG_SETJMP_SUPPORTED volatile #endif png_structp png_ptr; volatile int png_cleanup_needed = 0; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD jmp_buf jmpbuf; #endif #endif int i; png_debug(1, "in png_create_read_struct"); #ifdef PNG_USER_MEM_SUPPORTED png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, malloc_fn, mem_ptr); #else png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); #endif if (png_ptr == NULL) return (NULL); /* Added at libpng-1.2.6 */ #ifdef PNG_USER_LIMITS_SUPPORTED png_ptr->user_width_max = PNG_USER_WIDTH_MAX; png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; # ifdef PNG_USER_CHUNK_CACHE_MAX /* Added at libpng-1.2.43 and 1.4.0 */ png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; # endif # ifdef PNG_SET_USER_CHUNK_MALLOC_MAX /* Added at libpng-1.2.43 and 1.4.1 */ png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; # endif #endif #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD if (setjmp(jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ #endif PNG_ABORT(); #ifdef USE_FAR_KEYWORD png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf)); #endif #endif /* PNG_SETJMP_SUPPORTED */ #ifdef PNG_USER_MEM_SUPPORTED png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); #endif png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); if (user_png_ver) { i = 0; do { if (user_png_ver[i] != png_libpng_ver[i]) png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; } while (png_libpng_ver[i++]); } else png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) { /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so * we must recompile any applications that use any older library version. * For versions after libpng 1.0, we will be compatible, so we need * only check the first digit. */ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || (user_png_ver[0] == '0' && user_png_ver[2] < '9')) { #ifdef PNG_STDIO_SUPPORTED char msg[80]; if (user_png_ver) { png_snprintf(msg, 80, "Application was compiled with png.h from libpng-%.20s", user_png_ver); png_warning(png_ptr, msg); } png_snprintf(msg, 80, "Application is running with png.c from libpng-%.20s", png_libpng_ver); png_warning(png_ptr, msg); #endif #ifdef PNG_ERROR_NUMBERS_SUPPORTED png_ptr->flags = 0; #endif png_warning(png_ptr, "Incompatible libpng version in application and library"); png_cleanup_needed = 1; } } if (!png_cleanup_needed) { /* Initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); if (png_ptr->zbuf == NULL) png_cleanup_needed = 1; } png_ptr->zstream.zalloc = png_zalloc; png_ptr->zstream.zfree = png_zfree; png_ptr->zstream.opaque = (voidpf)png_ptr; if (!png_cleanup_needed) { switch (inflateInit(&png_ptr->zstream)) { case Z_OK: /* Do nothing */ break; case Z_MEM_ERROR: case Z_STREAM_ERROR: png_warning(png_ptr, "zlib memory error"); png_cleanup_needed = 1; break; case Z_VERSION_ERROR: png_warning(png_ptr, "zlib version error"); png_cleanup_needed = 1; break; default: png_warning(png_ptr, "Unknown zlib error"); png_cleanup_needed = 1; } } if (png_cleanup_needed) { /* Clean up PNG structure and deallocate any memory. */ png_free(png_ptr, png_ptr->zbuf); png_ptr->zbuf = NULL; #ifdef PNG_USER_MEM_SUPPORTED png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, (png_voidp)mem_ptr); #else png_destroy_struct((png_voidp)png_ptr); #endif return (NULL); } png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_set_read_fn(png_ptr, NULL, NULL); return (png_ptr); }
cache Png_Create(int width, int height, int numpal, dPalette_t* pal, int bits, cache data, int lump, int* size) { int i = 0; int x = 0; int j = 0; cache image; cache out; cache* row_pointers; png_structp png_ptr; png_infop info_ptr; png_colorp palette; // setup png pointer png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if(png_ptr == NULL) { WGen_Complain("Png_Create: Failed getting png_ptr"); return NULL; } // setup info pointer info_ptr = png_create_info_struct(png_ptr); if(info_ptr == NULL) { png_destroy_write_struct(&png_ptr, NULL); WGen_Complain("Png_Create: Failed getting info_ptr"); return NULL; } // what does this do again? if(setjmp(png_jmpbuf(png_ptr))) { png_destroy_write_struct(&png_ptr, &info_ptr); WGen_Complain("Png_Create: Failed on setjmp"); return NULL; } // setup custom data writing procedure png_set_write_fn(png_ptr, NULL, Png_WriteData, NULL); // setup image png_set_IHDR( png_ptr, info_ptr, width, height, bits, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT); // setup palette palette = (png_colorp)Mem_Alloc((16 * numpal) * png_sizeof(png_color)); // copy dPalette_t data over to png_colorp for(x = 0, j = 0; x < numpal; x++) { for(i = 0; i < 16; i++) { palette[j].red = pal[j].r; palette[j].green = pal[j].g; palette[j].blue = pal[j].b; j++; } } i = 0; // add palette to png png_set_PLTE(png_ptr, info_ptr, palette, (16 * numpal)); // set transparent index if(palette[0].red == 0 && palette[0].green == 0 && palette[0].blue == 0) { char tmp[9]; strncpy(tmp, romWadFile.lump[lump].name, 8); tmp[0] -= (char)0x80; tmp[8] = 0; // Exempt these lumps if(strcmp(tmp, "FIRE") && /*strcmp(tmp, "USLEGAL") && strcmp(tmp, "TITLE") &&*/ strcmp(tmp, "EVIL") && /*strcmp(tmp, "IDCRED1") && strcmp(tmp, "WMSCRED1") &&*/ strcmp(tmp, "SPACE") && strcmp(tmp, "CLOUD") && strcmp(tmp, "FINAL")) png_set_tRNS(png_ptr, info_ptr, (png_bytep)&i, 1, NULL); } // add png info to data png_write_info(png_ptr, info_ptr); // add offset chunk if png is a sprite if(INSPRITELIST(lump)) { for(i = 0; i < spriteExCount; i++) { if(exSpriteLump[i].lumpRef == lump) { int offs[2]; offs[0] = WGen_Swap32(exSpriteLump[i].sprite.offsetx); offs[1] = WGen_Swap32(exSpriteLump[i].sprite.offsety); png_write_chunk(png_ptr, "grAb", (byte*)offs, 8); break; } } } // setup packing if needed png_set_packing(png_ptr); png_set_packswap(png_ptr); // copy data over image = data; row_pointers = (cache*)Mem_Alloc(sizeof(byte*) * height); for(i = 0; i < height; i++) { row_pointers[i] = (cache)Mem_Alloc(width); if(bits == 4) { for(j = 0; j < width; j += 2) { row_pointers[i][j] = *image & 0xf; row_pointers[i][j+1] = *image >> 4; image++; } } else { for(j = 0; j < width; j++) { row_pointers[i][j] = *image; image++; } } png_write_rows(png_ptr, &row_pointers[i], 1); }