From: Jiyong Min Date: Thu, 8 Mar 2018 01:30:16 +0000 (+0900) Subject: reading & writing png code refactoring X-Git-Tag: accepted/tizen/unified/20180315.061339~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=675194a6e6b5c33edc39ec932e5c2b379617edbc;p=platform%2Fcore%2Fmultimedia%2Flibmm-utility.git reading & writing png code refactoring Change-Id: I213c8c0f7b4475d1864d50410a1202b221e4d6b1 Signed-off-by: Jiyong Min --- diff --git a/packaging/libmm-utility.spec b/packaging/libmm-utility.spec index 45a8168..f8a10db 100755 --- a/packaging/libmm-utility.spec +++ b/packaging/libmm-utility.spec @@ -1,6 +1,6 @@ Name: libmm-utility Summary: Multimedia Framework Utility Library -Version: 0.1.19 +Version: 0.1.20 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/png/mm_util_png.c b/png/mm_util_png.c index 809cbf1..81c924a 100755 --- a/png/mm_util_png.c +++ b/png/mm_util_png.c @@ -38,16 +38,10 @@ typedef struct { int bit_depth; /**< Bit depth*/ int color_type; /**< Color type*/ int interlace_type; /**< Interlace type */ + int compression_type; /**< compression type */ int filter_type; /**< Filter type*/ - - void *data; - size_t size; - size_t rowbytes; /**< Number or bytes in each row*/ - - int transform; /**< Transform masks for decoding */ - int compression_level; /**< Compression level of encoding */ - int filter; /**< Filter */ -} png_data_s; + int filter; /**< Filter */ +} png_property_s; typedef struct { @@ -65,87 +59,109 @@ static void __user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) mm_util_error("%s", warning_msg); } -static void __dec_set_prop(png_data_s *png_data, png_structp png_ptr, png_infop info) +static void __read_data_fn(png_structp png_ptr, png_bytep data, png_size_t size) +{ + png_mem_s *png_mem_ptr = (png_mem_s *) png_get_io_ptr(png_ptr); + + if (png_mem_ptr == NULL || data == NULL) + return; + + if (png_mem_ptr->mem && size > 0) { + memcpy(data, png_mem_ptr->mem + png_mem_ptr->size, size); + png_mem_ptr->size += size; + } +} + +static void __flush_data_fn(png_structp png_ptr G_GNUC_UNUSED) +{ + /* do nothing */ +} + +static void __write_data_fn(png_structp png_ptr, png_bytep data, png_uint_32 length) +{ + png_mem_s *png_mem_ptr = (png_mem_s *) png_get_io_ptr(png_ptr); + + if (png_mem_ptr == NULL || data == NULL) + return; + + png_mem_ptr->mem = (void *)realloc(png_mem_ptr->mem, sizeof(png_bytep) * (png_mem_ptr->size + length)); + if (png_mem_ptr->mem) { + memcpy(png_mem_ptr->mem + png_mem_ptr->size, data, length); + png_mem_ptr->size += length; + } +} + +static void __get_property(png_property_s *png_prop, png_structp png_ptr, png_infop info_ptr) { png_color_16 *image_background = NULL; - mm_util_debug("__dec_set_prop"); + mm_util_fenter(); - png_read_info(png_ptr, info); + png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info, &png_data->width, &png_data->height, &png_data->bit_depth, &png_data->color_type, &png_data->interlace_type, NULL, &png_data->filter_type); + png_get_IHDR(png_ptr, info_ptr, &png_prop->width, &png_prop->height, &png_prop->bit_depth, &png_prop->color_type, &png_prop->interlace_type, &png_prop->compression_type, &png_prop->filter_type); /* Get bits per channel */ - png_data->bit_depth = png_get_bit_depth(png_ptr, info); + png_prop->bit_depth = png_get_bit_depth(png_ptr, info_ptr); /* Get Color type */ - png_data->color_type = png_get_color_type(png_ptr, info); + png_prop->color_type = png_get_color_type(png_ptr, info_ptr); /* Gray scale converted to upscaled to 8 bits */ - if ((png_data->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (png_data->color_type == PNG_COLOR_TYPE_GRAY)) { + if ((png_prop->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (png_prop->color_type == PNG_COLOR_TYPE_GRAY)) { /* Gray scale with alpha channel converted to RGB */ - if (png_data->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + if (png_prop->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); - if (png_data->bit_depth < MM_UTIL_BIT_DEPTH_8)/* Convert to 8 bits */ + if (png_prop->bit_depth < MM_UTIL_BIT_DEPTH_8)/* Convert to 8 bits */ png_set_expand_gray_1_2_4_to_8(png_ptr); } /* Palette converted to RGB */ - else if (png_data->color_type == PNG_COLOR_TYPE_PALETTE) + else if (png_prop->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); /* Add alpha channel, but not for GRAY images */ - if ((png_data->bit_depth >= MM_UTIL_BIT_DEPTH_8) - && (png_data->color_type != PNG_COLOR_TYPE_GRAY)) { + if ((png_prop->bit_depth >= MM_UTIL_BIT_DEPTH_8) + && (png_prop->color_type != PNG_COLOR_TYPE_GRAY)) { png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER); } - if (png_get_valid(png_ptr, info, PNG_INFO_tRNS) != 0) + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) png_set_tRNS_to_alpha(png_ptr); - if (png_get_bKGD(png_ptr, info, &image_background) != 0) + if (png_get_bKGD(png_ptr, info_ptr, &image_background) != 0) png_set_background(png_ptr, image_background, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); png_set_interlace_handling(png_ptr); /* Update the info structure */ - png_read_update_info(png_ptr, info); + png_read_update_info(png_ptr, info_ptr); - png_data->rowbytes = png_get_rowbytes(png_ptr, info); - png_data->size = ((size_t)(png_data->height) * png_data->rowbytes); -} + mm_util_fleave(); -static void __read_function(png_structp png_ptr, png_bytep data, png_size_t size) -{ - png_mem_s *png_mem_ptr = (png_mem_s *) png_get_io_ptr(png_ptr); - - if (png_mem_ptr->mem && size > 0) { - memcpy(data, png_mem_ptr->mem + png_mem_ptr->size, size); - png_mem_ptr->size += size; - } } -static int __read_png(mm_util_png_data *decoded, FILE * fp, void *memory) +static int _read_png(FILE *fp, void *memory, mm_util_png_data *decoded) { png_structp png_ptr; png_infop info_ptr; guint row_index; - png_mem_s png_mem_ptr; - png_data_s png_data; + png_mem_s png_mem_ptr = {memory, 0}; + png_property_s png_prop; - mm_util_debug("__read_png"); + mm_util_retvm_if(((fp == NULL) && (memory == NULL)), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid png image"); + mm_util_retvm_if((decoded == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid color image"); + /* create libpng structures to read png */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, __user_error_fn, __user_warning_fn); if (png_ptr == NULL) { mm_util_error("could not create read struct"); - mm_util_safe_fclose(fp); return MM_UTIL_ERROR_INVALID_OPERATION; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { mm_util_error("could not create info struct"); - mm_util_safe_fclose(fp); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); return MM_UTIL_ERROR_INVALID_OPERATION; } @@ -153,130 +169,83 @@ static int __read_png(mm_util_png_data *decoded, FILE * fp, void *memory) if (setjmp(png_jmpbuf(png_ptr))) { mm_util_error("setjmp called due to internal libpng error"); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - mm_util_safe_fclose(fp); return MM_UTIL_ERROR_INVALID_OPERATION; } + /* set file i/o or data function to read png */ if (fp) png_init_io(png_ptr, fp); - else if (memory) { - png_mem_ptr.mem = memory; - png_mem_ptr.size = 0; - png_set_read_fn(png_ptr, &png_mem_ptr, __read_function); - } else { - png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - return MM_UTIL_ERROR_INVALID_OPERATION; - } + else + png_set_read_fn(png_ptr, &png_mem_ptr, __read_data_fn); + + /* get properties(header) to png_prop */ + __get_property(&png_prop, png_ptr, info_ptr); - __dec_set_prop(&png_data, png_ptr, info_ptr); - if (png_data.size == 0) { + png_bytep row_pointers[png_prop.height]; + png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr); + size_t data_size = ((size_t)(png_prop.height) * rowbytes); + if (data_size == 0) { + mm_util_error("wrong data size"); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); return MM_UTIL_ERROR_INVALID_OPERATION; } - png_bytep row_pointers[png_data.height]; - - for (row_index = 0; row_index < png_data.height; row_index++) - row_pointers[row_index] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + for (row_index = 0; row_index < png_prop.height; row_index++) + row_pointers[row_index] = png_malloc(png_ptr, rowbytes); png_read_image(png_ptr, row_pointers); - decoded->data = (void *)png_malloc(png_ptr, sizeof(png_bytep) * png_data.size); + decoded->data = (void *)png_malloc(png_ptr, sizeof(png_bytep) * data_size); + if (decoded->data == NULL) { + mm_util_error("out of memory"); + png_read_end(png_ptr, info_ptr); + png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); + return MM_UTIL_ERROR_OUT_OF_MEMORY; + } - for (row_index = 0; row_index < png_data.height; row_index++) { - memcpy(decoded->data + (row_index * png_data.rowbytes), row_pointers[row_index], png_data.rowbytes); + /* read png data */ + for (row_index = 0; row_index < png_prop.height; row_index++) { + memcpy(decoded->data + (row_index * rowbytes), row_pointers[row_index], rowbytes); png_free(png_ptr, row_pointers[row_index]); } png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); - mm_util_safe_fclose(fp); - if (decoded->data) { - decoded->width = (unsigned long)png_data.width; - decoded->height = (unsigned long)png_data.height; - decoded->size = png_data.size; - } + /* set result */ + decoded->width = (unsigned long)png_prop.width; + decoded->height = (unsigned long)png_prop.height; + decoded->size = data_size; return MM_UTIL_ERROR_NONE; } -int mm_util_decode_from_png_file(const char *fpath, mm_util_png_data *decoded) -{ - int ret = MM_UTIL_ERROR_NONE; - FILE *fp; - - ret = mm_util_safe_fopen(fpath, "r", &fp); - if (ret != MM_UTIL_ERROR_NONE) { - mm_util_error("mm_util_safe_fopen failed (%d)", ret); - return ret; - } - - if (fp) - ret = __read_png(decoded, fp, NULL); - - return ret; -} - -int mm_util_decode_from_png_memory(void *memory, const size_t src_size, mm_util_png_data *decoded) -{ - int ret = MM_UTIL_ERROR_NONE; - - mm_util_debug("mm_util_decode_from_memory"); - - ret = __read_png(decoded, NULL, memory); - - return ret; -} - -static void __flush_data_fn(png_structp png_ptr G_GNUC_UNUSED) -{ - /* do nothing */ -} - -static void __write_function(png_structp png_ptr, png_bytep data, png_uint_32 length) -{ - png_mem_s *png_mem_ptr = (png_mem_s *) png_get_io_ptr(png_ptr); - - if (data) { - png_mem_ptr->mem = (void *)realloc(png_mem_ptr->mem, sizeof(png_bytep) * (png_mem_ptr->size + length)); - - memcpy(png_mem_ptr->mem + png_mem_ptr->size, data, length); - png_mem_ptr->size += length; - } -} - -void __init_encode_png(png_data_s *png_data) -{ - png_data->compression_level = MM_UTIL_COMPRESSION_6; - png_data->filter = PNG_FILTER_NONE; - png_data->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - png_data->filter_type = PNG_FILTER_TYPE_BASE; - png_data->interlace_type = PNG_INTERLACE_NONE; - png_data->bit_depth = MM_UTIL_BIT_DEPTH_8; -} - -int write_png(mm_util_png_data *decoded, mm_util_png_compression compression_level, FILE *fp, void **buffer, size_t *size) +int _write_png(mm_util_png_data *decoded, mm_util_png_compression compression_level, FILE *fp, void **buffer, size_t *size) { png_structp png_ptr; png_infop info_ptr; guint row_index; static png_bytepp row_pointers = NULL; - png_mem_s png_mem_ptr; - png_data_s png_data; - - mm_util_debug("write_png"); - png_mem_ptr.mem = NULL; - png_mem_ptr.size = 0; - - __init_encode_png(&png_data); - png_data.compression_level = compression_level; - + png_size_t rowbytes = 0; + png_mem_s png_mem_ptr = {NULL, 0}; + png_property_s png_prop; + + mm_util_retvm_if((decoded == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid color image"); + mm_util_retvm_if(((fp == NULL) && (buffer == NULL || size == NULL)), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid png image"); + + /* initialize png_prop */ + png_prop.filter = PNG_FILTER_NONE; + png_prop.color_type = PNG_COLOR_TYPE_RGB_ALPHA; + png_prop.compression_type = PNG_COMPRESSION_TYPE_BASE; + png_prop.filter_type = PNG_FILTER_TYPE_BASE; + png_prop.interlace_type = PNG_INTERLACE_NONE; + png_prop.bit_depth = MM_UTIL_BIT_DEPTH_8; + + /* create libpng structures to write png */ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, __user_error_fn, __user_warning_fn); if (png_ptr == NULL) { - mm_util_error("could not create write struct"); - mm_util_safe_fclose(fp); + mm_util_error("could not create read struct"); return MM_UTIL_ERROR_INVALID_OPERATION; } @@ -284,33 +253,38 @@ int write_png(mm_util_png_data *decoded, mm_util_png_compression compression_lev if (info_ptr == NULL) { mm_util_error("could not create info struct"); png_destroy_write_struct(&png_ptr, png_infopp_NULL); - mm_util_safe_fclose(fp); return MM_UTIL_ERROR_INVALID_OPERATION; } if (setjmp(png_jmpbuf(png_ptr))) { mm_util_error("setjmp called due to internal libpng error"); png_destroy_write_struct(&png_ptr, &info_ptr); - mm_util_safe_fclose(fp); return MM_UTIL_ERROR_INVALID_OPERATION; } - png_set_filter(png_ptr, 0, png_data.filter); - png_set_compression_level(png_ptr, png_data.compression_level); - - png_set_IHDR(png_ptr, info_ptr, decoded->width, decoded->height, png_data.bit_depth, png_data.color_type, png_data.interlace_type, PNG_COMPRESSION_TYPE_BASE, png_data.filter_type); - + /* set file i/o or data function to write png */ if (fp) png_init_io(png_ptr, fp); else - png_set_write_fn(png_ptr, &png_mem_ptr, (png_rw_ptr) __write_function, __flush_data_fn); + png_set_write_fn(png_ptr, &png_mem_ptr, (png_rw_ptr) __write_data_fn, __flush_data_fn); - png_data.rowbytes = (size_t)png_get_rowbytes(png_ptr, info_ptr); + /* set properties(header) from png_prop */ + png_set_filter(png_ptr, 0, png_prop.filter); + png_set_compression_level(png_ptr, compression_level); + png_set_IHDR(png_ptr, info_ptr, decoded->width, decoded->height, png_prop.bit_depth, png_prop.color_type, png_prop.interlace_type, png_prop.compression_type, png_prop.filter_type); + + rowbytes = (size_t)png_get_rowbytes(png_ptr, info_ptr); row_pointers = png_malloc(png_ptr, sizeof(png_bytep) * decoded->height); + if (row_pointers == NULL) { + mm_util_error("out of memory"); + png_destroy_write_struct(&png_ptr, &info_ptr); + return MM_UTIL_ERROR_OUT_OF_MEMORY; + } + /* write png data */ for (row_index = 0; row_index < decoded->height; row_index++) - row_pointers[row_index] = decoded->data + (row_index * png_data.rowbytes); + row_pointers[row_index] = decoded->data + (row_index * rowbytes); png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, row_pointers); @@ -318,9 +292,9 @@ int write_png(mm_util_png_data *decoded, mm_util_png_compression compression_lev png_free(png_ptr, row_pointers); png_destroy_write_struct(&png_ptr, &info_ptr); - mm_util_safe_fclose(fp); - if (png_mem_ptr.mem) { + /* set result */ + if (!fp && png_mem_ptr.mem) { *buffer = (void *)png_mem_ptr.mem; *size = png_mem_ptr.size; } @@ -328,33 +302,96 @@ int write_png(mm_util_png_data *decoded, mm_util_png_compression compression_lev return MM_UTIL_ERROR_NONE; } +int mm_util_decode_from_png_file(const char *fpath, mm_util_png_data *decoded) +{ + int ret = MM_UTIL_ERROR_NONE; + FILE *fp = NULL; + + mm_util_retvm_if((decoded == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid color image"); + mm_util_retvm_if(!MMUTIL_STRING_VALID(fpath), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path"); + + mm_util_fenter(); + + ret = mm_util_safe_fopen(fpath, "r", &fp); + if (ret != MM_UTIL_ERROR_NONE) { + mm_util_error("mm_util_safe_fopen failed (%d)", ret); + mm_util_safe_fclose(fp); + mm_util_fleave(); + return ret; + } + + ret = _read_png(fp, NULL, decoded); + if (ret != MM_UTIL_ERROR_NONE) + mm_util_error("_write_png failed (%d)", ret); + + mm_util_safe_fclose(fp); + + mm_util_fleave(); + + return ret; +} + +int mm_util_decode_from_png_memory(void *memory, const size_t src_size, mm_util_png_data *decoded) +{ + int ret = MM_UTIL_ERROR_NONE; + + mm_util_retvm_if((memory == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid png image"); + mm_util_retvm_if((decoded == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid color image"); + + mm_util_fenter(); + + ret = _read_png(NULL, memory, decoded); + if (ret != MM_UTIL_ERROR_NONE) + mm_util_error("_write_png failed (%d)", ret); + + mm_util_fleave(); + + return ret; +} + int mm_util_encode_to_png_file(mm_util_png_data *decoded, mm_util_png_compression compression_level, const char *fpath) { int ret = MM_UTIL_ERROR_NONE; - FILE *fp; + FILE *fp = NULL; - mm_util_debug("mm_util_encode_to_png"); + mm_util_retvm_if((decoded == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid color image"); + mm_util_retvm_if(!MMUTIL_STRING_VALID(fpath), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid path"); - mm_util_retvm_if(!MMUTIL_STRING_VALID(fpath), MM_UTIL_ERROR_NO_SUCH_FILE, "invalid path"); + mm_util_fenter(); ret = mm_util_safe_fopen(fpath, "w", &fp); if (ret != MM_UTIL_ERROR_NONE) { mm_util_error("mm_util_safe_fopen failed (%d)", ret); + mm_util_safe_fclose(fp); + mm_util_fleave(); return ret; } - ret = write_png(decoded, compression_level, fp, NULL, NULL); + ret = _write_png(decoded, compression_level, fp, NULL, NULL); + if (ret != MM_UTIL_ERROR_NONE) + mm_util_error("_write_png failed (%d)", ret); + + mm_util_safe_fclose(fp); + + mm_util_fleave(); return ret; } int mm_util_encode_to_png_memory(mm_util_png_data *decoded, mm_util_png_compression compression_level, void **data, size_t *size) { - int ret; + int ret = MM_UTIL_ERROR_NONE; + + mm_util_retvm_if((decoded == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid color image"); + mm_util_retvm_if((data == NULL || size == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid png image"); + + mm_util_fenter(); - mm_util_debug("mm_util_encode_to_memory"); + ret = _write_png(decoded, compression_level, NULL, data, size); + if (ret != MM_UTIL_ERROR_NONE) + mm_util_error("_write_png failed (%d)", ret); - ret = write_png(decoded, compression_level, NULL, data, size); + mm_util_fleave(); return ret; } diff --git a/png/test/mm_util_png_testsuite.c b/png/test/mm_util_png_testsuite.c index 6b8a156..ecdf2bd 100755 --- a/png/test/mm_util_png_testsuite.c +++ b/png/test/mm_util_png_testsuite.c @@ -33,8 +33,8 @@ #define DECODE_FILE_PATH tzplatform_mkpath(TZ_USER_CONTENT, "png_test_dec_file.raw") #define DECODE_MEM_PATH tzplatform_mkpath(TZ_USER_CONTENT, "png_test_dec_mem.raw") -#define ENCODE_FILE_PATH tzplatform_mkpath(TZ_USER_CONTENT, "png_test_enc_file.jpg") -#define ENCODE_MEM_PATH tzplatform_mkpath(TZ_USER_CONTENT, "png_test_enc_mem.jpg") +#define ENCODE_FILE_PATH tzplatform_mkpath(TZ_USER_CONTENT, "png_test_enc_file.png") +#define ENCODE_MEM_PATH tzplatform_mkpath(TZ_USER_CONTENT, "png_test_enc_mem.png") typedef enum { TEST_AUTO,