aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-06-13 15:35:48 -0700
committerCedric BAIL <cedric.bail@free.fr>2019-06-13 15:37:31 -0700
commit21fd869cad2d60c88c972c40a0d0526465e432c8 (patch)
treeb1134310c3192c1c64ae6d2407822b3768c9c32e
parentevas: add infrastructure to feed 9 patch information from file loader to imag... (diff)
downloadefl-devs/cedric/9patch.tar.gz
evas: add support for .9.png file to PNG loader.devs/cedric/9patch
This support Android 9 patch file format. Only black is a recognized color for both the stretch area and the content area. All other color are associated with being "white".
-rw-r--r--src/modules/evas/image_loaders/png/evas_image_load_png.c621
1 files changed, 457 insertions, 164 deletions
diff --git a/src/modules/evas/image_loaders/png/evas_image_load_png.c b/src/modules/evas/image_loaders/png/evas_image_load_png.c
index 1460cc783d..503f89aa61 100644
--- a/src/modules/evas/image_loaders/png/evas_image_load_png.c
+++ b/src/modules/evas/image_loaders/png/evas_image_load_png.c
@@ -10,6 +10,8 @@
#include "evas_private.h"
#define PNG_BYTES_TO_CHECK 4
+#define WHITE 0xFFFFFFFF
+#define BLACK 0xFF000000
typedef struct _Evas_PNG_Info Evas_PNG_Info;
struct _Evas_PNG_Info
@@ -17,6 +19,13 @@ struct _Evas_PNG_Info
unsigned char *map;
size_t length;
size_t position;
+
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_uint_32 w32, h32;
+ int bit_depth, color_type, interlace_type;
+
+ volatile Eina_Bool hasa;
};
typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
@@ -37,6 +46,34 @@ static const Evas_Colorspace cspace_grey_alpha[2] = {
};
static void
+_evas_image_png_update_x_content(Eina_Rectangle *r, int index)
+{
+ if (r->x == 0)
+ {
+ r->x = index;
+ r->w = 1;
+ }
+ else
+ {
+ r->w = index - r->x;
+ }
+}
+
+static void
+_evas_image_png_update_y_content(Eina_Rectangle *r, int index)
+{
+ if (r->y == 0)
+ {
+ r->y = index;
+ r->h = 1;
+ }
+ else
+ {
+ r->h = index - r->y;
+ }
+}
+
+static void
_evas_image_png_read(png_structp png_ptr, png_bytep out, png_size_t count)
{
Evas_PNG_Info *epi = png_get_io_ptr(png_ptr);
@@ -76,77 +113,65 @@ evas_image_load_file_close_png(void *loader_data)
}
static Eina_Bool
-evas_image_load_file_head_png(void *loader_data,
- Emile_Image_Property *prop,
- int *error)
+_evas_image_load_file_internal_head_png(Evas_Loader_Internal *loader,
+ Evas_Image_Property *prop,
+ Evas_PNG_Info *epi,
+ int *error, Eina_Bool close_file)
{
- Evas_Loader_Internal *loader = loader_data;
- Evas_Image_Load_Opts *opts;
- Eina_File *f;
-
- Evas_PNG_Info epi;
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL;
- png_uint_32 w32, h32;
- int bit_depth, color_type, interlace_type;
- volatile char hasa;
+ Evas_Image_Load_Opts *opts = loader->opts;
+ Eina_File *f = loader->f;
volatile Eina_Bool r = EINA_FALSE;
- opts = loader->opts;
- f = loader->f;
+ *error = EVAS_LOAD_ERROR_NONE;
- hasa = 0;
- epi.map = eina_file_map_all(f, EINA_FILE_RANDOM);
- if (!epi.map)
+ epi->hasa = 0;
+ epi->map = eina_file_map_all(f, EINA_FILE_RANDOM);
+ if (!epi->map)
{
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
goto close_file;
}
- epi.length = eina_file_size_get(f);
- epi.position = 0;
+ epi->length = eina_file_size_get(f);
+ epi->position = 0;
- if (epi.length < PNG_BYTES_TO_CHECK)
+ if (epi->length < PNG_BYTES_TO_CHECK)
{
- *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+ goto close_file;
}
-
- if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK))
+ if (png_sig_cmp(epi->map, 0, PNG_BYTES_TO_CHECK))
{
- *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+ goto close_file;
}
-
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_ptr)
+ epi->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!epi->png_ptr)
{
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+ goto close_file;
}
-
- info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr)
+ epi->info_ptr = png_create_info_struct(epi->png_ptr);
+ if (!epi->info_ptr)
{
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+ goto close_file;
}
-
- png_set_read_fn(png_ptr, &epi, _evas_image_png_read);
-
- if (setjmp(png_jmpbuf(png_ptr)))
+ png_set_read_fn(epi->png_ptr, epi, _evas_image_png_read);
+ if (setjmp(png_jmpbuf(epi->png_ptr)))
{
- *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+ goto close_file;
}
- png_read_info(png_ptr, info_ptr);
- png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
- (png_uint_32 *) (&h32), &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
- if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) ||
- IMG_TOO_BIG(w32, h32))
+ png_read_info(epi->png_ptr, epi->info_ptr);
+ png_get_IHDR(epi->png_ptr, epi->info_ptr, (png_uint_32 *) (&epi->w32),
+ (png_uint_32 *) (&epi->h32), &epi->bit_depth, &epi->color_type,
+ &epi->interlace_type, NULL, NULL);
+ if ((epi->w32 < 1) || (epi->h32 < 1) ||
+ (epi->w32 > IMG_MAX_SIZE) || (epi->h32 > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(epi->w32, epi->h32))
{
- if (IMG_TOO_BIG(w32, h32))
+ if (IMG_TOO_BIG(epi->w32, epi->h32))
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
else
*error = EVAS_LOAD_ERROR_GENERIC;
@@ -155,28 +180,28 @@ evas_image_load_file_head_png(void *loader_data,
if (opts->emile.region.w > 0 && opts->emile.region.h > 0)
{
- if (((int) w32 < opts->emile.region.x + opts->emile.region.w) ||
- ((int) h32 < opts->emile.region.y + opts->emile.region.h))
+ if (((int) epi->w32 < opts->emile.region.x + opts->emile.region.w) ||
+ ((int) epi->h32 < opts->emile.region.y + opts->emile.region.h))
{
*error = EVAS_LOAD_ERROR_GENERIC;
goto close_file;
}
if(opts->emile.scale_down_by > 1)
{
- prop->w = opts->emile.region.w / opts->emile.scale_down_by;
- prop->h = opts->emile.region.h / opts->emile.scale_down_by;
+ prop->generic.w = opts->emile.region.w / opts->emile.scale_down_by;
+ prop->generic.h = opts->emile.region.h / opts->emile.scale_down_by;
}
else
{
- prop->w = opts->emile.region.w;
- prop->h = opts->emile.region.h;
+ prop->generic.w = opts->emile.region.w;
+ prop->generic.h = opts->emile.region.h;
}
}
else if (opts->emile.scale_down_by > 1)
{
- prop->w = (int) w32 / opts->emile.scale_down_by;
- prop->h = (int) h32 / opts->emile.scale_down_by;
- if ((prop->w < 1) || (prop->h < 1))
+ prop->generic.w = (int) epi->w32 / opts->emile.scale_down_by;
+ prop->generic.h = (int) epi->h32 / opts->emile.scale_down_by;
+ if ((prop->generic.w < 1) || (prop->generic.h < 1))
{
*error = EVAS_LOAD_ERROR_GENERIC;
goto close_file;
@@ -184,191 +209,458 @@ evas_image_load_file_head_png(void *loader_data,
}
else
{
- prop->w = (int) w32;
- prop->h = (int) h32;
+ prop->generic.w = (int) epi->w32;
+ prop->generic.h = (int) epi->h32;
}
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1;
- switch (color_type)
+ if (png_get_valid(epi->png_ptr, epi->info_ptr, PNG_INFO_tRNS)) epi->hasa = 1;
+ switch (epi->color_type)
{
case PNG_COLOR_TYPE_RGB_ALPHA:
- hasa = 1;
+ epi->hasa = 1;
break;
case PNG_COLOR_TYPE_GRAY_ALPHA:
- hasa = 1;
- prop->cspaces = cspace_grey_alpha;
+ epi->hasa = 1;
+ prop->generic.cspaces = cspace_grey_alpha;
break;
case PNG_COLOR_TYPE_GRAY:
- if (!hasa) prop->cspaces = cspace_grey;
+ if (!epi->hasa) prop->generic.cspaces = cspace_grey;
break;
}
- if (hasa) prop->alpha = 1;
+ if (epi->hasa) prop->generic.alpha = 1;
+
+ prop->need_data = eina_str_has_extension(eina_file_filename_get(f), ".9.png");
+ if (prop->need_data)
+ {
+ // Adjust size to take into account the 9 patch pixels information
+ prop->generic.w -= 2;
+ prop->generic.h -= 2;
+ }
- *error = EVAS_LOAD_ERROR_NONE;
r = EINA_TRUE;
+ if (!close_file) return r;
+
close_file:
- if (png_ptr) png_destroy_read_struct(&png_ptr,
- info_ptr ? &info_ptr : NULL,
+ if (epi->png_ptr) png_destroy_read_struct(&epi->png_ptr,
+ epi->info_ptr ? &epi->info_ptr : NULL,
NULL);
- if (epi.map) eina_file_map_free(f, epi. map);
+ if (epi->map) eina_file_map_free(f, epi->map);
+ memset(epi, 0, sizeof (Evas_PNG_Info));
return r;
}
static Eina_Bool
-evas_image_load_file_data_png(void *loader_data,
- Emile_Image_Property *prop,
- void *pixels,
+evas_image_load_file_head_png(void *loader_data,
+ Evas_Image_Property *prop,
int *error)
{
Evas_Loader_Internal *loader = loader_data;
+ Evas_PNG_Info epi;
+
+ memset(&epi, 0, sizeof (Evas_PNG_Info));
+
+ if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_TRUE))
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+static inline Eina_Bool
+_is_black(DATA32 *ptr)
+{
+ if (*ptr == BLACK) return EINA_TRUE;
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+evas_image_load_file_head_with_data_png(void *loader_data,
+ Evas_Image_Property *prop,
+ void *pixels,
+ int *error)
+{
+ Evas_Loader_Internal *loader = loader_data;
Evas_Image_Load_Opts *opts;
Eina_File *f;
+ unsigned char *src_ptr;
+ unsigned char *pixels2;
unsigned char *surface;
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL;
Evas_PNG_Info epi;
- png_uint_32 w32, h32;
+ Eina_Rectangle region;
unsigned int pack_offset;
int w, h;
- int bit_depth, color_type, interlace_type;
- volatile char hasa;
char passes;
int i, j, p, k;
volatile int scale_ratio = 1;
- volatile int region_set = 0;
int image_w = 0, image_h = 0;
volatile Eina_Bool r = EINA_FALSE;
+ Eina_Bool nine_patch = EINA_FALSE;
opts = loader->opts;
f = loader->f;
- hasa = 0;
+ memset(&epi, 0, sizeof (Evas_PNG_Info));
+ region = opts->emile.region;
+
+ if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE))
+ return EINA_FALSE;
+
+ image_w = epi.w32;
+ image_h = epi.h32;
- epi.map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
- if (!epi.map)
+ // We are leveragging region code to not load the border information pixels
+ // from 9patch files into the surface used by Evas
+ if (prop->need_data)
{
- *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
- goto close_file;
+ nine_patch = EINA_TRUE;
+
+ region.x += 1;
+ region.y += 1;
+
+ if (region.w > 0 && region.h > 0)
+ {
+ if (region.x + region.w + 1 < image_w) region.w += 1;
+ else region.w = image_w - region.x - 1;
+ if (region.y + region.h + 1 < image_h) region.h += 1;
+ else region.h = image_h - region.y - 1;
+ }
+ else
+ {
+ region.w = image_w - region.x - 1;
+ region.h = image_h - region.y - 1;
+ }
}
- epi.length = eina_file_size_get(f);
- epi.position = 0;
- if (epi.length < PNG_BYTES_TO_CHECK)
+ surface = pixels;
+
+ /* Prep for transformations... ultimately we want ARGB */
+ /* expand palette -> RGB if necessary */
+ if (epi.color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(epi.png_ptr);
+ /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
+ if ((epi.color_type == PNG_COLOR_TYPE_GRAY) ||
+ (epi.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
{
- *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+ if (prop->generic.cspace == EVAS_COLORSPACE_ARGB8888)
+ png_set_gray_to_rgb(epi.png_ptr);
+ if (epi.bit_depth < 8) png_set_expand_gray_1_2_4_to_8(epi.png_ptr);
+ }
+ /* reduce 16bit color -> 8bit color if necessary */
+ if (epi.bit_depth > 8) png_set_strip_16(epi.png_ptr);
+ /* pack all pixels to byte boundaries */
+ png_set_packing(epi.png_ptr);
+
+ w = prop->generic.w;
+ h = prop->generic.h;
+
+ switch (prop->generic.cspace)
+ {
+ case EVAS_COLORSPACE_ARGB8888:
+ /* we want ARGB */
+#ifdef WORDS_BIGENDIAN
+ png_set_swap_alpha(epi.png_ptr);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
+#else
+ png_set_bgr(epi.png_ptr);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
+#endif
+ pack_offset = sizeof(DATA32);
+ break;
+ case EVAS_COLORSPACE_AGRY88:
+ /* we want AGRY */
+#ifdef WORDS_BIGENDIAN
+ png_set_swap_alpha(epi.png_ptr);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
+#else
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
+#endif
+ pack_offset = sizeof(DATA16);
+ break;
+ case EVAS_COLORSPACE_GRY8: pack_offset = sizeof(DATA8); break;
+ default: abort();
+ }
+
+ passes = png_set_interlace_handling(epi.png_ptr);
+
+ /* we read image line by line in all case because of .9.png */
+ pixels2 = malloc(image_w * image_h * pack_offset);
+ if (!pixels2)
+ {
+ *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
goto close_file;
}
- /* if we havent read the header before, set the header data */
- if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK))
+ for (p = 0; p < passes; p++)
{
- *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
- goto close_file;
+ for (i = 0; i < image_h; i++)
+ png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL);
}
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_ptr)
+ png_read_end(epi.png_ptr, epi.info_ptr);
+
+ if (nine_patch && pack_offset != sizeof (DATA32))
{
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+ goto close_file;
}
- info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr)
+ if (nine_patch)
{
- png_destroy_read_struct(&png_ptr, NULL, NULL);
- *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
- goto close_file;
+ DATA32 *src_ptr1;
+ DATA32 *src_ptr2;
+ Eina_Bool stretchable = EINA_FALSE;
+ Eina_Rectangle optional_content = { 0 };
+ uint8_t current = 0;
+
+ memset(&prop->content, 0, sizeof (Eina_Rectangle));
+
+ // Top line of the image
+ src_ptr1 = (DATA32*) pixels2 + 1;
+ // Bottom line of the image
+ src_ptr2 = src_ptr1 + (image_h - 1) * image_w;
+
+ // Extract top stretch zone and horizontal content area
+ for (i = 1; i < image_w - 1;
+ i++, src_ptr1++, src_ptr2++)
+ {
+ Eina_Bool bp1 = _is_black(src_ptr1);
+ Eina_Bool bp2 = _is_black(src_ptr2);
+
+ // Updating horizontal area where content can be located
+ if (bp2)
+ _evas_image_png_update_x_content(&prop->content, i);
+
+ // In case no content area is provided, let's make it up
+ if (bp1)
+ _evas_image_png_update_x_content(&optional_content, i);
+
+ // Switching from a non stretchable to a stretchable zone or the opposite
+ if (!((stretchable && (bp1)) ||
+ (!stretchable && (!bp1))))
+ {
+ evas_loader_helper_stretch_zone_push(&prop->stretch.horizontal.zone,
+ &current, stretchable);
+ stretchable = !stretchable;
+ }
+
+ // Keep counting in the area we are in
+ current++;
+
+ if (current != 0x7F) continue;
+
+ // The bucket is full
+ evas_loader_helper_stretch_zone_push(&prop->stretch.horizontal.zone,
+ &current, stretchable);
+ }
+
+ current = 0;
+
+ // Left border of the image
+ src_ptr1 = (DATA32*) pixels2 + image_w;
+ // Right border of the image
+ src_ptr2 = src_ptr1 + (image_w - 1);
+
+ for (i = 1; i < image_h - 1;
+ i++, src_ptr1 += image_w, src_ptr2 += image_w)
+ {
+ Eina_Bool bp1 = _is_black(src_ptr1);
+ Eina_Bool bp2 = _is_black(src_ptr2);
+
+ // Updating vertical area where content can be located
+ if (bp2)
+ _evas_image_png_update_y_content(&prop->content, i);
+
+ // In case no content area is provided, let's make it up
+ if (bp1)
+ _evas_image_png_update_y_content(&optional_content, i);
+
+ // Switching from a non stretchable to a stretchable zone or the opposite
+ if (!((stretchable && (bp1)) ||
+ (!stretchable && (!bp1))))
+ {
+ evas_loader_helper_stretch_zone_push(&prop->stretch.vertical.zone,
+ &current, stretchable);
+ stretchable = !stretchable;
+ }
+
+ // Keep counting in the area we are in
+ current++;
+
+ if (current != 0x7F) continue;
+
+ // The bucket is full
+ evas_loader_helper_stretch_zone_push(&prop->stretch.vertical.zone,
+ &current, stretchable);
+ }
+
+ // Content zone is optional, if not provided, we should use the one we guessed
+ if (prop->content.x == 0 || prop->content.y == 0)
+ memcpy(&prop->content, &optional_content, sizeof (Eina_Rectangle));
+
+ // Check that the limit of our content zone are correct
+ // This could be handled as an incorrect file completly,
+ // but let's try to recover
+ if (prop->content.x == 0 || prop->content.y == 0)
+ {
+ *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+ goto close_file;
+ }
+ if ((prop->content.x + prop->content.w >= image_w - 1) &&
+ (prop->content.y + prop->content.h >= image_h - 1))
+ {
+ *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+ goto close_file;
+ }
+
+ if (eina_rectangle_intersection(&prop->content, &region))
+ {
+ prop->content.x--;
+ prop->content.y--;
+ }
}
- png_set_read_fn(png_ptr, &epi, _evas_image_png_read);
+ src_ptr = pixels2 + (region.y * image_w * pack_offset) + region.x * pack_offset;
- if (setjmp(png_jmpbuf(png_ptr)))
+ //general case: 4 bytes pixel.
+ if (pack_offset == sizeof(DATA32))
{
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
- goto close_file;
+ DATA32 *dst_ptr = (DATA32 *) surface;
+ DATA32 *src_ptr2 = (DATA32 *) src_ptr;
+
+ for (i = 0; i < h; i++)
+ {
+ for (j = 0; j < w; j++)
+ {
+ *dst_ptr = *src_ptr2;
+ ++dst_ptr;
+ src_ptr2 += scale_ratio;
+ }
+ src_ptr2 += scale_ratio * (image_w - w);
+ }
}
+ else
+ {
+ unsigned char *dst_ptr = surface;
+
+ for (i = 0; i < h; i++)
+ {
+ for (j = 0; j < w; j++)
+ {
+ for (k = 0; k < (int)pack_offset; k++)
+ dst_ptr[k] = src_ptr[k + scale_ratio * j * pack_offset];
+ dst_ptr += pack_offset;
+ }
+ src_ptr += scale_ratio * (image_w - w) * pack_offset;
+ }
+ }
+ free(pixels2);
+
+ prop->generic.premul = EINA_TRUE;
+
+ *error = EVAS_LOAD_ERROR_NONE;
+ r = EINA_TRUE;
+
+ close_file:
+ if (epi.png_ptr) png_destroy_read_struct(&epi.png_ptr,
+ epi.info_ptr ? &epi.info_ptr : NULL,
+ NULL);
+ if (epi.map) eina_file_map_free(f, epi.map);
+ return r;
+}
+
+static Eina_Bool
+evas_image_load_file_data_png(void *loader_data,
+ Evas_Image_Property *prop,
+ void *pixels,
+ int *error)
+{
+ Evas_Loader_Internal *loader = loader_data;
+ Evas_Image_Load_Opts *opts;
+ Eina_File *f;
- png_read_info(png_ptr, info_ptr);
- png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
- (png_uint_32 *) (&h32), &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
- image_w = w32;
- image_h = h32;
+ unsigned char *surface;
+ Evas_PNG_Info epi;
+ unsigned int pack_offset;
+ int w, h;
+ char passes;
+ int i, j, p, k;
+ volatile int scale_ratio = 1;
+ volatile int region_set = 0;
+ int image_w = 0, image_h = 0;
+ volatile Eina_Bool r = EINA_FALSE;
+
+ opts = loader->opts;
+ f = loader->f;
+
+ memset(&epi, 0, sizeof (Evas_PNG_Info));
+
+ if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE))
+ return EINA_FALSE;
+
+ image_w = epi.w32;
+ image_h = epi.h32;
if (opts->emile.scale_down_by > 1)
{
scale_ratio = opts->emile.scale_down_by;
- w32 /= scale_ratio;
- h32 /= scale_ratio;
+ epi.w32 /= scale_ratio;
+ epi.h32 /= scale_ratio;
}
if ((opts->emile.region.w > 0 && opts->emile.region.h > 0) &&
(opts->emile.region.w != image_w || opts->emile.region.h != image_h))
{
- w32 = opts->emile.region.w / scale_ratio;
- h32 = opts->emile.region.h / scale_ratio;
+ epi.w32 = opts->emile.region.w / scale_ratio;
+ epi.h32 = opts->emile.region.h / scale_ratio;
region_set = 1;
}
- if (prop->w != w32 ||
- prop->h != h32)
+ if (prop->generic.w != epi.w32 ||
+ prop->generic.h != epi.h32)
{
- *error = EVAS_LOAD_ERROR_GENERIC;
- goto close_file;
+ *error = EVAS_LOAD_ERROR_GENERIC;
+ goto close_file;
}
surface = pixels;
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
- {
- /* expand transparency entry -> alpha channel if present */
- png_set_tRNS_to_alpha(png_ptr);
- hasa = 1;
- }
- if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1;
- if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1;
- if (hasa) prop->alpha = 1;
/* Prep for transformations... ultimately we want ARGB */
/* expand palette -> RGB if necessary */
- if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
+ if (epi.color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(epi.png_ptr);
/* expand gray (w/reduced bits) -> 8-bit RGB if necessary */
- if ((color_type == PNG_COLOR_TYPE_GRAY) ||
- (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ if ((epi.color_type == PNG_COLOR_TYPE_GRAY) ||
+ (epi.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
{
- if (prop->cspace == EVAS_COLORSPACE_ARGB8888)
- png_set_gray_to_rgb(png_ptr);
- if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
+ if (prop->generic.cspace == EVAS_COLORSPACE_ARGB8888)
+ png_set_gray_to_rgb(epi.png_ptr);
+ if (epi.bit_depth < 8) png_set_expand_gray_1_2_4_to_8(epi.png_ptr);
}
/* reduce 16bit color -> 8bit color if necessary */
- if (bit_depth > 8) png_set_strip_16(png_ptr);
+ if (epi.bit_depth > 8) png_set_strip_16(epi.png_ptr);
/* pack all pixels to byte boundaries */
- png_set_packing(png_ptr);
+ png_set_packing(epi.png_ptr);
- w = w32;
- h = h32;
+ w = epi.w32;
+ h = epi.h32;
- switch (prop->cspace)
+ switch (prop->generic.cspace)
{
case EVAS_COLORSPACE_ARGB8888:
/* we want ARGB */
#ifdef WORDS_BIGENDIAN
- png_set_swap_alpha(png_ptr);
- if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
+ png_set_swap_alpha(epi.png_ptr);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
#else
- png_set_bgr(png_ptr);
- if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+ png_set_bgr(epi.png_ptr);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
#endif
pack_offset = sizeof(DATA32);
break;
case EVAS_COLORSPACE_AGRY88:
/* we want AGRY */
#ifdef WORDS_BIGENDIAN
- png_set_swap_alpha(png_ptr);
- if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
+ png_set_swap_alpha(epi.png_ptr);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE);
#else
- if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+ if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER);
#endif
pack_offset = sizeof(DATA16);
break;
@@ -376,7 +668,7 @@ evas_image_load_file_data_png(void *loader_data,
default: abort();
}
- passes = png_set_interlace_handling(png_ptr);
+ passes = png_set_interlace_handling(epi.png_ptr);
/* we read image line by line if scale down was set */
if (scale_ratio == 1 && region_set == 0)
@@ -384,9 +676,9 @@ evas_image_load_file_data_png(void *loader_data,
for (p = 0; p < passes; p++)
{
for (i = 0; i < h; i++)
- png_read_row(png_ptr, surface + (i * w * pack_offset), NULL);
+ png_read_row(epi.png_ptr, surface + (i * w * pack_offset), NULL);
}
- png_read_end(png_ptr, info_ptr);
+ png_read_end(epi.png_ptr, epi.info_ptr);
}
else
{
@@ -409,9 +701,9 @@ evas_image_load_file_data_png(void *loader_data,
unsigned short *pbuf;
for (skip_row = 0; skip_row < region_y; skip_row++)
- png_read_row(png_ptr, tmp_line, NULL);
+ png_read_row(epi.png_ptr, tmp_line, NULL);
- png_read_row(png_ptr, tmp_line, NULL);
+ png_read_row(epi.png_ptr, tmp_line, NULL);
src_ptr = tmp_line + (region_x * pack_offset);
//The first pixel, of the first line
@@ -450,7 +742,7 @@ evas_image_load_file_data_png(void *loader_data,
//vertical interpolation.
for (j = 0; j < scale_ratio; j++)
{
- png_read_row(png_ptr, tmp_line, NULL);
+ png_read_row(epi.png_ptr, tmp_line, NULL);
src_ptr = tmp_line + (region_x * pack_offset);
for (p = 0; p < line_size; ++p)
@@ -486,7 +778,7 @@ evas_image_load_file_data_png(void *loader_data,
}
for (skip_row = region_y + h * scale_ratio; skip_row < image_h; skip_row++)
- png_read_row(png_ptr, tmp_line, NULL);
+ png_read_row(epi.png_ptr, tmp_line, NULL);
}
else
{
@@ -499,8 +791,9 @@ evas_image_load_file_data_png(void *loader_data,
for (p = 0; p < passes; p++)
{
for (i = 0; i < image_h; i++)
- png_read_row(png_ptr, pixels2 + (i * image_w * pack_offset), NULL);
+ png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL);
}
+ png_read_end(epi.png_ptr, epi.info_ptr);
src_ptr = pixels2 + (region_y * image_w * pack_offset) + region_x * pack_offset;
@@ -541,15 +834,15 @@ evas_image_load_file_data_png(void *loader_data,
}
}
- prop->premul = EINA_TRUE;
+ prop->generic.premul = EINA_TRUE;
*error = EVAS_LOAD_ERROR_NONE;
r = EINA_TRUE;
close_file:
- if (png_ptr) png_destroy_read_struct(&png_ptr,
- info_ptr ? &info_ptr : NULL,
- NULL);
+ if (epi.png_ptr) png_destroy_read_struct(&epi.png_ptr,
+ epi.info_ptr ? &epi.info_ptr : NULL,
+ NULL);
if (epi.map) eina_file_map_free(f, epi.map);
return r;
}
@@ -559,9 +852,9 @@ static Evas_Image_Load_Func evas_image_load_png_func =
EVAS_IMAGE_LOAD_VERSION,
evas_image_load_file_open_png,
evas_image_load_file_close_png,
- (void*) evas_image_load_file_head_png,
- NULL,
- (void*) evas_image_load_file_data_png,
+ evas_image_load_file_head_png,
+ evas_image_load_file_head_with_data_png,
+ evas_image_load_file_data_png,
NULL,
EINA_TRUE,
EINA_FALSE