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..4ffd5643c6 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; @@ -36,6 +45,34 @@ static const Evas_Colorspace cspace_grey_alpha[2] = { EVAS_COLORSPACE_ARGB8888 }; +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) { @@ -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)) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + 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; + } + epi->info_ptr = png_create_info_struct(epi->png_ptr); + if (!epi->info_ptr) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + 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; } - if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK)) + 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)) { - *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) - { - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto close_file; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - *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))) - { - *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)) - { - 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->info.w = opts->emile.region.w / opts->emile.scale_down_by; + prop->info.h = opts->emile.region.h / opts->emile.scale_down_by; } else { - prop->w = opts->emile.region.w; - prop->h = opts->emile.region.h; + prop->info.w = opts->emile.region.w; + prop->info.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->info.w = (int) epi->w32 / opts->emile.scale_down_by; + prop->info.h = (int) epi->h32 / opts->emile.scale_down_by; + if ((prop->info.w < 1) || (prop->info.h < 1)) { *error = EVAS_LOAD_ERROR_GENERIC; goto close_file; @@ -184,40 +209,371 @@ evas_image_load_file_head_png(void *loader_data, } else { - prop->w = (int) w32; - prop->h = (int) h32; + prop->info.w = (int) epi->w32; + prop->info.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->info.cspaces = cspace_grey_alpha; break; case PNG_COLOR_TYPE_GRAY: - if (!hasa) prop->cspaces = cspace_grey; + if (!epi->hasa) prop->info.cspaces = cspace_grey; break; } - if (hasa) prop->alpha = 1; + if (epi->hasa) prop->info.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->info.w -= 2; + prop->info.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_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; + Evas_PNG_Info epi; + Eina_Rectangle region; + unsigned int pack_offset; + int w, h; + char passes; + int i, j, p, k; + volatile int scale_ratio = 1; + 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; + + 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; + + // 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) + { + 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; + } + } + + 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)) + { + if (prop->info.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->info.w; + h = prop->info.h; + + switch (prop->info.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; + } + + for (p = 0; p < passes; p++) + { + for (i = 0; i < image_h; i++) + png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL); + } + png_read_end(epi.png_ptr, epi.info_ptr); + + if (nine_patch && pack_offset != sizeof (DATA32)) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto close_file; + } + + if (nine_patch) + { + 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_region_push(&prop->stretch.horizontal.region, + ¤t, stretchable); + stretchable = !stretchable; + } + + // Keep counting in the area we are in + current++; + + if (current != 0x7F) continue; + + // The bucket is full + evas_loader_helper_stretch_region_push(&prop->stretch.horizontal.region, + ¤t, 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_region_push(&prop->stretch.vertical.region, + ¤t, stretchable); + stretchable = !stretchable; + } + + // Keep counting in the area we are in + current++; + + if (current != 0x7F) continue; + + // The bucket is full + evas_loader_helper_stretch_region_push(&prop->stretch.vertical.region, + ¤t, 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; + } + + // Correct the work space to be the same as the image one for intersection + // with region and correct back afterward. + prop->content.x++; + prop->content.y++; + if (eina_rectangle_intersection(&prop->content, ®ion)) + { + prop->content.x--; + prop->content.y--; + } + } + + src_ptr = pixels2 + (region.y * image_w * pack_offset) + region.x * pack_offset; + + //general case: 4 bytes pixel. + if (pack_offset == sizeof(DATA32)) + { + 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->info.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, - Emile_Image_Property *prop, + Evas_Image_Property *prop, void *pixels, int *error) { @@ -226,14 +582,9 @@ evas_image_load_file_data_png(void *loader_data, Eina_File *f; unsigned char *surface; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; Evas_PNG_Info epi; - png_uint_32 w32, h32; 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; @@ -244,131 +595,76 @@ evas_image_load_file_data_png(void *loader_data, opts = loader->opts; f = loader->f; - hasa = 0; + memset(&epi, 0, sizeof (Evas_PNG_Info)); - epi.map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); - if (!epi.map) - { - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - goto close_file; - } - epi.length = eina_file_size_get(f); - epi.position = 0; + if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE)) + return EINA_FALSE; - if (epi.length < PNG_BYTES_TO_CHECK) - { - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - 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)) - { - *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) - { - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto close_file; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - *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_destroy_read_struct(&png_ptr, &info_ptr, NULL); - *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); - image_w = w32; - image_h = h32; + 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->info.w != epi.w32 || + prop->info.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->info.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->info.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 +672,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 +680,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 +705,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 +746,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 +782,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 +795,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 +838,15 @@ evas_image_load_file_data_png(void *loader_data, } } - prop->premul = EINA_TRUE; + prop->info.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 +856,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