forked from enlightenment/efl
From: Jiyoun Park <jy0703.park@samsung.com>
Subject: Re: [E-devel] [Patch] Implement scale down decoding feature of bmp loader I implement scale down decoding feature of bmp loader using down sample algorithm. Desktop have low risk to go wrong memory problem during big image decoding, but mobile device is different. Raster said it is life (meet memory problem during big image decoding), and it is enough to return decoding fail. But I think it seems a bit harsh, because 2 or 3 bmp image (5000X5000 size: for example) can cause application close because of memory lack. SVN revision: 64163
This commit is contained in:
parent
eca175dbe5
commit
a1e7fa3103
|
@ -8,6 +8,8 @@
|
|||
# include <Evil.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "evas_common.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
|
@ -259,7 +261,14 @@ evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
/* It is not bad idea that bmp loader support scale down decoding
|
||||
* because of memory issue in mobile world.*/
|
||||
if (ie->load_opts.scale_down_by > 1)
|
||||
{
|
||||
w /= ie->load_opts.scale_down_by;
|
||||
h /= ie->load_opts.scale_down_by;
|
||||
}
|
||||
|
||||
if (bit_count < 16)
|
||||
{
|
||||
if ((palette_size < 0) || (palette_size > 256)) pal_num = 256;
|
||||
|
@ -345,7 +354,14 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
int fsize = 0;
|
||||
unsigned int bmpsize;
|
||||
unsigned short res1, res2;
|
||||
|
||||
|
||||
/* for scale decoding */
|
||||
unsigned int *scale_surface = NULL, *scale_pix = NULL;
|
||||
int scale_ratio = 1, image_w = 0, image_h = 0;
|
||||
int row_size = 0; /* Row size is rounded up to a multiple of 4bytes */
|
||||
int read_line = 0; /* total read line */
|
||||
|
||||
|
||||
f = fopen(file, "rb");
|
||||
if (!f)
|
||||
{
|
||||
|
@ -533,20 +549,40 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
/* It is not bad idea that bmp loader support scale down decoding
|
||||
* because of memory issue in mobile world. */
|
||||
if (ie->load_opts.scale_down_by > 1)
|
||||
scale_ratio = ie->load_opts.scale_down_by;
|
||||
image_w = w;
|
||||
image_h = h;
|
||||
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
w /= scale_ratio;
|
||||
h /= scale_ratio;
|
||||
|
||||
if ((w < 1) || (h < 1) )
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto close_file;
|
||||
}
|
||||
}
|
||||
|
||||
if ((w != (int)ie->w) || (h != (int)ie->h))
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||
goto close_file;
|
||||
}
|
||||
evas_cache_image_surface_alloc(ie, w, h);
|
||||
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
||||
surface = evas_cache_image_pixels(ie);
|
||||
if (!surface)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
goto close_file;
|
||||
}
|
||||
|
||||
|
||||
row_size = ceil((double)(image_w * bit_count) / 32) * 4;
|
||||
|
||||
if (bit_count < 16)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -580,25 +616,52 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
pal[i] = ARGB_JOIN(a, r, g, b);
|
||||
}
|
||||
fseek(f, offset, SEEK_SET);
|
||||
buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
|
||||
|
||||
if ((scale_ratio == 1) || (comp !=0))
|
||||
buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
|
||||
else
|
||||
{
|
||||
scale_surface = malloc(image_w * sizeof(DATA32)); //for one line decoding
|
||||
if (!scale_surface)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
goto close_file;
|
||||
}
|
||||
buffer = malloc(row_size); // scale down is usually set because of memory issue, so read line by line
|
||||
}
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
goto close_file;
|
||||
}
|
||||
buffer_end = buffer + image_size;
|
||||
if ((scale_ratio == 1) || (comp !=0))
|
||||
buffer_end = buffer + image_size;
|
||||
else
|
||||
buffer_end = buffer + row_size;
|
||||
p = buffer;
|
||||
if (fread(buffer, image_size, 1, f) != 1) goto close_file;
|
||||
|
||||
|
||||
if ((scale_ratio == 1) || (comp !=0))
|
||||
{
|
||||
if (fread(buffer, image_size, 1, f) != 1) goto close_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
}
|
||||
|
||||
if (bit_count == 1)
|
||||
{
|
||||
if (comp == 0) // no compression
|
||||
{
|
||||
pix = surface;
|
||||
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
||||
for (x = 0; x < w; x++)
|
||||
if (scale_ratio > 1) pix = scale_surface; // one line decoding
|
||||
|
||||
for (x = 0; x < image_w; x++)
|
||||
{
|
||||
if ((x & 0x7) == 0x0)
|
||||
{
|
||||
|
@ -636,10 +699,34 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
if ((x & 0x7) != 0) p++;
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
if (!right_way_up) scale_pix = surface + ((h - 1 - y) * w);
|
||||
else scale_pix = surface + (y * w);
|
||||
|
||||
pix = scale_surface;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*scale_pix = *pix;
|
||||
scale_pix ++;
|
||||
pix += scale_ratio;
|
||||
}
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((x & 0x7) != 0) p++;
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -653,7 +740,8 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
for (y = 0; y < h; y++)
|
||||
{
|
||||
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
||||
for (x = 0; x < w; x++)
|
||||
if (scale_ratio > 1) pix = scale_surface; // one line decoding
|
||||
for (x = 0; x < image_w; x++)
|
||||
{
|
||||
if ((x & 0x1) == 0x1)
|
||||
{
|
||||
|
@ -667,116 +755,184 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
if ((x & 0x1) != 0) p++;
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
if (!right_way_up) scale_pix = surface + ((h - 1 - y) * w);
|
||||
else scale_pix = surface + (y * w);
|
||||
|
||||
pix = scale_surface;
|
||||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*scale_pix = *pix;
|
||||
scale_pix ++;
|
||||
pix += scale_ratio;
|
||||
}
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((x & 0x1) != 0) p++;
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (comp == 2) // rle 4bit/pixel
|
||||
{
|
||||
int count = 0, done = 0, wpad;
|
||||
int scale_x = 0, scale_y = 0;
|
||||
Eina_Bool scale_down_line = EINA_TRUE;
|
||||
|
||||
pix = surface;
|
||||
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
||||
wpad = ((w + 1) / 2) * 2;
|
||||
wpad = ((image_w + 1) / 2) * 2;
|
||||
while (p < buffer_end)
|
||||
{
|
||||
if (p[0])
|
||||
{
|
||||
if ((x + p[0]) <= wpad)
|
||||
{
|
||||
unsigned int col1 = pal[p[1] >> 4];
|
||||
unsigned int col2 = pal[p[1] & 0xf];
|
||||
|
||||
count = p[0] / 2;
|
||||
while (count > 0)
|
||||
if (scale_down_line)
|
||||
{
|
||||
if ((x + p[0]) <= wpad)
|
||||
{
|
||||
if (x < w)
|
||||
unsigned int col1 = pal[p[1] >> 4];
|
||||
unsigned int col2 = pal[p[1] & 0xf];
|
||||
|
||||
count = p[0] / 2;
|
||||
while (count > 0)
|
||||
{
|
||||
pix[0] = col1;
|
||||
if (x < w)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = col1;
|
||||
pix++;
|
||||
scale_x++;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
if (x < w)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = col2;
|
||||
pix++;
|
||||
scale_x++;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
if (p[0] & 0x1)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = col1;
|
||||
pix++;
|
||||
scale_x++;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
if (x < w)
|
||||
{
|
||||
pix[1] = col2;
|
||||
x++;
|
||||
}
|
||||
pix += 2;
|
||||
count--;
|
||||
}
|
||||
if (p[0] & 0x1)
|
||||
{
|
||||
*pix = col1;
|
||||
x++;
|
||||
pix++;
|
||||
}
|
||||
}
|
||||
}
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (p[1])
|
||||
{
|
||||
case 0: // EOL
|
||||
x = 0;
|
||||
y++;
|
||||
if (!right_way_up)
|
||||
pix = surface + ((h - 1 - y) * w);
|
||||
else
|
||||
pix = surface + (y * w);
|
||||
if (y >= h)
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
p += 2;
|
||||
break;
|
||||
case 1: // EOB
|
||||
p = buffer_end;
|
||||
break;
|
||||
case 2: // DELTA
|
||||
x += p[2];
|
||||
y += p[3];
|
||||
if ((x >= w) || (y >= h))
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
if (!right_way_up)
|
||||
pix = surface + x + ((h - 1 - y) * w);
|
||||
else
|
||||
pix = surface + x + (y * w);
|
||||
p += 4;
|
||||
break;
|
||||
default:
|
||||
count = p[1];
|
||||
if (((p + count) > buffer_end) ||
|
||||
((x + count) > w))
|
||||
{
|
||||
p = buffer_end;
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
done = count;
|
||||
count /= 2;
|
||||
while (count > 0)
|
||||
{
|
||||
pix[0] = pal[*p >> 4];
|
||||
pix[1] = pal[*p & 0xf];
|
||||
pix += 2;
|
||||
p++;
|
||||
count--;
|
||||
}
|
||||
x += done;
|
||||
if (done & 0x1)
|
||||
{
|
||||
*pix = pal[*p >> 4];
|
||||
p++;
|
||||
}
|
||||
if ((done & 0x3) == 0x1)
|
||||
p += 2;
|
||||
else if ((done & 0x3) == 0x2)
|
||||
p += 1;
|
||||
break;
|
||||
case 0: // EOL
|
||||
x = 0;
|
||||
scale_x = 0;
|
||||
y++;
|
||||
if ((y % scale_ratio) == 0)
|
||||
{
|
||||
scale_y++;
|
||||
scale_down_line = EINA_TRUE;
|
||||
if (!right_way_up)
|
||||
pix = surface + ((h - 1 - scale_y) * w);
|
||||
else
|
||||
pix = surface + (scale_y * w);
|
||||
}
|
||||
else
|
||||
scale_down_line = EINA_FALSE;
|
||||
if (scale_y >= h)
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
p += 2;
|
||||
break;
|
||||
case 1: // EOB
|
||||
p = buffer_end;
|
||||
break;
|
||||
case 2: // DELTA
|
||||
x += p[2];
|
||||
y += p[3];
|
||||
scale_x = x / scale_ratio;
|
||||
scale_y = y / scale_ratio;
|
||||
if ((scale_x >= w) || (scale_y >= h))
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
if (!right_way_up)
|
||||
pix = surface + scale_x + ((h - 1 - scale_y) * w);
|
||||
else
|
||||
pix = surface + scale_x + (scale_y * w);
|
||||
p += 4;
|
||||
break;
|
||||
default:
|
||||
count = p[1];
|
||||
if (((p + count) > buffer_end) ||
|
||||
((x + count) > w))
|
||||
{
|
||||
p = buffer_end;
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
done = count;
|
||||
count /= 2;
|
||||
while (count > 0)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = pal[*p >> 4];
|
||||
pix++;
|
||||
scale_x++;
|
||||
}
|
||||
x++;
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = pal[*p & 0xf];
|
||||
pix++;
|
||||
scale_x++;
|
||||
}
|
||||
x++;
|
||||
|
||||
p++;
|
||||
count--;
|
||||
}
|
||||
|
||||
if (done & 0x1)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = pal[*p >> 4];
|
||||
scale_x++;
|
||||
}
|
||||
x++;
|
||||
p++;
|
||||
}
|
||||
if ((done & 0x3) == 0x1)
|
||||
p += 2;
|
||||
else if ((done & 0x3) == 0x2)
|
||||
p += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -795,93 +951,131 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
for (x = 0; x < w; x++)
|
||||
{
|
||||
*pix = pal[*p];
|
||||
p++;
|
||||
p += scale_ratio;
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (comp == 1) // rle 8bit/pixel
|
||||
{
|
||||
int count = 0, done = 0;
|
||||
int scale_x = 0, scale_y = 0;
|
||||
Eina_Bool scale_down_line = EINA_TRUE;
|
||||
|
||||
pix = surface;
|
||||
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
||||
|
||||
while (p < buffer_end)
|
||||
{
|
||||
if (p[0])
|
||||
{
|
||||
if ((x + p[0]) <= w)
|
||||
{
|
||||
unsigned int col = pal[p[1]];
|
||||
|
||||
count = p[0];
|
||||
while (count > 0)
|
||||
if (scale_down_line)
|
||||
{
|
||||
if ((x + p[0]) <= image_w)
|
||||
{
|
||||
*pix = col;
|
||||
pix++;
|
||||
count--;
|
||||
unsigned int col = pal[p[1]];
|
||||
|
||||
count = p[0];
|
||||
while (count > 0)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = col;
|
||||
pix++;
|
||||
scale_x ++;
|
||||
}
|
||||
x++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
x += p[0];
|
||||
}
|
||||
}
|
||||
p += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (p[1])
|
||||
{
|
||||
case 0: // EOL
|
||||
x = 0;
|
||||
y++;
|
||||
if (!right_way_up)
|
||||
pix = surface + ((h - 1 - y) * w);
|
||||
else
|
||||
pix = surface + (y * w);
|
||||
if (y >= h)
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
p += 2;
|
||||
break;
|
||||
case 1: // EOB
|
||||
p = buffer_end;
|
||||
break;
|
||||
case 2: // DELTA
|
||||
x += p[2];
|
||||
y += p[3];
|
||||
if ((x >= w) || (y >= h))
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
if (!right_way_up)
|
||||
pix = surface + x + ((h - 1 - y) * w);
|
||||
else
|
||||
pix = surface + x + (y * w);
|
||||
p += 4;
|
||||
break;
|
||||
default:
|
||||
count = p[1];
|
||||
if (((p + count) > buffer_end) ||
|
||||
((x + count) > w))
|
||||
{
|
||||
p = buffer_end;
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
done = count;
|
||||
while (count > 0)
|
||||
{
|
||||
*pix = pal[*p];
|
||||
pix++;
|
||||
p++;
|
||||
count--;
|
||||
}
|
||||
x += done;
|
||||
if (done & 0x1) p++;
|
||||
break;
|
||||
case 0: // EOL
|
||||
x = 0;
|
||||
scale_x = 0;
|
||||
y++;
|
||||
if ((y % scale_ratio) == 0)
|
||||
{
|
||||
scale_y++;
|
||||
scale_down_line = EINA_TRUE;
|
||||
if (!right_way_up)
|
||||
pix = surface + ((h - 1 - scale_y) * w);
|
||||
else
|
||||
pix = surface + (scale_y * w);
|
||||
}
|
||||
else
|
||||
scale_down_line = EINA_FALSE;
|
||||
|
||||
if (scale_y >= h)
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
p += 2;
|
||||
break;
|
||||
case 1: // EOB
|
||||
p = buffer_end;
|
||||
break;
|
||||
case 2: // DELTA
|
||||
x += p[2];
|
||||
y += p[3];
|
||||
scale_x = x / scale_ratio;
|
||||
scale_y = y / scale_ratio;
|
||||
if ((scale_x >= w) || (scale_y >= h))
|
||||
{
|
||||
p = buffer_end;
|
||||
}
|
||||
if (!right_way_up)
|
||||
pix = surface + scale_x + ((h - 1 - scale_y) * w);
|
||||
else
|
||||
pix = surface + scale_x + (scale_y * w);
|
||||
p += 4;
|
||||
break;
|
||||
default:
|
||||
count = p[1];
|
||||
if (((p + count) > buffer_end) ||
|
||||
((x + count) > image_w))
|
||||
{
|
||||
p = buffer_end;
|
||||
break;
|
||||
}
|
||||
p += 2;
|
||||
done = count;
|
||||
while (count > 0)
|
||||
{
|
||||
if (((x % scale_ratio) == 0) && (scale_x < w))
|
||||
{
|
||||
*pix = pal[*p];
|
||||
pix++;
|
||||
scale_x ++;
|
||||
}
|
||||
p++;
|
||||
x++;
|
||||
count--;
|
||||
}
|
||||
if (done & 0x1) p++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -895,19 +1089,33 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
if (comp == 0) // no compression
|
||||
{
|
||||
fseek(f, offset, SEEK_SET);
|
||||
buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
|
||||
if (scale_ratio == 1)
|
||||
buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
|
||||
else
|
||||
buffer = malloc(row_size); // scale down is usually set because of memory issue, so read line by line
|
||||
if (!buffer)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
goto close_file;
|
||||
}
|
||||
buffer_end = buffer + image_size;
|
||||
if (scale_ratio == 1)
|
||||
buffer_end = buffer + image_size;
|
||||
else
|
||||
buffer_end = buffer + row_size;
|
||||
|
||||
p = buffer;
|
||||
if (fread(buffer, image_size, 1, f) != 1) goto close_file;
|
||||
if (scale_ratio == 1)
|
||||
{
|
||||
if (fread(buffer, image_size, 1, f) != 1) goto close_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
}
|
||||
if (bit_count == 16)
|
||||
{
|
||||
unsigned short tmp;
|
||||
|
||||
|
||||
pix = surface;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
|
@ -920,13 +1128,28 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
g = (tmp >> 2) & 0xf8; g |= g >> 5;
|
||||
b = (tmp << 3) & 0xf8; b |= b >> 5;
|
||||
*pix = ARGB_JOIN(0xff, r, g, b);
|
||||
p += 2;
|
||||
|
||||
p += 2 * scale_ratio;
|
||||
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bit_count == 24)
|
||||
|
@ -941,13 +1164,26 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
g = p[1];
|
||||
r = p[2];
|
||||
*pix = ARGB_JOIN(0xff, r, g, b);
|
||||
p += 3;
|
||||
p += 3 * scale_ratio;
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bit_count == 32)
|
||||
|
@ -966,13 +1202,27 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
if (a) none_zero_alpha = 1;
|
||||
if (!hasa) a = 0xff;
|
||||
*pix = ARGB_JOIN(a, r, g, b);
|
||||
p += 4;
|
||||
p += 4 * scale_ratio;
|
||||
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
if (!none_zero_alpha)
|
||||
{
|
||||
|
@ -996,21 +1246,37 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
if (!read_uint(f, &bmask)) goto close_file;
|
||||
|
||||
fseek(f, offset, SEEK_SET);
|
||||
buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
|
||||
if (scale_ratio == 1)
|
||||
buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
|
||||
else
|
||||
buffer = malloc(row_size); // scale down is usually set because of memory issue, so read line by line
|
||||
|
||||
if (!buffer)
|
||||
{
|
||||
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
goto close_file;
|
||||
}
|
||||
buffer_end = buffer + image_size;
|
||||
if (scale_ratio == 1)
|
||||
buffer_end = buffer + image_size;
|
||||
else
|
||||
buffer_end = buffer + row_size;
|
||||
|
||||
p = buffer;
|
||||
if (fread(buffer, image_size, 1, f) != 1) goto close_file;
|
||||
if (scale_ratio == 1)
|
||||
{
|
||||
if (fread(buffer, image_size, 1, f) != 1) goto close_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
}
|
||||
|
||||
if ((bit_count == 16) &&
|
||||
(rmask == 0xf800) && (gmask == 0x07e0) && (bmask == 0x001f)
|
||||
)
|
||||
{
|
||||
unsigned short tmp;
|
||||
|
||||
|
||||
pix = surface;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
|
@ -1023,13 +1289,27 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
g = (tmp >> 3) & 0xfc; g |= g >> 6;
|
||||
b = (tmp << 3) & 0xf8; b |= b >> 5;
|
||||
*pix = ARGB_JOIN(0xff, r, g, b);
|
||||
p += 2;
|
||||
|
||||
p += 2 * scale_ratio;
|
||||
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((bit_count == 16) &&
|
||||
|
@ -1037,7 +1317,6 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
)
|
||||
{
|
||||
unsigned short tmp;
|
||||
|
||||
pix = surface;
|
||||
for (y = 0; y < h; y++)
|
||||
{
|
||||
|
@ -1050,13 +1329,26 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
g = (tmp >> 2) & 0xf8; g |= g >> 5;
|
||||
b = (tmp << 3) & 0xf8; b |= b >> 5;
|
||||
*pix = ARGB_JOIN(0xff, r, g, b);
|
||||
p += 2;
|
||||
p += 2 * scale_ratio;
|
||||
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bit_count == 32)
|
||||
|
@ -1073,13 +1365,27 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
a = p[3];
|
||||
if (!hasa) a = 0xff;
|
||||
*pix = ARGB_JOIN(a, r, g, b);
|
||||
p += 4;
|
||||
|
||||
p += 4 * scale_ratio;
|
||||
|
||||
if (p >= buffer_end) break;
|
||||
pix++;
|
||||
}
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
if (scale_ratio > 1)
|
||||
{
|
||||
read_line += scale_ratio;
|
||||
if (read_line >= image_h) break;
|
||||
fseek(f, row_size * (scale_ratio - 1), SEEK_CUR);
|
||||
if (fread(buffer, row_size, 1, f) != 1) goto close_file;
|
||||
p = buffer;
|
||||
buffer_end = buffer + row_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
fix = (int)(((unsigned long)p) & 0x3);
|
||||
if (fix > 0) p += 4 - fix; // align row read
|
||||
if (p >= buffer_end) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1100,6 +1406,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
goto close_file;
|
||||
|
||||
if (buffer) free(buffer);
|
||||
if (scale_surface) free(scale_surface);
|
||||
fclose(f);
|
||||
|
||||
evas_common_image_premul(ie);
|
||||
|
@ -1108,6 +1415,7 @@ evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key
|
|||
|
||||
close_file:
|
||||
if (buffer) free(buffer);
|
||||
if (scale_surface) free(scale_surface);
|
||||
fclose(f);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue