forked from enlightenment/efl
make loaders use "big image" macro to detect an image that is going to just
be way too big to ever allocate. probably code can do with other fixes too. also make jpeg loader rudametarily understand load regions. very brute-force. but enough for just this moment to do testing. SVN revision: 42507
This commit is contained in:
parent
ed7064edcc
commit
65f147aa81
|
@ -620,7 +620,7 @@ evas_cache_engine_image_load_data(Engine_Image_Entry *eim)
|
|||
assert(eim->src);
|
||||
assert(eim->cache);
|
||||
|
||||
if (eim->flags.loaded) return ;
|
||||
if (eim->flags.loaded) return;
|
||||
|
||||
if (eim->src)
|
||||
evas_cache_image_load_data(eim->src);
|
||||
|
|
|
@ -46,7 +46,7 @@ static pthread_t tid = 0;
|
|||
|
||||
static Eina_Bool running = EINA_FALSE;
|
||||
|
||||
static void* _evas_cache_background_load(void *);
|
||||
static void *_evas_cache_background_load(void *);
|
||||
#endif
|
||||
|
||||
#define FREESTRC(Var) \
|
||||
|
@ -412,16 +412,20 @@ _evas_cache_image_entry_preload_remove(Image_Entry *ie, const void *target)
|
|||
{
|
||||
Evas_Cache_Target *tg;
|
||||
|
||||
if (target) {
|
||||
if (target)
|
||||
{
|
||||
EINA_INLIST_FOREACH(ie->targets, tg)
|
||||
{
|
||||
if (tg->target == target) {
|
||||
if (tg->target == target)
|
||||
{
|
||||
ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
|
||||
free(tg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_evas_cache_image_async_call__locked(ie);
|
||||
|
||||
while (ie->targets)
|
||||
|
@ -622,7 +626,7 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
|
|||
file_length = strlen(file);
|
||||
key_length = key ? strlen(key) : 6;
|
||||
|
||||
size = file_length + key_length + 64;
|
||||
size = file_length + key_length + 128;
|
||||
hkey = alloca(sizeof (char) * size);
|
||||
|
||||
memcpy(hkey, file, file_length);
|
||||
|
@ -639,13 +643,15 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
|
|||
(lo &&
|
||||
(lo->scale_down_by == 0) &&
|
||||
(lo->dpi == 0.0) &&
|
||||
((lo->w == 0) || (lo->h == 0))))
|
||||
((lo->w == 0) || (lo->h == 0)) &&
|
||||
((lo->region.w == 0) || (lo->region.w == 0))
|
||||
))
|
||||
{
|
||||
lo = &prevent;
|
||||
if (key)
|
||||
format = "%s//://%s";
|
||||
else
|
||||
format = "%s//://%p";
|
||||
// if (key)
|
||||
// format = "%s//://%s";
|
||||
// else
|
||||
// format = "%s//://%p";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -668,6 +674,26 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
|
|||
size += 1;
|
||||
|
||||
size += eina_convert_xtoa(lo->h, hkey + size);
|
||||
|
||||
hkey[size] = '/';
|
||||
size += 1;
|
||||
|
||||
size += eina_convert_xtoa(lo->region.x, hkey + size);
|
||||
|
||||
hkey[size] = '+';
|
||||
size += 1;
|
||||
|
||||
size += eina_convert_xtoa(lo->region.y, hkey + size);
|
||||
|
||||
hkey[size] = '.';
|
||||
size += 1;
|
||||
|
||||
size += eina_convert_xtoa(lo->region.w, hkey + size);
|
||||
|
||||
hkey[size] = 'x';
|
||||
size += 1;
|
||||
|
||||
size += eina_convert_xtoa(lo->region.h, hkey + size);
|
||||
}
|
||||
|
||||
hkey[size] = '\0';
|
||||
|
@ -1270,6 +1296,8 @@ _evas_cache_background_load(void *data)
|
|||
current->channel++;
|
||||
cache = current->cache;
|
||||
|
||||
if (!current->flags.loaded)
|
||||
{
|
||||
error = cache->func.load(current);
|
||||
if (cache->func.debug)
|
||||
cache->func.debug("load", current);
|
||||
|
@ -1284,6 +1312,7 @@ _evas_cache_background_load(void *data)
|
|||
{
|
||||
current->flags.loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
current->flags.preload = 0;
|
||||
|
||||
|
|
|
@ -46,9 +46,9 @@ _evas_image_foreach_loader(const Eina_Hash *hash, const char *key, Evas_Module *
|
|||
evas_module_use(em);
|
||||
if (evas_image_load_func && evas_image_load_func->file_head(ie, ie->file, ie->key))
|
||||
{
|
||||
ie->info.module = (void*) em;
|
||||
ie->info.loader = (void*) evas_image_load_func;
|
||||
evas_module_ref((Evas_Module*) ie->info.module);
|
||||
ie->info.module = (void *)em;
|
||||
ie->info.loader = (void *)evas_image_load_func;
|
||||
evas_module_ref((Evas_Module *)ie->info.module);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
|
|||
{
|
||||
for (i = 0, ++dot; i < (sizeof (loaders) / sizeof (struct ext_loader_s)); ++i)
|
||||
{
|
||||
if (!strcasecmp (dot, loaders[i].extention))
|
||||
if (!strcasecmp(dot, loaders[i].extention))
|
||||
{
|
||||
loader = loaders[i].loader;
|
||||
break;
|
||||
|
@ -108,7 +108,7 @@ evas_common_load_rgba_image_module_from_file(Image_Entry *ie)
|
|||
|
||||
/* This is our last chance, try all known image loader. */
|
||||
/* FIXME: We could use eina recursive module search ability. */
|
||||
for (i = 0; i < sizeof (loaders_name) / sizeof (char *); ++i)
|
||||
for (i = 0; i < sizeof (loaders_name) / sizeof (char *); i++)
|
||||
{
|
||||
em = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loaders_name[i]);
|
||||
if (em)
|
||||
|
@ -165,7 +165,9 @@ evas_common_load_rgba_image_data_from_file(Image_Entry *ie)
|
|||
evas_image_load_func = ie->info.loader;
|
||||
evas_module_use((Evas_Module*) ie->info.module);
|
||||
if (!evas_image_load_func->file_data(ie, ie->file, ie->key))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// evas_module_unref((Evas_Module*) ie->info.module);
|
||||
// ie->info.module = NULL;
|
||||
|
|
|
@ -166,7 +166,11 @@ void *alloca (size_t);
|
|||
/* use exact rects for updates not tiles */
|
||||
/* #define RECTUPDATE */
|
||||
#define TILESIZE 8
|
||||
#define IMG_MAX_SIZE 65536
|
||||
#define IMG_MAX_SIZE 65000
|
||||
|
||||
#define IMG_TOO_BIG(w, h) \
|
||||
((((unsigned long long)w) * ((unsigned long long)h)) > \
|
||||
(1 << (29 * (sizeof(void *) / 4))))
|
||||
|
||||
#ifdef BUILD_SMALL_DITHER_MASK
|
||||
# define DM_TABLE _evas_dither_44
|
||||
|
|
|
@ -56,7 +56,8 @@ evas_image_load_file_head_edb(Image_Entry *ie, const char *file, const char *key
|
|||
}
|
||||
w = header[1];
|
||||
h = header[2];
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(w, h))
|
||||
{
|
||||
free(ret);
|
||||
e_db_close(db);
|
||||
|
@ -120,7 +121,8 @@ evas_image_load_file_data_edb(Image_Entry *ie, const char *file, const char *key
|
|||
}
|
||||
w = header[1];
|
||||
h = header[2];
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(w, h))
|
||||
{
|
||||
free(ret);
|
||||
e_db_close(db);
|
||||
|
|
|
@ -32,6 +32,7 @@ evas_image_load_file_head_eet(Image_Entry *ie, const char *file, const char *key
|
|||
if (!ef) return 0;
|
||||
ok = eet_data_image_header_read(ef, key,
|
||||
&w, &h, &alpha, &compression, &quality, &lossy);
|
||||
if (IMG_TOO_BIG(w, h)) goto on_error;
|
||||
if (!ok) goto on_error;
|
||||
if (alpha) ie->flags.alpha = 1;
|
||||
ie->w = w;
|
||||
|
@ -59,6 +60,7 @@ evas_image_load_file_data_eet(Image_Entry *ie, const char *file, const char *key
|
|||
if (!ef) return 0;
|
||||
ok = eet_data_image_header_read(ef, key,
|
||||
&w, &h, &alpha, &compression, &quality, &lossy);
|
||||
if (IMG_TOO_BIG(w, h)) goto on_error;
|
||||
if (!ok) goto on_error;
|
||||
evas_cache_image_surface_alloc(ie, w, h);
|
||||
ok = eet_data_image_read_to_surface(ef, key, 0, 0,
|
||||
|
|
|
@ -65,7 +65,8 @@ evas_image_load_file_head_gif(Image_Entry *ie, const char *file, const char *key
|
|||
}
|
||||
w = gif->Image.Width;
|
||||
h = gif->Image.Height;
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(w, h))
|
||||
{
|
||||
DGifCloseFile(gif);
|
||||
return 0;
|
||||
|
|
|
@ -104,13 +104,8 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
/* head decoding */
|
||||
w = cinfo.output_width;
|
||||
h = cinfo.output_height;
|
||||
if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
|
||||
{
|
||||
RECTS_CLIP_TO_RECT(ie->load_opts.region.x, ie->load_opts.region.y,
|
||||
ie->load_opts.region.w, ie->load_opts.region.h,
|
||||
0, 0, w, h);
|
||||
}
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
||||
(IMG_TOO_BIG(w, h)))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
|
@ -182,9 +177,23 @@ evas_image_load_file_head_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
jpeg_start_decompress(&cinfo);
|
||||
}
|
||||
|
||||
// FIXME: handle region if specified
|
||||
ie->w = cinfo.output_width;
|
||||
ie->h = cinfo.output_height;
|
||||
|
||||
// be nice and clip region to image. if its totally outside, fail load
|
||||
if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
|
||||
{
|
||||
RECTS_CLIP_TO_RECT(ie->load_opts.region.x, ie->load_opts.region.y,
|
||||
ie->load_opts.region.w, ie->load_opts.region.h,
|
||||
0, 0, ie->w, ie->h);
|
||||
if ((ie->load_opts.region.w <= 0) || (ie->load_opts.region.h <= 0))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
}
|
||||
ie->w = ie->load_opts.region.w;
|
||||
ie->h = ie->load_opts.region.h;
|
||||
}
|
||||
/* end head decoding */
|
||||
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
@ -200,6 +209,7 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
DATA8 *ptr, *line[16], *data;
|
||||
DATA32 *ptr2;
|
||||
int x, y, l, i, scans, count;
|
||||
int region = 0;
|
||||
|
||||
if (!f) return 0;
|
||||
cinfo.err = jpeg_std_error(&(jerr.pub));
|
||||
|
@ -250,10 +260,19 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
w = cinfo.output_width;
|
||||
h = cinfo.output_height;
|
||||
|
||||
if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
|
||||
region = 1;
|
||||
if ((w != ie->w) || (h != ie->h))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
// OK. region decode happening. a sub-set of the image
|
||||
// jpeg_destroy_decompress(&cinfo);
|
||||
// return 0;
|
||||
}
|
||||
if ((region) &&
|
||||
((ie->w != ie->load_opts.region.w) || (ie->h != ie->load_opts.region.h)))
|
||||
{
|
||||
ie->w = ie->load_opts.region.w;
|
||||
ie->h = ie->load_opts.region.h;
|
||||
}
|
||||
|
||||
if (!(((cinfo.out_color_space == JCS_RGB) &&
|
||||
|
@ -272,17 +291,18 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
return 0;
|
||||
}
|
||||
data = alloca(w * 16 * cinfo.output_components);
|
||||
evas_cache_image_surface_alloc(ie, w, h);
|
||||
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
||||
if (ie->flags.loaded)
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
ptr2 = evas_cache_image_pixels(ie);
|
||||
count = 0;
|
||||
/* We handle first CMYK (4 components) */
|
||||
if (cinfo.output_components == 4)
|
||||
{
|
||||
// FIXME: handle region
|
||||
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||||
line[i] = data + (i * w * 4);
|
||||
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
||||
|
@ -331,6 +351,17 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
/* We handle then RGB with 3 components */
|
||||
else if (cinfo.output_components == 3)
|
||||
{
|
||||
if (region)
|
||||
{
|
||||
printf("R| %p %5ix%5i %s: %5i %5i %5ix%5i\n",
|
||||
ie,
|
||||
ie->w, ie->h,
|
||||
ie->file,
|
||||
ie->load_opts.region.x,
|
||||
ie->load_opts.region.y,
|
||||
ie->load_opts.region.w,
|
||||
ie->load_opts.region.h);
|
||||
}
|
||||
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||||
line[i] = data + (i * w * 3);
|
||||
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
||||
|
@ -339,6 +370,8 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
scans = cinfo.rec_outbuf_height;
|
||||
if ((h - l) < scans) scans = h - l;
|
||||
ptr = data;
|
||||
if (!region)
|
||||
{
|
||||
for (y = 0; y < scans; y++)
|
||||
{
|
||||
for (x = 0; x < w; x++)
|
||||
|
@ -350,6 +383,39 @@ evas_image_load_file_data_jpeg_internal(Image_Entry *ie, FILE *f)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if line # > region last line, break
|
||||
if (l >= (ie->load_opts.region.y + ie->load_opts.region.h))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return 1;
|
||||
}
|
||||
// els if scan block intersects region start or later
|
||||
else if ((l + scans) >
|
||||
(ie->load_opts.region.y))
|
||||
{
|
||||
for (y = 0; y < scans; y++)
|
||||
{
|
||||
if (((y + l) >= ie->load_opts.region.y) &&
|
||||
((y + l) < (ie->load_opts.region.y + ie->load_opts.region.h)))
|
||||
{
|
||||
ptr += (3 * ie->load_opts.region.x);
|
||||
for (x = 0; x < ie->load_opts.region.w; x++)
|
||||
{
|
||||
*ptr2 =
|
||||
(0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
|
||||
ptr += 3;
|
||||
ptr2++;
|
||||
}
|
||||
ptr += (3 * (w - (ie->load_opts.region.x + ie->load_opts.region.w)));
|
||||
}
|
||||
else
|
||||
ptr += (3 * w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* We finally handle RGB with 1 component */
|
||||
else if (cinfo.output_components == 1)
|
||||
|
|
|
@ -85,7 +85,8 @@ evas_image_load_file_head_png(Image_Entry *ie, const char *file, const char *key
|
|||
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))
|
||||
if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(w32, h32))
|
||||
{
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
goto close_file;
|
||||
|
|
|
@ -85,7 +85,8 @@ evas_image_load_file_head_svg(Image_Entry *ie, const char *file, const char *key
|
|||
rsvg_handle_get_dimensions(rsvg, &dim);
|
||||
w = dim.width;
|
||||
h = dim.height;
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
|
||||
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(w, h))
|
||||
{
|
||||
// rsvg_handle_close(rsvg, NULL);
|
||||
g_object_unref(rsvg);
|
||||
|
|
|
@ -174,7 +174,8 @@ evas_image_load_file_head_tiff(Image_Entry *ie, const char *file, const char *ke
|
|||
if (tiff_image.alpha != EXTRASAMPLE_UNSPECIFIED)
|
||||
ie->flags.alpha = 1;
|
||||
if ((tiff_image.width < 1) || (tiff_image.height < 1) ||
|
||||
(tiff_image.width > IMG_MAX_SIZE) || (tiff_image.height > IMG_MAX_SIZE))
|
||||
(tiff_image.width > IMG_MAX_SIZE) || (tiff_image.height > IMG_MAX_SIZE) ||
|
||||
IMG_TOO_BIG(tiff_image.width, tiff_image.height))
|
||||
{
|
||||
TIFFClose(tif);
|
||||
return 0;
|
||||
|
|
|
@ -245,6 +245,15 @@ evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UN
|
|||
xpm_parse_done();
|
||||
return 0;
|
||||
}
|
||||
if (IMG_TOO_BIG(w, h))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"XPM ERROR: Image just too big to ever allocate\n");
|
||||
free(line);
|
||||
fclose(f);
|
||||
xpm_parse_done();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cmap)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue