#define png_infopp_NULL (png_infopp)NULL
typedef struct {
+ uint32_t width;
+ uint32_t height;
+ int bit_depth; /**< Bit depth*/
+ int color_type; /**< Color type*/
+ int interlace_type; /**< Interlace 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;
+
+
+typedef struct {
void *mem;
png_size_t size;
-} read_data;
+} png_mem_s;
static void __user_error_fn(png_structp png_ptr, png_const_charp error_msg)
{
mm_util_error("%s", warning_msg);
}
-static void __dec_set_prop(mm_util_png_data *decoded, png_structp png_ptr, png_infop info)
+static void __dec_set_prop(png_data_s *png_data, png_structp png_ptr, png_infop info)
{
png_color_16 *image_background = NULL;
- png_uint_32 _width = 0;
- png_uint_32 _height = 0;
mm_util_debug("__dec_set_prop");
png_read_info(png_ptr, info);
- png_get_IHDR(png_ptr, info, &_width, &_height, &decoded->png.bit_depth, &decoded->png.color_type, &decoded->png.interlace_type, NULL, &decoded->png.filter_type);
+ 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);
/* Get bits per channel */
- decoded->png.bit_depth = png_get_bit_depth(png_ptr, info);
+ png_data->bit_depth = png_get_bit_depth(png_ptr, info);
/* Get Color type */
- decoded->png.color_type = png_get_color_type(png_ptr, info);
+ png_data->color_type = png_get_color_type(png_ptr, info);
/* Gray scale converted to upscaled to 8 bits */
- if ((decoded->png.color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (decoded->png.color_type == PNG_COLOR_TYPE_GRAY)) {
+ if ((png_data->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || (png_data->color_type == PNG_COLOR_TYPE_GRAY)) {
/* Gray scale with alpha channel converted to RGB */
- if (decoded->png.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ if (png_data->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
- if (decoded->png.bit_depth < MM_UTIL_BIT_DEPTH_8)/* Convert to 8 bits */
+ if (png_data->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 (decoded->png.color_type == PNG_COLOR_TYPE_PALETTE)
+ else if (png_data->color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
/* Add alpha channel, but not for GRAY images */
- if ((decoded->png.bit_depth >= MM_UTIL_BIT_DEPTH_8)
- && (decoded->png.color_type != PNG_COLOR_TYPE_GRAY)) {
+ if ((png_data->bit_depth >= MM_UTIL_BIT_DEPTH_8)
+ && (png_data->color_type != PNG_COLOR_TYPE_GRAY)) {
png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
}
/* Update the info structure */
png_read_update_info(png_ptr, info);
- decoded->width = (uint32_t)_width;
- decoded->height = (uint32_t)_height;
- decoded->png.rowbytes = (size_t)png_get_rowbytes(png_ptr, info);
- decoded->size = (size_t)((size_t)(decoded->height) * decoded->png.rowbytes);
+ png_data->rowbytes = png_get_rowbytes(png_ptr, info);
+ png_data->size = ((size_t)(png_data->height) * png_data->rowbytes);
}
static void __read_function(png_structp png_ptr, png_bytep data, png_size_t size)
{
- read_data *read_data_ptr = (read_data *) png_get_io_ptr(png_ptr);
+ png_mem_s *png_mem_ptr = (png_mem_s *) png_get_io_ptr(png_ptr);
- if (read_data_ptr->mem && size > 0) {
- memcpy(data, read_data_ptr->mem + read_data_ptr->size, size);
- read_data_ptr->size += size;
+ if (png_mem_ptr->mem && size > 0) {
+ memcpy(data, png_mem_ptr->mem + png_mem_ptr->size, size);
+ png_mem_ptr->size += size;
}
}
-void __init_decode_png(mm_util_png *png)
-{
- mm_util_debug("mm_util_init_decode_png");
- png->transform = PNG_TRANSFORM_IDENTITY;
-}
-
static int __read_png(mm_util_png_data *decoded, FILE * fp, void *memory)
{
png_structp png_ptr;
png_infop info_ptr;
guint row_index;
- read_data read_data_ptr;
+ png_mem_s png_mem_ptr;
+ png_data_s png_data;
mm_util_debug("__read_png");
- decoded->data = NULL;
- __init_decode_png(&decoded->png);
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, __user_error_fn, __user_warning_fn);
if (setjmp(png_jmpbuf(png_ptr))) {
mm_util_error("setjmp called due to internal libpng error");
- if (decoded->data) {
- png_free(png_ptr, decoded->data);
- decoded->data = NULL;
- mm_util_debug("free data");
- }
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
mm_util_safe_fclose(fp);
return MM_UTIL_ERROR_INVALID_OPERATION;
if (fp)
png_init_io(png_ptr, fp);
else if (memory) {
- read_data_ptr.mem = memory;
- read_data_ptr.size = 0;
- png_set_read_fn(png_ptr, &read_data_ptr, __read_function);
+ 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;
}
- __dec_set_prop(decoded, png_ptr, info_ptr);
+ __dec_set_prop(&png_data, png_ptr, info_ptr);
+ if (png_data.size == 0) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
+ return MM_UTIL_ERROR_INVALID_OPERATION;
+ }
- {
- png_bytep row_pointers[decoded->height];
+ png_bytep row_pointers[png_data.height];
- for (row_index = 0; row_index < decoded->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_data.height; row_index++)
+ row_pointers[row_index] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
- png_read_image(png_ptr, row_pointers);
+ png_read_image(png_ptr, row_pointers);
- decoded->data = (void *)png_malloc(png_ptr, sizeof(png_bytep) * decoded->size);
+ decoded->data = (void *)png_malloc(png_ptr, sizeof(png_bytep) * png_data.size);
- for (row_index = 0; row_index < decoded->height; row_index++) {
- memcpy(decoded->data + (row_index * decoded->png.rowbytes), row_pointers[row_index], decoded->png.rowbytes);
- png_free(png_ptr, row_pointers[row_index]);
- }
+ 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);
+ 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;
+ }
+
return MM_UTIL_ERROR_NONE;
}
return ret;
}
-static void user_flush_data(png_structp png_ptr G_GNUC_UNUSED)
+static void __flush_data_fn(png_structp png_ptr G_GNUC_UNUSED)
{
/* do nothing */
}
-static void user_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
+static void __write_function(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
- mm_util_png_data *encoded = (mm_util_png_data *) png_get_io_ptr(png_ptr);
+ png_mem_s *png_mem_ptr = (png_mem_s *) png_get_io_ptr(png_ptr);
if (data) {
- encoded->data = (void *)realloc(encoded->data, sizeof(png_bytep) * (encoded->size + length));
+ png_mem_ptr->mem = (void *)realloc(png_mem_ptr->mem, sizeof(png_bytep) * (png_mem_ptr->size + length));
- memcpy(encoded->data + encoded->size, data, length);
- encoded->size += length;
+ memcpy(png_mem_ptr->mem + png_mem_ptr->size, data, length);
+ png_mem_ptr->size += length;
}
}
-void __init_encode_png(mm_util_png *png)
+void __init_encode_png(png_data_s *png_data)
{
- mm_util_debug("mm_util_init_encode_png");
- png->compression_level = MM_UTIL_COMPRESSION_6;
- png->filter = PNG_FILTER_NONE;
- png->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
- png->filter_type = PNG_FILTER_TYPE_BASE;
- png->interlace_type = PNG_INTERLACE_NONE;
- png->bit_depth = MM_UTIL_BIT_DEPTH_8;
+ 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(void **data, mm_util_png_data *encoded, FILE *fp, mm_util_png_compression compression_level)
+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");
- encoded->data = NULL;
- encoded->size = 0;
+ png_mem_ptr.mem = NULL;
+ png_mem_ptr.size = 0;
- __init_encode_png(&encoded->png);
- encoded->png.compression_level = compression_level;
+ __init_encode_png(&png_data);
+ png_data.compression_level = compression_level;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, __user_error_fn, __user_warning_fn);
if (setjmp(png_jmpbuf(png_ptr))) {
mm_util_error("setjmp called due to internal libpng error");
- if (encoded->data) {
- png_free(png_ptr, encoded->data);
- encoded->data = NULL;
- mm_util_debug("free data");
- }
- if (row_pointers)
- png_free(png_ptr, row_pointers);
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, encoded->png.filter);
- png_set_compression_level(png_ptr, encoded->png.compression_level);
-
- /* convert color type */
- if (encoded->png.color_type == MM_UTIL_COLOR_RGBA)
- encoded->png.color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ 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, encoded->width, encoded->height, encoded->png.bit_depth, encoded->png.color_type, encoded->png.interlace_type, PNG_COMPRESSION_TYPE_BASE, encoded->png.filter_type);
+ 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);
if (fp)
png_init_io(png_ptr, fp);
else
- png_set_write_fn(png_ptr, encoded, (png_rw_ptr) user_write_data, user_flush_data);
+ png_set_write_fn(png_ptr, &png_mem_ptr, (png_rw_ptr) __write_function, __flush_data_fn);
- encoded->png.rowbytes = (size_t)png_get_rowbytes(png_ptr, info_ptr);
+ png_data.rowbytes = (size_t)png_get_rowbytes(png_ptr, info_ptr);
- row_pointers = png_malloc(png_ptr, sizeof(png_bytep) * encoded->height);
+ row_pointers = png_malloc(png_ptr, sizeof(png_bytep) * decoded->height);
- for (row_index = 0; row_index < encoded->height; row_index++)
- row_pointers[row_index] = (*data) + (row_index * encoded->png.rowbytes);
+ for (row_index = 0; row_index < decoded->height; row_index++)
+ row_pointers[row_index] = decoded->data + (row_index * png_data.rowbytes);
png_write_info(png_ptr, info_ptr);
png_write_image(png_ptr, row_pointers);
png_destroy_write_struct(&png_ptr, &info_ptr);
mm_util_safe_fclose(fp);
+ if (png_mem_ptr.mem) {
+ *buffer = (void *)png_mem_ptr.mem;
+ *size = png_mem_ptr.size;
+ }
+
return MM_UTIL_ERROR_NONE;
}
-int mm_util_encode_to_png_file(void **data, mm_util_png_data *encoded, const char *fpath, mm_util_png_compression compression_level)
+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;
return ret;
}
- ret = write_png(data, encoded, fp, compression_level);
+ ret = write_png(decoded, compression_level, fp, NULL, NULL);
return ret;
}
-int mm_util_encode_to_png_memory(void **data, mm_util_png_data *encoded, mm_util_png_compression compression_level)
+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;
mm_util_debug("mm_util_encode_to_memory");
- ret = write_png(data, encoded, NULL, compression_level);
+ ret = write_png(decoded, compression_level, NULL, data, size);
return ret;
}