2010-05-30 06:04:34 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
|
|
|
|
2011-10-18 23:36:28 -07:00
|
|
|
#include <math.h>
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
#include "evas_common.h"
|
|
|
|
#include "evas_private.h"
|
|
|
|
|
|
|
|
static Eina_Bool evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
|
|
|
|
static Eina_Bool evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
|
|
|
|
|
|
|
|
static Evas_Image_Load_Func evas_image_load_bmp_func =
|
|
|
|
{
|
|
|
|
EINA_TRUE,
|
|
|
|
evas_image_load_file_head_bmp,
|
2011-08-10 23:04:08 -07:00
|
|
|
evas_image_load_file_data_bmp,
|
2011-12-13 08:58:20 -08:00
|
|
|
NULL,
|
|
|
|
EINA_FALSE
|
2010-05-30 06:04:34 -07:00
|
|
|
};
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
static Eina_Bool
|
|
|
|
read_short(unsigned char *map, size_t length, size_t *position, short *ret)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
|
|
|
unsigned char b[2];
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (*position + 2 > length) return EINA_FALSE;
|
|
|
|
b[0] = map[(*position)++];
|
|
|
|
b[1] = map[(*position)++];
|
2010-05-30 06:04:34 -07:00
|
|
|
*ret = (b[1] << 8) | b[0];
|
2011-12-12 05:39:35 -08:00
|
|
|
return EINA_TRUE;
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
2010-08-18 08:11:07 -07:00
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
static Eina_Bool
|
|
|
|
read_ushort(unsigned char *map, size_t length, size_t *position, unsigned short *ret)
|
2010-08-18 08:11:07 -07:00
|
|
|
{
|
|
|
|
unsigned char b[2];
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (*position + 2 > length) return EINA_FALSE;
|
|
|
|
b[0] = map[(*position)++];
|
|
|
|
b[1] = map[(*position)++];
|
2010-08-18 08:11:07 -07:00
|
|
|
*ret = (b[1] << 8) | b[0];
|
2011-12-12 05:39:35 -08:00
|
|
|
return EINA_TRUE;
|
2010-08-18 08:11:07 -07:00
|
|
|
}
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
static Eina_Bool
|
|
|
|
read_int(unsigned char *map, size_t length, size_t *position, int *ret)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
2010-08-18 08:20:48 -07:00
|
|
|
unsigned char b[4];
|
2011-12-12 05:39:35 -08:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (*position + 4 > length) return EINA_FALSE;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
b[i] = map[(*position)++];
|
2010-06-07 22:39:46 -07:00
|
|
|
*ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
|
2011-12-12 05:39:35 -08:00
|
|
|
return EINA_TRUE;
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
static Eina_Bool
|
|
|
|
read_uint(unsigned char *map, size_t length, size_t *position, unsigned int *ret)
|
2010-08-18 08:11:07 -07:00
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
unsigned char b[4];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (*position + 4 > length) return EINA_FALSE;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
b[i] = map[(*position)++];
|
2010-08-18 08:11:07 -07:00
|
|
|
*ret = ARGB_JOIN(b[3], b[2], b[1], b[0]);
|
2011-12-12 05:39:35 -08:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
read_uchar(unsigned char *map, size_t length, size_t *position, unsigned char *ret)
|
|
|
|
{
|
|
|
|
if (*position + 1 > length) return EINA_FALSE;
|
|
|
|
*ret = map[(*position)++];
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
read_skip(size_t length, size_t *position, int skip)
|
|
|
|
{
|
|
|
|
if (*position + skip > length) return EINA_FALSE;
|
|
|
|
*position += skip;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
read_mem(unsigned char *map, size_t length, size_t *position, void *buffer, int size)
|
|
|
|
{
|
|
|
|
if (*position + size > length) return EINA_FALSE;
|
|
|
|
memcpy(buffer, map + *position, size);
|
|
|
|
*position += size;
|
|
|
|
return EINA_TRUE;
|
2010-08-18 08:11:07 -07:00
|
|
|
}
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
static Eina_Bool
|
2012-11-04 03:51:42 -08:00
|
|
|
evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key EINA_UNUSED, int *error)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
Eina_File *f;
|
|
|
|
void *map = NULL;
|
|
|
|
size_t position = 0;
|
2010-05-30 06:04:34 -07:00
|
|
|
char hasa = 0;
|
2012-01-19 08:35:47 -08:00
|
|
|
int w = 0, h = 0, bit_count = 0, image_size = 0, comp = 0;
|
|
|
|
unsigned int offset, head_size, amask = 0;
|
2012-12-21 01:01:29 -08:00
|
|
|
size_t fsize;
|
2010-05-30 06:04:34 -07:00
|
|
|
unsigned int bmpsize;
|
|
|
|
unsigned short res1, res2;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
f = eina_file_open(file, 0);
|
2010-05-30 06:04:34 -07:00
|
|
|
if (!f)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
2011-12-12 05:39:35 -08:00
|
|
|
fsize = eina_file_size_get(f);
|
2010-05-30 06:04:34 -07:00
|
|
|
if (fsize < 2) goto close_file;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
|
|
|
|
if (!map) goto close_file;
|
|
|
|
|
|
|
|
if (strncmp(map, "BM", 2)) goto close_file; // magic number
|
|
|
|
position += 2;
|
2010-05-30 06:04:34 -07:00
|
|
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_uint(map, fsize, &position, &bmpsize)) goto close_file;
|
|
|
|
if (!read_ushort(map, fsize, &position, &res1)) goto close_file;
|
|
|
|
if (!read_ushort(map, fsize, &position, &res2)) goto close_file;
|
|
|
|
if (!read_uint(map, fsize, &position, &offset)) goto close_file;
|
|
|
|
if (!read_uint(map, fsize, &position, &head_size)) goto close_file;
|
2012-12-05 01:58:56 -08:00
|
|
|
if (offset > fsize) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
if (head_size == 12) // OS/2 V1 + Windows 3.0
|
|
|
|
{
|
|
|
|
short tmp;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8 & 24
|
|
|
|
}
|
|
|
|
else if (head_size == 64) // OS/2 V2
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
image_size = tmp2; // bitmap data size
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_skip(fsize, &position, 24)) goto close_file; // skip unused header
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
|
|
|
}
|
|
|
|
else if (head_size == 40) // Windows 3.0 + (v3)
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
image_size = tmp2; // bitmap data size
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
2011-03-10 04:11:42 -08:00
|
|
|
if ((comp == 0) && (bit_count == 32)) hasa = 1; // GIMP seems to store it this way
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
else if (head_size == 108) // Windows 95/NT4 + (v4)
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
image_size = tmp2; // bitmap data size
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//rmask = tmp2; // red mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//gmask = tmp2; // green mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//bmask = tmp2; // blue mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
amask = tmp2; // alpha mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_skip(fsize, &position, 36)) goto close_file; // skip unused cie
|
|
|
|
if (!read_skip(fsize, &position, 12)) goto close_file; // skip unused gamma
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
|
|
|
if ((amask) && (bit_count == 32)) hasa = 1;
|
|
|
|
}
|
|
|
|
else if (head_size == 124) // Windows 98/2000 + (v5)
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//image_size = tmp2; // bitmap data size
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//rmask = tmp2; // red mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//gmask = tmp2; // green mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//bmask = tmp2; // blue mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
amask = tmp2; // alpha mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_skip(fsize, &position, 36)) goto close_file; // skip unused cie
|
|
|
|
if (!read_skip(fsize, &position, 12)) goto close_file; // skip unused gamma
|
|
|
|
if (!read_skip(fsize, &position, 16)) goto close_file; // skip others
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
|
|
|
if ((amask) && (bit_count == 32)) hasa = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
|
|
|
|
if (h < 0)
|
|
|
|
{
|
|
|
|
h = -h;
|
2012-01-19 08:35:47 -08:00
|
|
|
//right_way_up = 1;
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
2011-12-12 05:39:35 -08:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
|
|
|
IMG_TOO_BIG(w, h))
|
|
|
|
{
|
|
|
|
if (IMG_TOO_BIG(w, h))
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
else
|
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (bit_count < 16)
|
|
|
|
{
|
2012-01-19 08:35:47 -08:00
|
|
|
//if ((palette_size < 0) || (palette_size > 256)) pal_num = 256;
|
|
|
|
//else pal_num = palette_size;
|
2010-05-30 06:04:34 -07:00
|
|
|
if (bit_count == 1)
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (bit_count == 4)
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (comp == 2) // rle 4bit/pixel
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (bit_count == 8)
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if (comp == 1) // rle 8bit/pixel
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
|
|
|
// handled
|
|
|
|
}
|
|
|
|
else if (comp == 3) // bit field
|
|
|
|
{
|
|
|
|
// handled
|
|
|
|
}
|
|
|
|
else if (comp == 4) // jpeg - only printer drivers
|
|
|
|
goto close_file;
|
|
|
|
else if (comp == 3) // png - only printer drivers
|
|
|
|
goto close_file;
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
|
|
|
|
ie->w = w;
|
|
|
|
ie->h = h;
|
|
|
|
if (hasa) ie->flags.alpha = 1;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
eina_file_map_free(f, map);
|
|
|
|
eina_file_close(f);
|
2010-05-30 06:04:34 -07:00
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
close_file:
|
2011-12-12 05:39:35 -08:00
|
|
|
if (map) eina_file_map_free(f, map);
|
|
|
|
eina_file_close(f);
|
2010-05-30 06:04:34 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-11-04 03:51:42 -08:00
|
|
|
evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key EINA_UNUSED, int *error)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
Eina_File *f;
|
|
|
|
void *map = NULL;
|
|
|
|
size_t position = 0;
|
2010-08-18 08:11:07 -07:00
|
|
|
unsigned char *buffer = NULL, *buffer_end = NULL, *p;
|
2010-05-30 06:04:34 -07:00
|
|
|
char hasa = 0;
|
2012-01-19 08:35:47 -08:00
|
|
|
int x = 0, y = 0, w = 0, h = 0, bit_count = 0, image_size = 0,
|
|
|
|
comp = 0, palette_size = -1;
|
2010-08-18 08:11:07 -07:00
|
|
|
unsigned int offset = 0, head_size = 0;
|
2010-05-30 06:04:34 -07:00
|
|
|
unsigned int *pal = NULL, pal_num = 0, *pix = NULL, *surface = NULL, fix,
|
|
|
|
rmask = 0, gmask = 0, bmask = 0, amask = 0;
|
|
|
|
int right_way_up = 0;
|
|
|
|
unsigned char r, g, b, a;
|
2012-12-21 01:01:29 -08:00
|
|
|
size_t fsize;
|
2010-05-30 06:04:34 -07:00
|
|
|
unsigned int bmpsize;
|
|
|
|
unsigned short res1, res2;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
f = eina_file_open(file, 0);
|
2010-05-30 06:04:34 -07:00
|
|
|
if (!f)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
2011-12-12 05:39:35 -08:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
2011-12-12 05:39:35 -08:00
|
|
|
fsize = eina_file_size_get(f);
|
2010-05-30 06:04:34 -07:00
|
|
|
if (fsize < 2) goto close_file;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
2012-01-05 02:06:49 -08:00
|
|
|
map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
|
|
|
|
if (!map) goto close_file;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
if (strncmp(map, "BM", 2)) goto close_file; // magic number
|
|
|
|
position += 2;
|
2010-05-30 06:04:34 -07:00
|
|
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_uint(map, fsize, &position, &bmpsize)) goto close_file;
|
|
|
|
if (!read_ushort(map, fsize, &position, &res1)) goto close_file;
|
|
|
|
if (!read_ushort(map, fsize, &position, &res2)) goto close_file;
|
|
|
|
if (!read_uint(map, fsize, &position, &offset)) goto close_file;
|
|
|
|
if (!read_uint(map, fsize, &position, &head_size)) goto close_file;
|
2012-12-05 01:58:56 -08:00
|
|
|
if (offset > fsize) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
image_size = fsize - offset;
|
|
|
|
if (image_size < 1) goto close_file;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (head_size == 12) // OS/2 V1 + Windows 3.0
|
|
|
|
{
|
|
|
|
short tmp;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8 & 24
|
|
|
|
}
|
|
|
|
else if (head_size == 64) // OS/2 V2
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-09-12 09:34:45 -07:00
|
|
|
if (tmp2 <= image_size) image_size = tmp2; // bitmap data size, GIMP can handle image size error
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_skip(fsize, &position, 24)) goto close_file; // skip unused header
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
|
|
|
}
|
|
|
|
else if (head_size == 40) // Windows 3.0 + (v3)
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-09-12 09:34:45 -07:00
|
|
|
if (tmp2 <= image_size) image_size = tmp2; // bitmap data size, GIMP can handle image size error
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
2011-03-10 04:11:42 -08:00
|
|
|
if ((comp == 0) && (bit_count == 32)) hasa = 1; // GIMP seems to store it this way
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
else if (head_size == 108) // Windows 95/NT4 + (v4)
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-09-12 09:34:45 -07:00
|
|
|
if (tmp2 <= image_size) image_size = tmp2; // bitmap data size, GIMP can handle image size error
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
rmask = tmp2; // red mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
gmask = tmp2; // green mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bmask = tmp2; // blue mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
amask = tmp2; // alpha mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_skip(fsize, &position, 36)) goto close_file; // skip unused cie
|
|
|
|
if (!read_skip(fsize, &position, 12)) goto close_file; // skip unused gamma
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
|
|
|
if ((amask) && (bit_count == 32)) hasa = 1;
|
|
|
|
}
|
|
|
|
else if (head_size == 124) // Windows 98/2000 + (v5)
|
|
|
|
{
|
|
|
|
short tmp;
|
|
|
|
int tmp2;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
w = tmp2; // width
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
h = tmp2; // height
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//planes = tmp; // must be 1
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_short(map, fsize, &position, &tmp)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
comp = tmp2; // compression method
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-09-12 09:34:45 -07:00
|
|
|
if (tmp2 <= image_size) image_size = tmp2; // bitmap data size, GIMP can handle image size error
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2012-01-19 08:35:47 -08:00
|
|
|
//important_colors = tmp2; // number of important colors - 0 if all
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
rmask = tmp2; // red mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
gmask = tmp2; // green mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
bmask = tmp2; // blue mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_int(map, fsize, &position, &tmp2)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
amask = tmp2; // alpha mask
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_skip(fsize, &position, 36)) goto close_file; // skip unused cie
|
|
|
|
if (!read_skip(fsize, &position, 12)) goto close_file; // skip unused gamma
|
|
|
|
if (!read_skip(fsize, &position, 16)) goto close_file; // skip others
|
2010-05-30 06:04:34 -07:00
|
|
|
if (image_size == 0) image_size = fsize - offset;
|
|
|
|
if ((amask) && (bit_count == 32)) hasa = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
|
|
|
|
if (h < 0)
|
|
|
|
{
|
|
|
|
h = -h;
|
|
|
|
right_way_up = 1;
|
|
|
|
}
|
|
|
|
if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
|
|
|
|
IMG_TOO_BIG(w, h))
|
|
|
|
{
|
|
|
|
if (IMG_TOO_BIG(w, h))
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
else
|
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-09-18 19:43:08 -07:00
|
|
|
if ((w != (int)ie->w) || (h != (int)ie->h))
|
2010-05-30 08:34:22 -07:00
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
2010-05-30 06:04:34 -07:00
|
|
|
surface = evas_cache_image_pixels(ie);
|
|
|
|
if (!surface)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
row_size = ceil((double)(image_w * bit_count) / 32) * 4;
|
2013-01-10 00:53:11 -08:00
|
|
|
if (image_size != row_size * h)
|
|
|
|
image_size = row_size * h;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (bit_count < 16)
|
|
|
|
{
|
2010-08-18 08:11:07 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (bit_count == 1)
|
|
|
|
{
|
|
|
|
if ((palette_size <= 0) || (palette_size > 2)) pal_num = 2;
|
|
|
|
else pal_num = palette_size;
|
|
|
|
}
|
|
|
|
else if (bit_count == 4)
|
|
|
|
{
|
|
|
|
if ((palette_size <= 0) || (palette_size > 16)) pal_num = 16;
|
|
|
|
else pal_num = palette_size;
|
|
|
|
}
|
|
|
|
else if (bit_count == 8)
|
|
|
|
{
|
|
|
|
if ((palette_size <= 0) || (palette_size > 256)) pal_num = 256;
|
|
|
|
else pal_num = palette_size;
|
|
|
|
}
|
|
|
|
pal = alloca(256 * 4);
|
|
|
|
for (i = 0; i < pal_num; i++)
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_uchar(map, fsize, &position, &b)) goto close_file;
|
|
|
|
if (!read_uchar(map, fsize, &position, &g)) goto close_file;
|
|
|
|
if (!read_uchar(map, fsize, &position, &r)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
if ((head_size != 12) /*&& (palette_size != 0)*/)
|
2010-09-07 20:51:24 -07:00
|
|
|
{ // OS/2 V1 doesn't do the pad byte
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_uchar(map, fsize, &position, &a)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
a = 0xff; // fillin a as solid for paletted images
|
2010-06-07 22:39:46 -07:00
|
|
|
pal[i] = ARGB_JOIN(a, r, g, b);
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
2011-12-12 05:39:35 -08:00
|
|
|
position = offset;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if ((scale_ratio == 1) || (comp !=0))
|
|
|
|
buffer_end = buffer + image_size;
|
|
|
|
else
|
|
|
|
buffer_end = buffer + row_size;
|
2010-05-30 06:04:34 -07:00
|
|
|
p = buffer;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
if ((scale_ratio == 1) || (comp !=0))
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_mem(map, fsize, &position, buffer, image_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (bit_count == 1)
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
|
|
|
pix = surface;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1) pix = scale_surface; // one line decoding
|
|
|
|
|
|
|
|
for (x = 0; x < image_w; x++)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
|
|
|
if ((x & 0x7) == 0x0)
|
|
|
|
{
|
|
|
|
*pix = pal[*p >> 7];
|
|
|
|
}
|
|
|
|
else if ((x & 0x7) == 0x1)
|
|
|
|
{
|
|
|
|
*pix = pal[(*p >> 6) & 0x1];
|
|
|
|
}
|
|
|
|
else if ((x & 0x7) == 0x2)
|
|
|
|
{
|
|
|
|
*pix = pal[(*p >> 5) & 0x1];
|
|
|
|
}
|
|
|
|
else if ((x & 0x7) == 0x3)
|
|
|
|
{
|
|
|
|
*pix = pal[(*p >> 4) & 0x1];
|
|
|
|
}
|
|
|
|
else if ((x & 0x7) == 0x4)
|
|
|
|
{
|
|
|
|
*pix = pal[(*p >> 3) & 0x1];
|
|
|
|
}
|
|
|
|
else if ((x & 0x7) == 0x5)
|
|
|
|
{
|
|
|
|
*pix = pal[(*p >> 2) & 0x1];
|
|
|
|
}
|
|
|
|
else if ((x & 0x7) == 0x6)
|
|
|
|
{
|
|
|
|
*pix = pal[(*p >> 1) & 0x1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pix = pal[*p & 0x1];
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((x & 0x7) != 0) p++;
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (bit_count == 4)
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1) pix = scale_surface; // one line decoding
|
|
|
|
for (x = 0; x < image_w; x++)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
|
|
|
if ((x & 0x1) == 0x1)
|
|
|
|
{
|
|
|
|
*pix = pal[*p & 0x0f];
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pix = pal[*p >> 4];
|
|
|
|
}
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
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;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((x & 0x1) != 0) p++;
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (comp == 2) // rle 4bit/pixel
|
|
|
|
{
|
|
|
|
int count = 0, done = 0, wpad;
|
2011-10-18 23:36:28 -07:00
|
|
|
int scale_x = 0, scale_y = 0;
|
|
|
|
Eina_Bool scale_down_line = EINA_TRUE;
|
2010-05-30 06:04:34 -07:00
|
|
|
|
|
|
|
pix = surface;
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
2011-10-18 23:36:28 -07:00
|
|
|
wpad = ((image_w + 1) / 2) * 2;
|
2010-05-30 06:04:34 -07:00
|
|
|
while (p < buffer_end)
|
|
|
|
{
|
|
|
|
if (p[0])
|
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_down_line)
|
|
|
|
{
|
|
|
|
if ((x + p[0]) <= wpad)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
unsigned int col1 = pal[p[1] >> 4];
|
|
|
|
unsigned int col2 = pal[p[1] & 0xf];
|
|
|
|
|
|
|
|
count = p[0] / 2;
|
|
|
|
while (count > 0)
|
2011-02-15 21:44:01 -08:00
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
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--;
|
2011-02-15 21:44:01 -08:00
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (p[0] & 0x1)
|
2011-02-15 21:44:01 -08:00
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
if (((x % scale_ratio) == 0) && (scale_x < w))
|
|
|
|
{
|
|
|
|
*pix = col1;
|
|
|
|
pix++;
|
|
|
|
scale_x++;
|
|
|
|
}
|
2011-02-15 21:44:01 -08:00
|
|
|
x++;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
p += 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (p[1])
|
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
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;
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (bit_count == 8)
|
|
|
|
{
|
|
|
|
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++)
|
|
|
|
{
|
|
|
|
*pix = pal[*p];
|
2011-10-18 23:36:28 -07:00
|
|
|
p += scale_ratio;
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (comp == 1) // rle 8bit/pixel
|
|
|
|
{
|
|
|
|
int count = 0, done = 0;
|
2011-10-18 23:36:28 -07:00
|
|
|
int scale_x = 0, scale_y = 0;
|
|
|
|
Eina_Bool scale_down_line = EINA_TRUE;
|
2010-05-30 06:04:34 -07:00
|
|
|
|
|
|
|
pix = surface;
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
2011-10-18 23:36:28 -07:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
while (p < buffer_end)
|
|
|
|
{
|
|
|
|
if (p[0])
|
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_down_line)
|
|
|
|
{
|
|
|
|
if ((x + p[0]) <= image_w)
|
2011-02-15 21:44:01 -08:00
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
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--;
|
|
|
|
}
|
2011-02-15 21:44:01 -08:00
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
p += 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (p[1])
|
|
|
|
{
|
2011-10-18 23:36:28 -07:00
|
|
|
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;
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
|
|
|
|
{
|
|
|
|
if (comp == 0) // no compression
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
position = offset;
|
2011-10-18 23:36:28 -07:00
|
|
|
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
|
2010-05-30 06:04:34 -07:00
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio == 1)
|
|
|
|
buffer_end = buffer + image_size;
|
|
|
|
else
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
p = buffer;
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio == 1)
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_mem(map, fsize, &position, buffer, image_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
if (bit_count == 16)
|
|
|
|
{
|
|
|
|
unsigned short tmp;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
tmp = *((unsigned short *)(p));
|
|
|
|
|
|
|
|
r = (tmp >> 7) & 0xf8; r |= r >> 5;
|
|
|
|
g = (tmp >> 2) & 0xf8; g |= g >> 5;
|
|
|
|
b = (tmp << 3) & 0xf8; b |= b >> 5;
|
2010-06-07 22:39:46 -07:00
|
|
|
*pix = ARGB_JOIN(0xff, r, g, b);
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
p += 2 * scale_ratio;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bit_count == 24)
|
|
|
|
{
|
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
b = p[0];
|
|
|
|
g = p[1];
|
|
|
|
r = p[2];
|
2010-06-07 22:39:46 -07:00
|
|
|
*pix = ARGB_JOIN(0xff, r, g, b);
|
2011-10-18 23:36:28 -07:00
|
|
|
p += 3 * scale_ratio;
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bit_count == 32)
|
|
|
|
{
|
2011-03-10 04:11:42 -08:00
|
|
|
int none_zero_alpha = 0;
|
2010-05-30 06:04:34 -07:00
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
b = p[0];
|
|
|
|
g = p[1];
|
|
|
|
r = p[2];
|
|
|
|
a = p[3];
|
2011-03-10 04:11:42 -08:00
|
|
|
if (a) none_zero_alpha = 1;
|
2010-05-30 06:04:34 -07:00
|
|
|
if (!hasa) a = 0xff;
|
2010-06-07 22:39:46 -07:00
|
|
|
*pix = ARGB_JOIN(a, r, g, b);
|
2011-10-18 23:36:28 -07:00
|
|
|
p += 4 * scale_ratio;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
2011-03-10 04:11:42 -08:00
|
|
|
if (!none_zero_alpha)
|
|
|
|
{
|
|
|
|
ie->flags.alpha = 0;
|
|
|
|
if (hasa)
|
|
|
|
{
|
2011-08-01 00:34:05 -07:00
|
|
|
unsigned int *pixend = surface + (w * h);
|
2011-12-12 05:39:35 -08:00
|
|
|
|
2011-03-10 04:11:42 -08:00
|
|
|
for (pix = surface; pix < pixend; pix++)
|
|
|
|
A_VAL(pix) = 0xff;
|
|
|
|
}
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (comp == 3) // bit field
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_uint(map, fsize, &position, &rmask)) goto close_file;
|
|
|
|
if (!read_uint(map, fsize, &position, &gmask)) goto close_file;
|
|
|
|
if (!read_uint(map, fsize, &position, &bmask)) goto close_file;
|
2010-05-30 06:04:34 -07:00
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
position = offset;
|
2011-10-18 23:36:28 -07:00
|
|
|
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
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (!buffer)
|
|
|
|
{
|
|
|
|
*error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
|
|
|
goto close_file;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio == 1)
|
|
|
|
buffer_end = buffer + image_size;
|
|
|
|
else
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
p = buffer;
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio == 1)
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_mem(map, fsize, &position, buffer, image_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-12-12 05:39:35 -08:00
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
}
|
|
|
|
|
2011-12-12 05:39:35 -08:00
|
|
|
if ((bit_count == 16) &&
|
2010-05-30 06:04:34 -07:00
|
|
|
(rmask == 0xf800) && (gmask == 0x07e0) && (bmask == 0x001f)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
unsigned short tmp;
|
2011-10-18 23:36:28 -07:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
tmp = *((unsigned short *)(p));
|
|
|
|
|
|
|
|
r = (tmp >> 8) & 0xf8; r |= r >> 5;
|
|
|
|
g = (tmp >> 3) & 0xfc; g |= g >> 6;
|
|
|
|
b = (tmp << 3) & 0xf8; b |= b >> 5;
|
2010-06-07 22:39:46 -07:00
|
|
|
*pix = ARGB_JOIN(0xff, r, g, b);
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
p += 2 * scale_ratio;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((bit_count == 16) &&
|
|
|
|
(rmask == 0x7c00) && (gmask == 0x03e0) && (bmask == 0x001f)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
unsigned short tmp;
|
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
tmp = *((unsigned short *)(p));
|
|
|
|
|
|
|
|
r = (tmp >> 7) & 0xf8; r |= r >> 5;
|
|
|
|
g = (tmp >> 2) & 0xf8; g |= g >> 5;
|
|
|
|
b = (tmp << 3) & 0xf8; b |= b >> 5;
|
2010-06-07 22:39:46 -07:00
|
|
|
*pix = ARGB_JOIN(0xff, r, g, b);
|
2011-10-18 23:36:28 -07:00
|
|
|
p += 2 * scale_ratio;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer_end, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bit_count == 32)
|
|
|
|
{
|
|
|
|
pix = surface;
|
|
|
|
for (y = 0; y < h; y++)
|
|
|
|
{
|
|
|
|
if (!right_way_up) pix = surface + ((h - 1 - y) * w);
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
b = p[0];
|
|
|
|
g = p[1];
|
|
|
|
r = p[2];
|
|
|
|
a = p[3];
|
|
|
|
if (!hasa) a = 0xff;
|
2010-06-07 22:39:46 -07:00
|
|
|
*pix = ARGB_JOIN(a, r, g, b);
|
2011-10-18 23:36:28 -07:00
|
|
|
|
|
|
|
p += 4 * scale_ratio;
|
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (p >= buffer_end) break;
|
|
|
|
pix++;
|
|
|
|
}
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_ratio > 1)
|
|
|
|
{
|
|
|
|
read_line += scale_ratio;
|
|
|
|
if (read_line >= image_h) break;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
position += row_size * (scale_ratio - 1);
|
|
|
|
if (!read_mem(map, fsize, &position, buffer, row_size)) goto close_file;
|
2011-10-18 23:36:28 -07:00
|
|
|
p = buffer;
|
|
|
|
buffer_end = buffer + row_size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-16 01:36:41 -08:00
|
|
|
fix = (int)(((uintptr_t)p) & 0x3);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (fix > 0) p += 4 - fix; // align row read
|
|
|
|
if (p >= buffer_end) break;
|
|
|
|
}
|
2010-05-30 06:04:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (comp == 4) // jpeg - only printer drivers
|
|
|
|
{
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else if (comp == 3) // png - only printer drivers
|
|
|
|
{
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto close_file;
|
2011-12-12 05:39:35 -08:00
|
|
|
|
2010-05-30 06:04:34 -07:00
|
|
|
if (buffer) free(buffer);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_surface) free(scale_surface);
|
2011-12-12 05:39:35 -08:00
|
|
|
|
|
|
|
eina_file_map_free(f, map);
|
|
|
|
eina_file_close(f);
|
2010-05-30 06:04:34 -07:00
|
|
|
|
|
|
|
evas_common_image_premul(ie);
|
|
|
|
*error = EVAS_LOAD_ERROR_NONE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
close_file:
|
|
|
|
if (buffer) free(buffer);
|
2011-10-18 23:36:28 -07:00
|
|
|
if (scale_surface) free(scale_surface);
|
2011-12-12 05:39:35 -08:00
|
|
|
if (map) eina_file_map_free(f, map);
|
|
|
|
eina_file_close(f);
|
2010-05-30 06:04:34 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
module_open(Evas_Module *em)
|
|
|
|
{
|
|
|
|
if (!em) return 0;
|
|
|
|
em->functions = (void *)(&evas_image_load_bmp_func);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-04 03:51:42 -08:00
|
|
|
module_close(Evas_Module *em EINA_UNUSED)
|
2010-05-30 06:04:34 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static Evas_Module_Api evas_modapi =
|
|
|
|
{
|
|
|
|
EVAS_MODULE_API_VERSION,
|
|
|
|
"bmp",
|
|
|
|
"none",
|
|
|
|
{
|
|
|
|
module_open,
|
|
|
|
module_close
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, bmp);
|
|
|
|
|
2010-05-30 07:33:36 -07:00
|
|
|
#ifndef EVAS_STATIC_BUILD_BMP
|
2010-05-30 06:04:34 -07:00
|
|
|
EVAS_EINA_MODULE_DEFINE(image_loader, bmp);
|
|
|
|
#endif
|