forked from enlightenment/efl
evas: add psd file format support.
Patch from Thierry el Borgi with some rework of myself. NOTE: I don't have much file to test, so if some don't contact us with those file and we will fix the loader if needed. SVN revision: 58873
This commit is contained in:
parent
bd1337f4cd
commit
0cef5e41fe
|
@ -23,3 +23,4 @@ Samsung SAIT <tbd>
|
||||||
Sung W. Park <sungwoo@gmail.com>
|
Sung W. Park <sungwoo@gmail.com>
|
||||||
Jiyoun Park <jy0703.park@samsung.com>
|
Jiyoun Park <jy0703.park@samsung.com>
|
||||||
Myoungwoon Roy Kim(roy_kim) <myoungwoon.kim@samsung.com> <myoungwoon@gmail.com>
|
Myoungwoon Roy Kim(roy_kim) <myoungwoon.kim@samsung.com> <myoungwoon@gmail.com>
|
||||||
|
Thierry el Borgi <tbd>
|
||||||
|
|
|
@ -262,3 +262,8 @@
|
||||||
Supports a filter object or filter under (the area where the object
|
Supports a filter object or filter under (the area where the object
|
||||||
is filtered). Various parameters to tweak, and potential for
|
is filtered). Various parameters to tweak, and potential for
|
||||||
additional filters (but you get to write the shader ;-)
|
additional filters (but you get to write the shader ;-)
|
||||||
|
|
||||||
|
2011-04-24 Thierry el Borgi
|
||||||
|
|
||||||
|
* Add PSD file format support.
|
||||||
|
|
||||||
|
|
|
@ -122,6 +122,7 @@ want_evas_image_loader_bmp="yes"
|
||||||
want_evas_image_loader_tga="yes"
|
want_evas_image_loader_tga="yes"
|
||||||
want_evas_image_loader_wbmp="yes"
|
want_evas_image_loader_wbmp="yes"
|
||||||
want_evas_image_loader_ico="yes"
|
want_evas_image_loader_ico="yes"
|
||||||
|
want_evas_image_loader_psd="yes"
|
||||||
|
|
||||||
want_evas_font_loader_eet="yes"
|
want_evas_font_loader_eet="yes"
|
||||||
|
|
||||||
|
@ -835,6 +836,8 @@ EVAS_CHECK_IMAGE_LOADER([WBMP], [${want_evas_image_loader_wbmp}])
|
||||||
|
|
||||||
EVAS_CHECK_IMAGE_LOADER([ICO], [${want_evas_image_loader_ico}])
|
EVAS_CHECK_IMAGE_LOADER([ICO], [${want_evas_image_loader_ico}])
|
||||||
|
|
||||||
|
EVAS_CHECK_IMAGE_LOADER([PSD], [${want_evas_image_loader_psd}])
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
## Cpu based optimizations
|
## Cpu based optimizations
|
||||||
|
|
||||||
|
@ -1607,6 +1610,7 @@ src/modules/loaders/tga/Makefile
|
||||||
src/modules/loaders/svg/Makefile
|
src/modules/loaders/svg/Makefile
|
||||||
src/modules/loaders/pmaps/Makefile
|
src/modules/loaders/pmaps/Makefile
|
||||||
src/modules/loaders/wbmp/Makefile
|
src/modules/loaders/wbmp/Makefile
|
||||||
|
src/modules/loaders/psd/Makefile
|
||||||
src/modules/savers/Makefile
|
src/modules/savers/Makefile
|
||||||
src/modules/savers/edb/Makefile
|
src/modules/savers/edb/Makefile
|
||||||
src/modules/savers/eet/Makefile
|
src/modules/savers/eet/Makefile
|
||||||
|
@ -1698,6 +1702,7 @@ echo " TGA.....................: $have_evas_image_loader_tga"
|
||||||
echo " TIFF....................: $have_evas_image_loader_tiff"
|
echo " TIFF....................: $have_evas_image_loader_tiff"
|
||||||
echo " WBMP....................: $have_evas_image_loader_wbmp"
|
echo " WBMP....................: $have_evas_image_loader_wbmp"
|
||||||
echo " XPM.....................: $have_evas_image_loader_xpm"
|
echo " XPM.....................: $have_evas_image_loader_xpm"
|
||||||
|
echo " PSD.....................: $have_evas_image_loader_psd"
|
||||||
echo
|
echo
|
||||||
echo "Font Sourcing Systems:"
|
echo "Font Sourcing Systems:"
|
||||||
echo " EET.....................: $have_evas_font_loader_eet"
|
echo " EET.....................: $have_evas_font_loader_eet"
|
||||||
|
|
|
@ -390,6 +390,26 @@ fi
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl use: EVAS_CHECK_LOADER_DEP_PSD(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||||
|
|
||||||
|
AC_DEFUN([EVAS_CHECK_LOADER_DEP_PSD],
|
||||||
|
[
|
||||||
|
|
||||||
|
have_dep="yes"
|
||||||
|
evas_image_loader_[]$1[]_cflags=""
|
||||||
|
evas_image_loader_[]$1[]_libs=""
|
||||||
|
|
||||||
|
AC_SUBST([evas_image_loader_$1_cflags])
|
||||||
|
AC_SUBST([evas_image_loader_$1_libs])
|
||||||
|
|
||||||
|
if test "x${have_dep}" = "xyes" ; then
|
||||||
|
m4_default([$3], [:])
|
||||||
|
else
|
||||||
|
m4_default([$4], [:])
|
||||||
|
fi
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
dnl use: EVAS_CHECK_IMAGE_LOADER(loader, want_loader, macro)
|
dnl use: EVAS_CHECK_IMAGE_LOADER(loader, want_loader, macro)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,11 @@ SUBDIRS += ../modules/loaders/xpm
|
||||||
EVAS_STATIC_MODULE += ../modules/loaders/xpm/libevas_loader_xpm.la
|
EVAS_STATIC_MODULE += ../modules/loaders/xpm/libevas_loader_xpm.la
|
||||||
EVAS_STATIC_LIBADD += @evas_image_loader_xpm_libs@
|
EVAS_STATIC_LIBADD += @evas_image_loader_xpm_libs@
|
||||||
endif
|
endif
|
||||||
|
if EVAS_STATIC_BUILD_PSD
|
||||||
|
SUBDIRS += ../modules/loaders/psd
|
||||||
|
EVAS_STATIC_MODULE += ../modules/loaders/psd/libevas_loader_psd.la
|
||||||
|
EVAS_STATIC_LIBADD += @evas_image_loader_psd_libs@
|
||||||
|
endif
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
-I. \
|
-I. \
|
||||||
|
|
|
@ -32,12 +32,13 @@ static const struct ext_loader_s loaders[] =
|
||||||
{ "tga", "tga" },
|
{ "tga", "tga" },
|
||||||
{ "wbmp", "wbmp" },
|
{ "wbmp", "wbmp" },
|
||||||
{ "ico", "ico" },
|
{ "ico", "ico" },
|
||||||
{ "cur", "ico" }
|
{ "cur", "ico" },
|
||||||
|
{ "psd", "psd" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *loaders_name[] =
|
static const char *loaders_name[] =
|
||||||
{
|
{
|
||||||
"png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "edb", "bmp", "tga", "wbmp", "ico"
|
"png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "edb", "bmp", "tga", "wbmp", "ico", "psd"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct evas_image_foreach_loader_data
|
struct evas_image_foreach_loader_data
|
||||||
|
|
|
@ -121,6 +121,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, edb);
|
||||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga);
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga);
|
||||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, wbmp);
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, wbmp);
|
||||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, ico);
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, ico);
|
||||||
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, psd);
|
||||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, edb);
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, edb);
|
||||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet);
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet);
|
||||||
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg);
|
EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg);
|
||||||
|
@ -238,6 +239,9 @@ static const struct {
|
||||||
#endif
|
#endif
|
||||||
#ifdef EVAS_STATIC_BUILD_TIFF
|
#ifdef EVAS_STATIC_BUILD_TIFF
|
||||||
EVAS_EINA_STATIC_MODULE_USE(image_saver, tiff),
|
EVAS_EINA_STATIC_MODULE_USE(image_saver, tiff),
|
||||||
|
#endif
|
||||||
|
#ifdef EVAS_STATIC_BUILD_PSD
|
||||||
|
EVAS_EINA_STATIC_MODULE_USE(image_saver, psd),
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,3 +80,9 @@ SUBDIRS += xpm
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_LOADER_PSD
|
||||||
|
if !EVAS_STATIC_BUILD_PSD
|
||||||
|
SUBDIRS += psd
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,947 @@
|
||||||
|
#define _XOPEN_SOURCE
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_EVIL
|
||||||
|
# include <Evil.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "evas_common.h"
|
||||||
|
#include "evas_private.h"
|
||||||
|
|
||||||
|
typedef struct _PSD_Header PSD_Header;
|
||||||
|
|
||||||
|
typedef enum _PSD_Mode
|
||||||
|
{
|
||||||
|
PSD_GREYSCALE = 1,
|
||||||
|
PSD_INDEXED = 2,
|
||||||
|
PSD_RGB = 3,
|
||||||
|
PSD_CMYK = 4
|
||||||
|
} PSD_Mode;
|
||||||
|
|
||||||
|
struct _PSD_Header
|
||||||
|
{
|
||||||
|
unsigned char signature[4];
|
||||||
|
unsigned short version;
|
||||||
|
unsigned char reserved[9];
|
||||||
|
unsigned short channels;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned int width;
|
||||||
|
unsigned short depth;
|
||||||
|
|
||||||
|
unsigned short channel_num;
|
||||||
|
|
||||||
|
PSD_Mode mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
READ_COMPRESSED_SUCCESS,
|
||||||
|
READ_COMPRESSED_ERROR_FILE_CORRUPT,
|
||||||
|
READ_COMPRESSED_ERROR_FILE_READ_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
static Eina_Bool get_compressed_channels_length(PSD_Header *Head,
|
||||||
|
FILE *file,
|
||||||
|
unsigned short *rle_table,
|
||||||
|
unsigned int *chanlen);
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_ushort(FILE *file, unsigned short *ret)
|
||||||
|
{
|
||||||
|
unsigned char b[2];
|
||||||
|
if (fread(b, sizeof(unsigned char), 2, file) != 2) return 0;
|
||||||
|
// FIXME: need to check order
|
||||||
|
*ret = (b[0] << 8) | b[1];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
read_uint(FILE *file, unsigned int *ret)
|
||||||
|
{
|
||||||
|
unsigned char b[4];
|
||||||
|
if (fread(b, sizeof(unsigned char), 4, file) != 4) return 0;
|
||||||
|
// FIXME: need to check order
|
||||||
|
*ret = ARGB_JOIN(b[0], b[1], b[2], b[3]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal function used to get the Psd header from the current file.
|
||||||
|
Eina_Bool
|
||||||
|
psd_get_header(PSD_Header *header, FILE * file)
|
||||||
|
{
|
||||||
|
unsigned short tmp;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return EINA_FALSE;
|
||||||
|
|
||||||
|
CHECK_RET(fread(header->signature, sizeof (unsigned char), 4, file), 4);
|
||||||
|
CHECK_RET(read_ushort(file, &header->version), 1);
|
||||||
|
CHECK_RET(fread(header->reserved, sizeof (unsigned char), 6, file), 6);
|
||||||
|
CHECK_RET(read_ushort(file, &header->channels), 1);
|
||||||
|
CHECK_RET(read_uint(file, &header->height), 1);
|
||||||
|
CHECK_RET(read_uint(file, &header->width), 1);
|
||||||
|
CHECK_RET(read_ushort(file, &header->depth), 1);
|
||||||
|
|
||||||
|
CHECK_RET(read_ushort(file, &tmp), 1);
|
||||||
|
header->mode = tmp;
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
|
||||||
|
/* fprintf(stderr, "<<<<<<<<<<<\nsignature : %c%c%c%c\n", */
|
||||||
|
/* header->signature[0], */
|
||||||
|
/* header->signature[1], */
|
||||||
|
/* header->signature[2], */
|
||||||
|
/* header->signature[3]); */
|
||||||
|
/* fprintf(stderr, "version : %i\n", header->version); */
|
||||||
|
/* fprintf(stderr, "channels : %i\n", header->channels); */
|
||||||
|
/* fprintf(stderr, "width x height : %dx%d\n", header->width, header->height); */
|
||||||
|
/* fprintf(stderr, "depth : %i\n", header->depth); */
|
||||||
|
/* fprintf(stderr, "mode : %i\n>>>>>>>>>>>>\n", header->mode); */
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Internal function used to check if the HEADER is a valid Psd header.
|
||||||
|
Eina_Bool
|
||||||
|
is_psd(PSD_Header *header)
|
||||||
|
{
|
||||||
|
if (strncmp((char*)header->signature, "8BPS", 4))
|
||||||
|
return EINA_FALSE;
|
||||||
|
if (header->version != 1)
|
||||||
|
return EINA_FALSE;
|
||||||
|
if (header->channels < 1 || header->channels > 24)
|
||||||
|
return EINA_FALSE;
|
||||||
|
if (header->height < 1 || header->width < 1)
|
||||||
|
return EINA_FALSE;
|
||||||
|
if (header->depth != 1 && header->depth != 8 && header->depth != 16)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
evas_image_load_file_head_psd(Image_Entry *ie, const char *FileName, const char *key, int *error)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
PSD_Header header;
|
||||||
|
|
||||||
|
*error = EVAS_LOAD_ERROR_NONE;
|
||||||
|
|
||||||
|
f = fopen(FileName, "rb");
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
psd_get_header(&header, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (!is_psd(&header))
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie->w = header.width;
|
||||||
|
ie->h = header.height;
|
||||||
|
if (header.channels == 3) ie->flags.alpha = 0;
|
||||||
|
else ie->flags.alpha = 1;
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int
|
||||||
|
read_compressed_channel(FILE* file,
|
||||||
|
const unsigned int channel_length, unsigned int size,
|
||||||
|
unsigned char* channel)
|
||||||
|
{
|
||||||
|
// FIXME: what does channel_length means, and why is it not used
|
||||||
|
unsigned int i;
|
||||||
|
char headbyte, c;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return READ_COMPRESSED_ERROR_FILE_READ_ERROR;
|
||||||
|
|
||||||
|
for (i = 0; i < size; )
|
||||||
|
{
|
||||||
|
CHECK_RET(fread(&headbyte, 1, 1, file), 1);
|
||||||
|
|
||||||
|
if (headbyte >= 0)
|
||||||
|
{
|
||||||
|
if (i + headbyte > size)
|
||||||
|
return READ_COMPRESSED_ERROR_FILE_CORRUPT;
|
||||||
|
|
||||||
|
CHECK_RET(fread(channel + i, headbyte + 1, 1, file), 1);
|
||||||
|
|
||||||
|
i += headbyte + 1;
|
||||||
|
}
|
||||||
|
else if (headbyte >= -127 && headbyte <= -1)
|
||||||
|
{
|
||||||
|
int run;
|
||||||
|
|
||||||
|
CHECK_RET(fread(&c, 1, 1, file), 1);
|
||||||
|
|
||||||
|
run = c;
|
||||||
|
/* if (run == -1) */
|
||||||
|
/* return READ_COMPRESSED_ERROR_FILE_READ_ERROR; */
|
||||||
|
|
||||||
|
if (i + (-headbyte + 1) > size)
|
||||||
|
return READ_COMPRESSED_ERROR_FILE_CORRUPT;
|
||||||
|
|
||||||
|
memset(channel + i, run, -headbyte + 1);
|
||||||
|
i += -headbyte + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
|
||||||
|
return READ_COMPRESSED_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
psd_get_data(Image_Entry *ie,
|
||||||
|
PSD_Header *head,
|
||||||
|
FILE *f,
|
||||||
|
unsigned char *buffer, Eina_Bool compressed,
|
||||||
|
int *error)
|
||||||
|
{
|
||||||
|
unsigned int c, x, y, numchan, bps, bpc, bpp;
|
||||||
|
unsigned int pixels_count;
|
||||||
|
unsigned char *channel = NULL;
|
||||||
|
unsigned char *data = NULL;
|
||||||
|
|
||||||
|
// Added 01-07-2009: This is needed to correctly load greyscale and
|
||||||
|
// paletted images.
|
||||||
|
switch (head->mode)
|
||||||
|
{
|
||||||
|
case PSD_GREYSCALE:
|
||||||
|
case PSD_INDEXED:
|
||||||
|
numchan = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
numchan = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpp = head->channels;
|
||||||
|
bpc = head->depth / 8;
|
||||||
|
pixels_count = head->width * head->height;
|
||||||
|
|
||||||
|
data = malloc(sizeof (unsigned char) * pixels_count * bpp);
|
||||||
|
if (!data) return EINA_FALSE;
|
||||||
|
|
||||||
|
channel = malloc(sizeof (unsigned char) * pixels_count * bpc);
|
||||||
|
if (!channel)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bps = head->width * head->channels * bpc;
|
||||||
|
// @TODO: Add support for this in, though I have yet to run across a .psd
|
||||||
|
// file that uses this.
|
||||||
|
if (compressed && bpc == 2)
|
||||||
|
{
|
||||||
|
free(data);
|
||||||
|
free(channel);
|
||||||
|
fprintf(stderr, "unsupported file format.\n");
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) \
|
||||||
|
{ \
|
||||||
|
free(data); \
|
||||||
|
free(channel); \
|
||||||
|
return EINA_FALSE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compressed)
|
||||||
|
{
|
||||||
|
if (bpc == 1)
|
||||||
|
{
|
||||||
|
for (c = 0; c < numchan; c++)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = channel;
|
||||||
|
|
||||||
|
CHECK_RET(fread(tmp, pixels_count, 1, f), 1);
|
||||||
|
|
||||||
|
for (y = 0; y < head->height * bps; y += bps)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps; x += bpp, tmp++)
|
||||||
|
{
|
||||||
|
data[y + x + c] = *tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulate any remaining channels into a single alpha channel
|
||||||
|
//@TODO: This needs to be changed for greyscale images.
|
||||||
|
for (; c < head->channels; c++)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = channel;
|
||||||
|
|
||||||
|
CHECK_RET(fread(channel, pixels_count, 1, f), 1);
|
||||||
|
|
||||||
|
for (y = 0; y < head->height * bps; y += bps)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps; x += bpp, tmp++)
|
||||||
|
{
|
||||||
|
unsigned short newval;
|
||||||
|
|
||||||
|
// previous formula was : (old / 255 * new / 255) * 255
|
||||||
|
newval = (*tmp) * data[y + x + 3];
|
||||||
|
|
||||||
|
data[y + x + 3] = newval >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bps2;
|
||||||
|
|
||||||
|
bps2 = bps / 2;
|
||||||
|
|
||||||
|
// iCurImage->Bpc == 2
|
||||||
|
for (c = 0; c < numchan; c++)
|
||||||
|
{
|
||||||
|
unsigned short *shortptr = (unsigned short*) channel;
|
||||||
|
|
||||||
|
CHECK_RET(fread(channel, pixels_count * 2, 1, f), 1);
|
||||||
|
|
||||||
|
for (y = 0; y < head->height * bps2; y += bps2)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps2; x += bpp, shortptr++)
|
||||||
|
{
|
||||||
|
((unsigned short*)data)[y + x + c] = *shortptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulate any remaining channels into a single alpha channel
|
||||||
|
//@TODO: This needs to be changed for greyscale images.
|
||||||
|
for (; c < head->channels; c++)
|
||||||
|
{
|
||||||
|
unsigned short *shortptr = (unsigned short*) channel;
|
||||||
|
|
||||||
|
CHECK_RET(fread(channel, pixels_count * 2, 1, f), 1);
|
||||||
|
|
||||||
|
for (y = 0; y < head->height * bps2; y += bps2)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps2; x += bpp, shortptr)
|
||||||
|
{
|
||||||
|
unsigned int newval;
|
||||||
|
|
||||||
|
newval = *shortptr * ((unsigned short*)data)[y + x + 3];
|
||||||
|
|
||||||
|
((unsigned short*)data)[y + x + 3] = newval >> 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned short *rle_table;
|
||||||
|
unsigned int *chanlen;
|
||||||
|
|
||||||
|
rle_table = alloca(head->height * head->channel_num * sizeof (unsigned short));
|
||||||
|
chanlen = alloca(head->channel_num * sizeof (unsigned int));
|
||||||
|
if (!get_compressed_channels_length(head, f, rle_table, chanlen))
|
||||||
|
goto file_read_error;
|
||||||
|
|
||||||
|
for (c = 0; c < numchan; c++)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = channel;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = read_compressed_channel(f,
|
||||||
|
chanlen[c],
|
||||||
|
pixels_count,
|
||||||
|
channel);
|
||||||
|
if (err == READ_COMPRESSED_ERROR_FILE_CORRUPT)
|
||||||
|
goto file_corrupt;
|
||||||
|
else if (err == READ_COMPRESSED_ERROR_FILE_READ_ERROR)
|
||||||
|
goto file_read_error;
|
||||||
|
|
||||||
|
for (y = 0; y < head->height * bps; y += bps)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps; x += bpp, tmp++)
|
||||||
|
{
|
||||||
|
data[y + x + c] = *tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the alpha channel to solid
|
||||||
|
//@TODO: This needs to be changed for greyscale images.
|
||||||
|
if (head->channels >= 4)
|
||||||
|
{
|
||||||
|
for (y = 0; y < head->height * bps; y += bps)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps; x += bpp)
|
||||||
|
{
|
||||||
|
data[y + x + 3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; c < head->channels; c++)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = channel;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = read_compressed_channel(f,
|
||||||
|
chanlen[c],
|
||||||
|
pixels_count,
|
||||||
|
channel);
|
||||||
|
if (err == READ_COMPRESSED_ERROR_FILE_CORRUPT)
|
||||||
|
goto file_corrupt;
|
||||||
|
else if (err == READ_COMPRESSED_ERROR_FILE_READ_ERROR)
|
||||||
|
goto file_read_error;
|
||||||
|
|
||||||
|
for (y = 0; y < head->height * bps; y += bps)
|
||||||
|
{
|
||||||
|
for (x = 0; x < bps; x += bpp, tmp++)
|
||||||
|
{
|
||||||
|
unsigned short newval;
|
||||||
|
|
||||||
|
newval = *tmp * data[y + x + 3];
|
||||||
|
|
||||||
|
data[y + x + 3] = newval >> 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bpp == 3)
|
||||||
|
{
|
||||||
|
for (x = 0; x < pixels_count; x++)
|
||||||
|
{
|
||||||
|
buffer[x * 4 + 0] = data[x * 3 + 2];
|
||||||
|
buffer[x * 4 + 1] = data[x * 3 + 1];
|
||||||
|
buffer[x * 4 + 2] = data[x * 3 + 0];
|
||||||
|
buffer[x * 4 + 3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// BRGA to RGBA
|
||||||
|
for (x= 0; x < pixels_count; x++)
|
||||||
|
{
|
||||||
|
buffer[x * 4 + 0] = data[x * 4 + 2];
|
||||||
|
buffer[x * 4 + 1] = data[x * 4 + 1];
|
||||||
|
buffer[x * 4 + 2] = data[x * 4 + 0];
|
||||||
|
buffer[x * 4 + 3] = data[x * 4 + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(channel);
|
||||||
|
free(data);
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
|
||||||
|
file_corrupt:
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
|
||||||
|
file_read_error:
|
||||||
|
free(channel);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
get_single_channel(Image_Entry *ie,
|
||||||
|
PSD_Header *head,
|
||||||
|
FILE *f,
|
||||||
|
unsigned char *buffer,
|
||||||
|
Eina_Bool compressed)
|
||||||
|
{
|
||||||
|
unsigned int i, bpc;
|
||||||
|
unsigned short *tmp;
|
||||||
|
char headbyte;
|
||||||
|
int c;
|
||||||
|
int pixels_count;
|
||||||
|
|
||||||
|
tmp = (unsigned short*)buffer;
|
||||||
|
bpc = (head->depth / 8);
|
||||||
|
pixels_count = head->width * head->height;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return EINA_FALSE;
|
||||||
|
|
||||||
|
if (!compressed)
|
||||||
|
{
|
||||||
|
if (bpc == 1)
|
||||||
|
{
|
||||||
|
CHECK_RET(fread(buffer, pixels_count, 1, f), 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Bpc == 2
|
||||||
|
CHECK_RET(fread(buffer, pixels_count * 2, 1, f), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < pixels_count; )
|
||||||
|
{
|
||||||
|
CHECK_RET(fread(&headbyte, 1, 1, f), 1);
|
||||||
|
|
||||||
|
if (headbyte >= 0)
|
||||||
|
{ // && HeadByte <= 127
|
||||||
|
CHECK_RET(fread(buffer + i, headbyte + 1, 1, f), 1);
|
||||||
|
|
||||||
|
i += headbyte + 1;
|
||||||
|
}
|
||||||
|
if (headbyte >= -127 && headbyte <= -1)
|
||||||
|
{
|
||||||
|
int run;
|
||||||
|
|
||||||
|
CHECK_RET(fread(&c, 1, 1, f), 1);
|
||||||
|
|
||||||
|
run = c;
|
||||||
|
if (run == -1) return EINA_FALSE;
|
||||||
|
|
||||||
|
memset(buffer + i, run, -headbyte + 1);
|
||||||
|
i += -headbyte + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
read_psd_grey(Image_Entry *ie, PSD_Header *head, FILE * f, int *error)
|
||||||
|
{
|
||||||
|
unsigned int color_mode, resource_size, misc_info;
|
||||||
|
unsigned short compressed;
|
||||||
|
unsigned int type;
|
||||||
|
void *surface = NULL;
|
||||||
|
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return EINA_FALSE;
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &color_mode), 1);
|
||||||
|
// Skip over the 'color mode data section'
|
||||||
|
CHECK_RET(fseek(f, color_mode, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &resource_size), 1);
|
||||||
|
// Read the 'image resources section'
|
||||||
|
|
||||||
|
CHECK_RET(fseek(f, resource_size, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &misc_info), 1);
|
||||||
|
CHECK_RET(fseek(f, misc_info, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_ushort(f, &compressed), 1);
|
||||||
|
|
||||||
|
ie->w = head->width;
|
||||||
|
ie->h = head->height;
|
||||||
|
if (head->channels == 3) ie->flags.alpha = 0;
|
||||||
|
else ie->flags.alpha = 1;
|
||||||
|
|
||||||
|
head->channel_num = head->channels;
|
||||||
|
// Temporary to read only one channel...some greyscale .psd files have 2.
|
||||||
|
head->channels = 1;
|
||||||
|
|
||||||
|
switch (head->depth)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
type = 1;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
type = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
||||||
|
surface = evas_cache_image_pixels(ie);
|
||||||
|
|
||||||
|
if (!psd_get_data(ie, head, f, surface, compressed, error))
|
||||||
|
goto cleanup_error;
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
|
||||||
|
cleanup_error:
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
read_psd_indexed(Image_Entry *ie, PSD_Header *head, FILE * f, int *error)
|
||||||
|
{
|
||||||
|
unsigned int color_mode, resource_size, misc_info;
|
||||||
|
unsigned short compressed;
|
||||||
|
void *surface;
|
||||||
|
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return EINA_FALSE;
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &color_mode), 1);
|
||||||
|
CHECK_RET((color_mode % 3), 0);
|
||||||
|
/*
|
||||||
|
Palette = (unsigned char*)malloc(Colormode);
|
||||||
|
if (Palette == NULL)
|
||||||
|
return EINA_FALSE;
|
||||||
|
if (fread(&Palette, 1, Colormode, file) != Colormode)
|
||||||
|
goto cleanup_error;
|
||||||
|
*/
|
||||||
|
// Skip over the 'color mode data section'
|
||||||
|
CHECK_RET(fseek(f, color_mode, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
// Read the 'image resources section'
|
||||||
|
CHECK_RET(read_uint(f, &resource_size), 1);
|
||||||
|
CHECK_RET(fseek(f, resource_size, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &misc_info), 1);
|
||||||
|
CHECK_RET(fseek(f, misc_info, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_ushort(f, &compressed), 1);
|
||||||
|
|
||||||
|
if (head->channels != 1 || head->depth != 8)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
head->channel_num = head->channels;
|
||||||
|
|
||||||
|
ie->w = head->width;
|
||||||
|
ie->h = head->height;
|
||||||
|
if (head->channels == 3) ie->flags.alpha = 0;
|
||||||
|
else ie->flags.alpha = 1;
|
||||||
|
|
||||||
|
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
||||||
|
surface = evas_cache_image_pixels(ie);
|
||||||
|
|
||||||
|
if (!psd_get_data(ie, head, f, surface, compressed, error))
|
||||||
|
return EINA_FALSE;
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
read_psd_rgb(Image_Entry *ie, PSD_Header *head, FILE *f, int *error)
|
||||||
|
{
|
||||||
|
unsigned int color_mode, resource_size, misc_info;
|
||||||
|
unsigned short compressed;
|
||||||
|
unsigned int format, type;
|
||||||
|
void *surface;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return EINA_FALSE;
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &color_mode), 1);
|
||||||
|
// Skip over the 'color mode data section'
|
||||||
|
CHECK_RET(fseek(f, color_mode, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
// Read the 'image resources section'
|
||||||
|
CHECK_RET(read_uint(f, &resource_size), 1);
|
||||||
|
CHECK_RET(fseek(f, resource_size, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &misc_info), 1);
|
||||||
|
CHECK_RET(fseek(f, misc_info, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_ushort(f, &compressed), 1);
|
||||||
|
|
||||||
|
head->channel_num = head->channels;
|
||||||
|
|
||||||
|
switch (head->depth)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
type = 1;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
type = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
ie->w = head->width;
|
||||||
|
ie->h = head->height;
|
||||||
|
if (head->channels == 3) ie->flags.alpha = 0;
|
||||||
|
else ie->flags.alpha = 1;
|
||||||
|
|
||||||
|
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
||||||
|
surface = evas_cache_image_pixels(ie);
|
||||||
|
|
||||||
|
if (!psd_get_data(ie, head, f, surface, compressed, error))
|
||||||
|
goto cleanup_error;
|
||||||
|
|
||||||
|
evas_common_image_premul(ie);
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
#undef CHECK_RET
|
||||||
|
|
||||||
|
cleanup_error:
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
read_psd_cmyk(Image_Entry *ie, PSD_Header *head, FILE *f, int *error)
|
||||||
|
{
|
||||||
|
unsigned int color_mode, resource_size, misc_info, size, i, j, data_size;
|
||||||
|
unsigned short compressed;
|
||||||
|
unsigned int format, type;
|
||||||
|
unsigned char *kchannel = NULL;
|
||||||
|
void *surface;
|
||||||
|
|
||||||
|
*error = EVAS_LOAD_ERROR_CORRUPT_FILE;
|
||||||
|
|
||||||
|
#define CHECK_RET(Call, Value) \
|
||||||
|
if (Call != Value) return EINA_FALSE;
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &color_mode), 1);
|
||||||
|
// Skip over the 'color mode data section'
|
||||||
|
CHECK_RET(fseek(f, color_mode, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &resource_size), 1);
|
||||||
|
// Read the 'image resources section'
|
||||||
|
CHECK_RET(fseek(f, resource_size, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_uint(f, &misc_info), 1);
|
||||||
|
CHECK_RET(fseek(f, misc_info, SEEK_CUR), 0);
|
||||||
|
|
||||||
|
CHECK_RET(read_ushort(f, &compressed), 1);
|
||||||
|
|
||||||
|
switch (head->channels)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
format = 0x1907;
|
||||||
|
head->channel_num = 4;
|
||||||
|
head->channels = 3;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
format = 0x1908;
|
||||||
|
head->channel_num = 5;
|
||||||
|
head->channels = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (head->depth)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
type = 1;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
type = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie->w = head->width;
|
||||||
|
ie->h = head->height;
|
||||||
|
if (head->channels == 3) ie->flags.alpha = 0;
|
||||||
|
else ie->flags.alpha = 1;
|
||||||
|
|
||||||
|
evas_cache_image_surface_alloc(ie, ie->w, ie->h);
|
||||||
|
surface = evas_cache_image_pixels(ie);
|
||||||
|
|
||||||
|
if (!psd_get_data(ie, head, f, surface, compressed, error))
|
||||||
|
goto cleanup_error;
|
||||||
|
|
||||||
|
size = type * ie->w * ie->h;
|
||||||
|
kchannel = malloc(size);
|
||||||
|
if (kchannel == NULL)
|
||||||
|
goto cleanup_error;
|
||||||
|
if (!get_single_channel(ie, head, f, kchannel, compressed))
|
||||||
|
goto cleanup_error;
|
||||||
|
|
||||||
|
data_size = head->channels * type * ie->w * ie->h;
|
||||||
|
if (format == 0x1907)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = surface;
|
||||||
|
const unsigned char *limit = tmp + data_size;
|
||||||
|
|
||||||
|
for (i = 0, j = 0; tmp < limit; tmp++, j++)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (k = 0; k < 3; k++)
|
||||||
|
*tmp = (*tmp * kchannel[j]) >> 8;
|
||||||
|
|
||||||
|
// FIXME: tmp[i+3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // RGBA
|
||||||
|
unsigned char *tmp = surface;
|
||||||
|
const unsigned char *limit = tmp + data_size;
|
||||||
|
|
||||||
|
// The KChannel array really holds the alpha channel on this one.
|
||||||
|
for (i = 0, j = 0; tmp < limit; tmp += 4, j++)
|
||||||
|
{
|
||||||
|
tmp[0] = (tmp[0] * tmp[3]) >> 8;
|
||||||
|
tmp[1] = (tmp[1] * tmp[3]) >> 8;
|
||||||
|
tmp[2] = (tmp[2] * tmp[3]) >> 8;
|
||||||
|
tmp[3] = kchannel[j]; // Swap 'K' with alpha channel.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(kchannel);
|
||||||
|
|
||||||
|
evas_common_image_premul(ie);
|
||||||
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
cleanup_error:
|
||||||
|
free(kchannel);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
evas_image_load_file_data_psd(Image_Entry *ie,
|
||||||
|
const char *file,
|
||||||
|
const char *key,
|
||||||
|
int *error)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
PSD_Header header;
|
||||||
|
Eina_Bool bpsd = EINA_FALSE;
|
||||||
|
|
||||||
|
f = fopen(file, "rb");
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
|
||||||
|
return bpsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
psd_get_header(&header, f);
|
||||||
|
if (!is_psd(&header))
|
||||||
|
{
|
||||||
|
*error = EVAS_LOAD_ERROR_GENERIC;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ie->w = header.width;
|
||||||
|
ie->h = header.height;
|
||||||
|
|
||||||
|
*error = EVAS_LOAD_ERROR_NONE;
|
||||||
|
|
||||||
|
switch (header.mode)
|
||||||
|
{
|
||||||
|
case PSD_GREYSCALE: // Greyscale
|
||||||
|
bpsd = read_psd_grey(ie, &header, f, error);
|
||||||
|
break;
|
||||||
|
case PSD_INDEXED: // Indexed
|
||||||
|
bpsd = read_psd_indexed(ie, &header, f, error);
|
||||||
|
break;
|
||||||
|
case PSD_RGB: // RGB
|
||||||
|
bpsd = read_psd_rgb(ie, &header, f, error);
|
||||||
|
break;
|
||||||
|
case PSD_CMYK: // CMYK
|
||||||
|
bpsd = read_psd_cmyk(ie, &header, f, error);
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
|
||||||
|
bpsd = EINA_FALSE;
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return bpsd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
get_compressed_channels_length(PSD_Header *head,
|
||||||
|
FILE * file,
|
||||||
|
unsigned short *rle_table,
|
||||||
|
unsigned int *chanlen)
|
||||||
|
{
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int c;
|
||||||
|
|
||||||
|
if (fread(rle_table,
|
||||||
|
sizeof(unsigned short),
|
||||||
|
head->height * head->channel_num,
|
||||||
|
file) != head->height * head->channel_num)
|
||||||
|
return EINA_FALSE;
|
||||||
|
|
||||||
|
memset(chanlen, 0, head->channel_num * sizeof(unsigned int));
|
||||||
|
for (c = 0; c < head->channel_num; c++)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
j = c * head->height;
|
||||||
|
for (i = 0; i < head->height; i++)
|
||||||
|
{
|
||||||
|
chanlen[c] += rle_table[i + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Evas_Image_Load_Func evas_image_load_psd_func = {
|
||||||
|
EINA_TRUE,
|
||||||
|
evas_image_load_file_head_psd,
|
||||||
|
evas_image_load_file_data_psd
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
module_open(Evas_Module *em)
|
||||||
|
{
|
||||||
|
if (!em) return 0;
|
||||||
|
em->functions = (void *)(&evas_image_load_psd_func);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
module_close(Evas_Module *em __UNUSED__)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static Evas_Module_Api evas_modapi =
|
||||||
|
{
|
||||||
|
EVAS_MODULE_API_VERSION,
|
||||||
|
"psd",
|
||||||
|
"none",
|
||||||
|
{
|
||||||
|
module_open,
|
||||||
|
module_close
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, psd);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef EVAS_STATIC_BUILD_PSD
|
||||||
|
EVAS_EINA_MODULE_DEFINE(image_loader, psd);
|
||||||
|
#endif
|
Loading…
Reference in New Issue