diff --git a/src/modules/evas/image_savers/png/evas_image_save_png.c b/src/modules/evas/image_savers/png/evas_image_save_png.c index e7149be1e7..6eef2fe221 100644 --- a/src/modules/evas/image_savers/png/evas_image_save_png.c +++ b/src/modules/evas/image_savers/png/evas_image_save_png.c @@ -26,16 +26,23 @@ save_image_png(RGBA_Image *im, const char *file, int do_compress, int interlace) FILE *f; png_structp png_ptr; png_infop info_ptr; - DATA32 *ptr, *data = NULL; + uint8_t *ptr, *data = NULL; unsigned int x, y, j; png_bytep row_ptr; volatile png_bytep png_data = NULL; - png_color_8 sig_bit; + png_color_8 sig_bit = {}; int num_passes = 1, pass; + Eina_Bool gry8 = EINA_FALSE, agry88 = EINA_FALSE, free_data = EINA_FALSE; + int pixel_size = 4; if (!im || !im->image.data || !file) return 0; + if ((im->cache_entry.space != EFL_GFX_COLORSPACE_ARGB8888) && + (im->cache_entry.space != EFL_GFX_COLORSPACE_AGRY88) && + (im->cache_entry.space != EFL_GFX_COLORSPACE_GRY8)) + return 0; + f = fopen(file, "wb"); if (!f) return 0; @@ -46,61 +53,83 @@ save_image_png(RGBA_Image *im, const char *file, int do_compress, int interlace) info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { - png_destroy_write_struct(&png_ptr, NULL); - goto close_file; + png_destroy_write_struct(&png_ptr, NULL); + goto close_file; } if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); - png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); - goto close_file; + png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); + png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); + goto close_file; } if (interlace) { #ifdef PNG_WRITE_INTERLACING_SUPPORTED - interlace = PNG_INTERLACE_ADAM7; + interlace = PNG_INTERLACE_ADAM7; #else - interlace = PNG_INTERLACE_NONE; + interlace = PNG_INTERLACE_NONE; #endif } else interlace = PNG_INTERLACE_NONE; - if (im->cache_entry.flags.alpha) + if (im->cache_entry.space == EFL_GFX_COLORSPACE_GRY8) { - data = malloc(im->cache_entry.w * im->cache_entry.h * sizeof(DATA32)); - if (!data) - { - png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); - png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); - goto close_file; - } - memcpy(data, im->image.data, im->cache_entry.w * im->cache_entry.h * sizeof(DATA32)); - evas_common_convert_argb_unpremul(data, im->cache_entry.w * im->cache_entry.h); - png_init_io(png_ptr, f); + gry8 = EINA_TRUE; + pixel_size = 1; + data = im->image.data8; + png_init_io(png_ptr, f); png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, - PNG_COLOR_TYPE_RGB_ALPHA, interlace, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + PNG_COLOR_TYPE_GRAY, interlace, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + } + else if (im->cache_entry.space == EFL_GFX_COLORSPACE_AGRY88) + { + agry88 = EINA_TRUE; + pixel_size = 2; + data = im->image.data8; + png_init_io(png_ptr, f); + png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, + PNG_COLOR_TYPE_GRAY_ALPHA, interlace, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + } + else if (im->cache_entry.flags.alpha) + { + data = malloc(im->cache_entry.w * im->cache_entry.h * sizeof(DATA32)); + if (!data) + { + png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); + png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); + goto close_file; + } + free_data = EINA_TRUE; + memcpy(data, im->image.data, im->cache_entry.w * im->cache_entry.h * sizeof(DATA32)); + evas_common_convert_argb_unpremul((DATA32 *) data, im->cache_entry.w * im->cache_entry.h); + png_init_io(png_ptr, f); + png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, + PNG_COLOR_TYPE_RGB_ALPHA, interlace, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); #ifdef WORDS_BIGENDIAN - png_set_swap_alpha(png_ptr); + png_set_swap_alpha(png_ptr); #else - png_set_bgr(png_ptr); + png_set_bgr(png_ptr); #endif } else { - data = im->image.data; - png_init_io(png_ptr, f); - png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, - PNG_COLOR_TYPE_RGB, interlace, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - png_data = alloca(im->cache_entry.w * 3 * sizeof(char)); + data = im->image.data8; + png_init_io(png_ptr, f); + png_set_IHDR(png_ptr, info_ptr, im->cache_entry.w, im->cache_entry.h, 8, + PNG_COLOR_TYPE_RGB, interlace, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_data = alloca(im->cache_entry.w * 3 * sizeof(char)); } sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; sig_bit.alpha = 8; + sig_bit.gray = 8; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_set_compression_level(png_ptr, do_compress); @@ -114,32 +143,32 @@ save_image_png(RGBA_Image *im, const char *file, int do_compress, int interlace) for (pass = 0; pass < num_passes; pass++) { - ptr = data; + ptr = data; - for (y = 0; y < im->cache_entry.h; y++) - { - if (im->cache_entry.flags.alpha) - row_ptr = (png_bytep) ptr; - else - { - for (j = 0, x = 0; x < im->cache_entry.w; x++) - { - png_data[j++] = (ptr[x] >> 16) & 0xff; - png_data[j++] = (ptr[x] >> 8) & 0xff; - png_data[j++] = (ptr[x]) & 0xff; - } - row_ptr = (png_bytep) png_data; - } - png_write_rows(png_ptr, &row_ptr, 1); - ptr += im->cache_entry.w; - } + for (y = 0; y < im->cache_entry.h; y++) + { + if (gry8 || agry88 || im->cache_entry.flags.alpha) + row_ptr = (png_bytep) ptr; + else + { + DATA32 *ptr32 = (DATA32 *) ptr; + for (j = 0, x = 0; x < im->cache_entry.w; x++) + { + png_data[j++] = (ptr32[x] >> 16) & 0xff; + png_data[j++] = (ptr32[x] >> 8) & 0xff; + png_data[j++] = (ptr32[x]) & 0xff; + } + row_ptr = (png_bytep) png_data; + } + png_write_rows(png_ptr, &row_ptr, 1); + ptr += im->cache_entry.w * pixel_size; + } } png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr); png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr); - if (im->cache_entry.flags.alpha) - free(data); + if (free_data) free(data); fclose(f); return 1;