forked from enlightenment/efl
evas: Implement GRY8/AGRY88 save support for PNG
This enables the PNG saver to save images with gray and alpha + gray colorspaces. GRY8 is usually used for alpha only. Note: This commit also introduces whitespace changes. Sorry about the mess, but at least now we have spaces only. Read the commit with show -w :) @feature
This commit is contained in:
parent
5eef9da416
commit
3425ad2abd
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue