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 {
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;
}
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;
}
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);
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;
}
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;
}