You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2082 lines
41 KiB
2082 lines
41 KiB
#define _GNU_SOURCE
|
|
#include <config.h>
|
|
#include "Imlib.h"
|
|
#include "Imlib_private.h"
|
|
#include <setjmp.h>
|
|
|
|
/* Split the ID - damages input */
|
|
|
|
static char *
|
|
_SplitID(char *file)
|
|
{
|
|
#ifndef __EMX__
|
|
char *p = strrchr(file, ':');
|
|
#else
|
|
char *p = strrchr(file, ';');
|
|
#endif
|
|
|
|
if (p == NULL)
|
|
return "";
|
|
else
|
|
{
|
|
*p++ = 0;
|
|
return p;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* * Doesn't damage the input
|
|
*/
|
|
|
|
char *
|
|
_GetExtension(char *file)
|
|
{
|
|
char *p = strrchr(file, '.');
|
|
|
|
if (p == NULL)
|
|
return "";
|
|
else
|
|
return p + 1;
|
|
}
|
|
|
|
/*
|
|
* Make sure we don't wrap on our memory allocations
|
|
*/
|
|
|
|
void * _imlib_malloc_image(unsigned int w, unsigned int h)
|
|
{
|
|
if( w > 32767 || h > 32767)
|
|
return NULL;
|
|
return malloc(w * h * 3);
|
|
}
|
|
|
|
#ifdef HAVE_LIBJPEG
|
|
|
|
/**
|
|
* * This error handling is broken beyond belief, but oh well it works
|
|
* **/
|
|
|
|
struct ImLib_JPEG_error_mgr
|
|
{
|
|
struct jpeg_error_mgr pub;
|
|
sigjmp_buf setjmp_buffer;
|
|
};
|
|
|
|
typedef struct ImLib_JPEG_error_mgr *emptr;
|
|
|
|
void
|
|
_JPEGFatalErrorHandler(j_common_ptr cinfo)
|
|
{
|
|
/*
|
|
* FIXME:
|
|
* We should somehow signal what error occurred to the caller so the
|
|
* caller can handle the error message
|
|
*/
|
|
emptr errmgr;
|
|
|
|
errmgr = (emptr) cinfo->err;
|
|
cinfo->err->output_message(cinfo);
|
|
siglongjmp(errmgr->setjmp_buffer, 1);
|
|
return;
|
|
}
|
|
|
|
unsigned char *
|
|
_LoadJPEG(ImlibData * id, FILE * f, int *w, int *h)
|
|
{
|
|
struct jpeg_decompress_struct cinfo;
|
|
struct ImLib_JPEG_error_mgr jerr;
|
|
unsigned char *data, *line[16], *ptr;
|
|
int x, y, i;
|
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
|
|
|
/* error handler to longjmp to, we want to preserve signals */
|
|
if (sigsetjmp(jerr.setjmp_buffer, 1))
|
|
{
|
|
/* Whoops there was a jpeg error */
|
|
jpeg_destroy_decompress(&cinfo);
|
|
return NULL;
|
|
}
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
jpeg_stdio_src(&cinfo, f);
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
cinfo.do_fancy_upsampling = FALSE;
|
|
cinfo.do_block_smoothing = FALSE;
|
|
jpeg_start_decompress(&cinfo);
|
|
*w = cinfo.output_width;
|
|
*h = cinfo.output_height;
|
|
data = _imlib_malloc_image(*w, *h);
|
|
if (!data)
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
return NULL;
|
|
}
|
|
ptr = data;
|
|
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
{
|
|
fprintf(stderr, "Imlib ERROR: JPEG uses line buffers > 16. Cannot load.\n");
|
|
return NULL;
|
|
}
|
|
if (cinfo.output_components == 3)
|
|
{
|
|
for (y = 0; y < *h; y += cinfo.rec_outbuf_height)
|
|
{
|
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
|
{
|
|
line[i] = ptr;
|
|
ptr += *w * 3;
|
|
}
|
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
|
}
|
|
}
|
|
else if (cinfo.output_components == 1)
|
|
{
|
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
|
{
|
|
if ((line[i] = malloc(*w)) == NULL)
|
|
{
|
|
int t = 0;
|
|
|
|
for (t = 0; t < i; t++)
|
|
free(line[t]);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
return NULL;
|
|
}
|
|
}
|
|
for (y = 0; y < *h; y += cinfo.rec_outbuf_height)
|
|
{
|
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
|
{
|
|
for (x = 0; x < *w; x++)
|
|
{
|
|
*ptr++ = line[i][x];
|
|
*ptr++ = line[i][x];
|
|
*ptr++ = line[i][x];
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
|
free(line[i]);
|
|
}
|
|
jpeg_finish_decompress(&cinfo);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return data;
|
|
}
|
|
#endif /* HAVE_LIBJPEG */
|
|
|
|
#ifdef HAVE_LIBPNG
|
|
unsigned char *
|
|
_LoadPNG(ImlibData * id, FILE * f, int *w, int *h, int *t)
|
|
{
|
|
png_structp png_ptr;
|
|
png_infop info_ptr;
|
|
unsigned char *data, *ptr, **lines, *ptr2, r, g, b, a;
|
|
int i, x, y, transp, bit_depth, color_type, interlace_type;
|
|
png_uint_32 ww, hh;
|
|
|
|
/* Init PNG Reader */
|
|
transp = 0;
|
|
|
|
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
if (!png_ptr)
|
|
return NULL;
|
|
info_ptr = png_create_info_struct(png_ptr);
|
|
if (!info_ptr)
|
|
{
|
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
return NULL;
|
|
}
|
|
if (setjmp(png_ptr->jmpbuf))
|
|
{
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
|
{
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
png_init_io(png_ptr, f);
|
|
|
|
/* Read Header */
|
|
png_read_info(png_ptr, info_ptr);
|
|
png_get_IHDR(png_ptr, info_ptr, &ww, &hh,
|
|
&bit_depth, &color_type, &interlace_type, NULL, NULL);
|
|
*w = ww;
|
|
*h = hh;
|
|
|
|
/* Setup Translators */
|
|
if ((color_type == PNG_COLOR_TYPE_PALETTE) ||
|
|
(color_type == PNG_COLOR_TYPE_GRAY))
|
|
png_set_expand(png_ptr);
|
|
png_set_strip_16(png_ptr);
|
|
png_set_packing(png_ptr);
|
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
|
|
png_set_expand(png_ptr);
|
|
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
|
|
data = _imlib_malloc_image(*w, *h);
|
|
if (!data)
|
|
{
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
/* This malloc is fine, _imlib_malloc_image will fail first */
|
|
lines = (unsigned char **)malloc(*h * sizeof(unsigned char *));
|
|
|
|
if (lines == NULL)
|
|
{
|
|
free(data);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < *h; i++)
|
|
{
|
|
/* Safe as well for the same reason as above */
|
|
if ((lines[i] = malloc(*w * (sizeof(unsigned char) * 4))) == NULL)
|
|
{
|
|
int n;
|
|
|
|
free(data);
|
|
for (n = 0; n < i; n++)
|
|
free(lines[n]);
|
|
free(lines);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
png_read_image(png_ptr, lines);
|
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
ptr = data;
|
|
if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
|
{
|
|
for (y = 0; y < *h; y++)
|
|
{
|
|
ptr2 = lines[y];
|
|
for (x = 0; x < *w; x++)
|
|
{
|
|
r = *ptr2++;
|
|
a = *ptr2++;
|
|
if (a < 128)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
transp = 1;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = r;
|
|
*ptr++ = r;
|
|
*ptr++ = r;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (color_type == PNG_COLOR_TYPE_GRAY)
|
|
{
|
|
for (y = 0; y < *h; y++)
|
|
{
|
|
ptr2 = lines[y];
|
|
for (x = 0; x < *w; x++)
|
|
{
|
|
r = *ptr2++;
|
|
ptr2++;
|
|
*ptr++ = r;
|
|
*ptr++ = r;
|
|
*ptr++ = r;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (y = 0; y < *h; y++)
|
|
{
|
|
ptr2 = lines[y];
|
|
for (x = 0; x < *w; x++)
|
|
{
|
|
r = *ptr2++;
|
|
g = *ptr2++;
|
|
b = *ptr2++;
|
|
a = *ptr2++;
|
|
if (a < 128)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
transp = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((r == 255) && (g == 0) && (b == 255))
|
|
r = 254;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < *h; i++)
|
|
free(lines[i]);
|
|
free(lines);
|
|
*t = transp;
|
|
return data;
|
|
}
|
|
#endif /* HAVE_LIBPNG */
|
|
|
|
#ifdef HAVE_LIBTIFF
|
|
unsigned char *
|
|
_LoadTIFF(ImlibData * id, FILE *f, char *file, int *w, int *h, int *t)
|
|
{
|
|
TIFF *tif;
|
|
unsigned char *data, *ptr, r, g, b, a;
|
|
int x, y;
|
|
uint32 ww, hh, *rast, *tptr;
|
|
size_t npix;
|
|
int istransp;
|
|
int fd;
|
|
|
|
istransp = 0;
|
|
if (!f)
|
|
return NULL;
|
|
|
|
fd = fileno(f);
|
|
/* Apparently rewind(f) isn't sufficient */
|
|
lseek(fd, (long) 0, 0);
|
|
/* So why does libtif need a filename here ??? */
|
|
tif = TIFFFdOpen(fd, file, "r");
|
|
|
|
if (!tif)
|
|
return NULL;
|
|
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &ww);
|
|
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &hh);
|
|
npix = ww * hh;
|
|
*w = (int)ww;
|
|
*h = (int)hh;
|
|
if(ww > 32767 || hh > 32767)
|
|
{
|
|
TIFFClose(tif);
|
|
return NULL;
|
|
}
|
|
rast = (uint32 *) _TIFFmalloc(npix * sizeof(uint32));
|
|
if (!rast)
|
|
{
|
|
TIFFClose(tif);
|
|
return NULL;
|
|
}
|
|
data = NULL;
|
|
if (TIFFReadRGBAImage(tif, ww, hh, rast, 0))
|
|
{
|
|
data = (unsigned char *)malloc(*w ** h * 3);
|
|
if (!data)
|
|
{
|
|
_TIFFfree(rast);
|
|
TIFFClose(tif);
|
|
return NULL;
|
|
}
|
|
ptr = data;
|
|
for (y = 0; y < *h; y++)
|
|
{
|
|
tptr = rast;
|
|
tptr += ((*h - y - 1) ** w);
|
|
for (x = 0; x < *w; x++)
|
|
{
|
|
a = TIFFGetA(*tptr);
|
|
b = TIFFGetB(*tptr);
|
|
g = TIFFGetG(*tptr);
|
|
r = TIFFGetR(*tptr);
|
|
tptr++;
|
|
if (a < 128)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
istransp = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((r == 255) && (g == 0) && (b == 255))
|
|
r = 254;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_TIFFfree(rast);
|
|
TIFFClose(tif);
|
|
*t = istransp;
|
|
return data;
|
|
}
|
|
|
|
#endif /* HAVE_LIBTIFF */
|
|
|
|
#ifdef HAVE_LIBGIF
|
|
unsigned char *
|
|
_LoadGIF(ImlibData * id, FILE *f, int *w, int *h, int *t)
|
|
{
|
|
unsigned char *data, *ptr;
|
|
GifFileType *gif;
|
|
GifRowType *rows;
|
|
GifRecordType rec;
|
|
ColorMapObject *cmap;
|
|
int i, j, done, bg, csize, r, g, b;
|
|
int intoffset[] = {0, 4, 2, 1};
|
|
int intjump[] = {8, 8, 4, 2};
|
|
int istransp, transp;
|
|
int fd;
|
|
|
|
done = 0;
|
|
istransp = 0;
|
|
data = NULL;
|
|
rows = NULL;
|
|
transp = -1;
|
|
|
|
fd = fileno(f);
|
|
/* Apparently rewind(f) isn't sufficient */
|
|
lseek(fd, (long) 0, 0);
|
|
gif = DGifOpenFileHandle(fd);
|
|
|
|
if (!gif)
|
|
return NULL;
|
|
do
|
|
{
|
|
if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
|
|
{
|
|
PrintGifError();
|
|
rec = TERMINATE_RECORD_TYPE;
|
|
}
|
|
if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
|
|
{
|
|
if (DGifGetImageDesc(gif) == GIF_ERROR)
|
|
{
|
|
PrintGifError();
|
|
rec = TERMINATE_RECORD_TYPE;
|
|
}
|
|
*w = gif->Image.Width;
|
|
*h = gif->Image.Height;
|
|
if (*h > 32767 || *w > 32767)
|
|
{
|
|
return NULL;
|
|
}
|
|
rows = malloc(*h * sizeof(GifRowType *));
|
|
if (!rows)
|
|
{
|
|
DGifCloseFile(gif);
|
|
return NULL;
|
|
}
|
|
data = _imlib_malloc_image(*w, *h);
|
|
if (!data)
|
|
{
|
|
DGifCloseFile(gif);
|
|
free(rows);
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < *h; i++)
|
|
rows[i] = NULL;
|
|
for (i = 0; i < *h; i++)
|
|
{
|
|
rows[i] = malloc(*w * sizeof(GifPixelType));
|
|
if (!rows[i])
|
|
{
|
|
DGifCloseFile(gif);
|
|
for (i = 0; i < *h; i++)
|
|
if (rows[i])
|
|
free(rows[i]);
|
|
free(rows);
|
|
free(data);
|
|
return NULL;
|
|
}
|
|
}
|
|
if (gif->Image.Interlace)
|
|
{
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
for (j = intoffset[i]; j < *h; j += intjump[i])
|
|
DGifGetLine(gif, rows[j], *w);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < *h; i++)
|
|
DGifGetLine(gif, rows[i], *w);
|
|
}
|
|
done = 1;
|
|
}
|
|
else if (rec == EXTENSION_RECORD_TYPE)
|
|
{
|
|
int ext_code;
|
|
GifByteType *ext;
|
|
|
|
ext = NULL;
|
|
DGifGetExtension(gif, &ext_code, &ext);
|
|
while (ext)
|
|
{
|
|
if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0))
|
|
{
|
|
istransp = 1;
|
|
transp = (int)ext[4];
|
|
}
|
|
ext = NULL;
|
|
DGifGetExtensionNext(gif, &ext);
|
|
}
|
|
}
|
|
}
|
|
while (rec != TERMINATE_RECORD_TYPE);
|
|
bg = gif->SBackGroundColor;
|
|
cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
|
|
csize = cmap->ColorCount;
|
|
ptr = data;
|
|
if (!istransp)
|
|
{
|
|
for (i = 0; i < *h; i++)
|
|
{
|
|
for (j = 0; j < *w; j++)
|
|
{
|
|
r = cmap->Colors[rows[i][j]].Red;
|
|
g = cmap->Colors[rows[i][j]].Green;
|
|
b = cmap->Colors[rows[i][j]].Blue;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < *h; i++)
|
|
{
|
|
for (j = 0; j < *w; j++)
|
|
{
|
|
if (rows[i][j] == transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
r = cmap->Colors[rows[i][j]].Red;
|
|
g = cmap->Colors[rows[i][j]].Green;
|
|
b = cmap->Colors[rows[i][j]].Blue;
|
|
if ((r == 255) && (g == 0) && (b == 255))
|
|
r = 254;
|
|
*ptr++ = r;
|
|
*ptr++ = g;
|
|
*ptr++ = b;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DGifCloseFile(gif);
|
|
for (i = 0; i < *h; i++)
|
|
free(rows[i]);
|
|
free(rows);
|
|
*t = istransp;
|
|
return data;
|
|
}
|
|
|
|
#endif /* HAVE_LIBGIF */
|
|
|
|
unsigned char *
|
|
_LoadBMP(ImlibData * id, FILE *file, int *w, int *h, int *t)
|
|
{
|
|
unsigned char *data, *ptr;
|
|
int done, i, bpp, planes, comp, ncolors, line, column,
|
|
linesize, linepos, rshift, gshift, bshift, size;
|
|
unsigned char byte;
|
|
short int word;
|
|
long int dbuf[4], dword, rmask, gmask, bmask, offset;
|
|
signed char bbuf[4];
|
|
struct _cmap
|
|
{
|
|
unsigned char r, g, b;
|
|
}
|
|
*cmap;
|
|
|
|
#define BI_RGB 0
|
|
#define BI_RLE8 1
|
|
#define BI_RLE4 2
|
|
#define BI_BITFIELDS 3
|
|
|
|
rshift = 0;
|
|
gshift = 0;
|
|
bshift = 0;
|
|
rmask = 0xff;
|
|
gmask = 0xff;
|
|
bmask = 0xff;
|
|
if (!file)
|
|
return NULL;
|
|
|
|
done = 0;
|
|
/*
|
|
* reading the bmp header
|
|
*/
|
|
|
|
fread(bbuf, 1, 2, file);
|
|
|
|
fread(dbuf, 4, 4, file);
|
|
|
|
size = dbuf[0];
|
|
offset = dbuf[2];
|
|
|
|
fread(dbuf, 4, 2, file);
|
|
*w = (int)dbuf[0];
|
|
*h = (int)dbuf[1];
|
|
if ((*w > 32767) || (*w < 0))
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n");
|
|
return NULL;
|
|
}
|
|
if ((*h > 32767) || (*h < 0))
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n");
|
|
return NULL;
|
|
}
|
|
fread(&word, 2, 1, file);
|
|
planes = (int)word;
|
|
fread(&word, 2, 1, file);
|
|
bpp = (int)word;
|
|
if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: unknown bitdepth in file\n");
|
|
return NULL;
|
|
}
|
|
fread(dbuf, 4, 4, file);
|
|
comp = (int)dbuf[0];
|
|
if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: unknown encoding in Windows BMP file\n");
|
|
return NULL;
|
|
}
|
|
fread(dbuf, 4, 2, file);
|
|
ncolors = (int)dbuf[0];
|
|
if ((ncolors > (1 << bpp)) || (ncolors < 0))
|
|
ncolors = 1 << bpp;
|
|
if ((ncolors < 0) || (ncolors > (1 << bpp)))
|
|
ncolors = 1 << bpp;
|
|
|
|
/* some more sanity checks */
|
|
if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: encoding of BMP doesn't match bitdepth\n");
|
|
return NULL;
|
|
}
|
|
if (bpp < 16)
|
|
{
|
|
cmap = (struct _cmap *)malloc(sizeof(struct _cmap) * ncolors);
|
|
|
|
if (!cmap)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for color map in BMP file\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
cmap = NULL;
|
|
ptr = (unsigned char *)_imlib_malloc_image(*w, *h);
|
|
if (!ptr)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for RGB data in file\n");
|
|
if (cmap)
|
|
free(cmap);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Reading the palette, if it exists.
|
|
*/
|
|
if (bpp < 16 && ncolors != 0)
|
|
{
|
|
for (i = 0; i < ncolors; i++)
|
|
{
|
|
fread(bbuf, 1, 4, file);
|
|
cmap[i].b = bbuf[0];
|
|
cmap[i].g = bbuf[1];
|
|
cmap[i].r = bbuf[2];
|
|
}
|
|
}
|
|
else if (bpp == 16 || bpp == 32)
|
|
{
|
|
if (comp == BI_BITFIELDS)
|
|
{
|
|
int bit = 0;
|
|
|
|
fread(dbuf, 4, 3, file);
|
|
bmask = dbuf[0];
|
|
gmask = dbuf[1];
|
|
rmask = dbuf[2];
|
|
/* find shift amount.. ugly, but i can't think of a better way */
|
|
for (bit = 0; bit < bpp; bit++)
|
|
{
|
|
if (bmask & (1 << bit))
|
|
bshift = bit;
|
|
if (gmask & (1 << bit))
|
|
gshift = bit;
|
|
if (rmask & (1 << bit))
|
|
rshift = bit;
|
|
}
|
|
}
|
|
else if (bpp == 16)
|
|
{
|
|
rmask = 0x7C00;
|
|
gmask = 0x03E0;
|
|
bmask = 0x001F;
|
|
rshift = 10;
|
|
gshift = 5;
|
|
bshift = 0;
|
|
}
|
|
else if (bpp == 32)
|
|
{
|
|
rmask = 0x00FF0000;
|
|
gmask = 0x0000FF00;
|
|
bmask = 0x000000FF;
|
|
rshift = 16;
|
|
gshift = 8;
|
|
bshift = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Reading the image data
|
|
*/
|
|
fseek(file, offset, SEEK_SET);
|
|
data = ptr;
|
|
|
|
/* set the whole image to the background color */
|
|
if (bpp < 16 && (comp == BI_RLE4 || comp == BI_RLE8))
|
|
{
|
|
for (i = 0; i < *w * *h; i++)
|
|
{
|
|
*ptr++ = cmap[0].r;
|
|
*ptr++ = cmap[0].g;
|
|
*ptr++ = cmap[0].b;
|
|
}
|
|
ptr = data;
|
|
}
|
|
line = 0;
|
|
column = 0;
|
|
#define poffset (line * *w * 3 + column * 3)
|
|
|
|
/*
|
|
* BMPs are stored upside down... hmmmmmmmmmm....
|
|
*/
|
|
|
|
linesize = ((*w * bpp + 31) / 32) * 4;
|
|
for (line = (*h - 1); line >= 0; line--)
|
|
{
|
|
linepos = 0;
|
|
for (column = 0; column < *w;)
|
|
{
|
|
if (bpp < 16)
|
|
{
|
|
int index;
|
|
|
|
linepos++;
|
|
byte = getc(file);
|
|
if (bpp == 1)
|
|
{
|
|
int bit = 0;
|
|
|
|
for (bit = 0; bit < 8; bit++)
|
|
{
|
|
index = ((byte & (0x80 >> bit)) ? 1 : 0);
|
|
/* possibly corrupted file? */
|
|
if (index < ncolors && poffset < *w * *h * 3)
|
|
{
|
|
ptr[poffset] = cmap[index].r;
|
|
ptr[poffset + 1] = cmap[index].g;
|
|
ptr[poffset + 2] = cmap[index].b;
|
|
}
|
|
column++;
|
|
}
|
|
}
|
|
else if (bpp == 4)
|
|
{
|
|
if (comp == BI_RLE4)
|
|
{
|
|
fprintf(stderr, "can't deal with 4bit encoded yet.\n");
|
|
free(data);
|
|
free(cmap);
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
int nibble = 0;
|
|
|
|
for (nibble = 0; nibble < 2; nibble++)
|
|
{
|
|
index = ((byte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
|
|
if (index >= 16)
|
|
index = 15;
|
|
/* possibly corrupted file? */
|
|
if (index < ncolors && poffset < *w * *h * 3)
|
|
{
|
|
ptr[poffset] = cmap[index].r;
|
|
ptr[poffset + 1] = cmap[index].g;
|
|
ptr[poffset + 2] = cmap[index].b;
|
|
}
|
|
column++;
|
|
}
|
|
}
|
|
}
|
|
else if (bpp == 8)
|
|
{
|
|
if (comp == BI_RLE8)
|
|
{
|
|
unsigned char first = byte;
|
|
|
|
byte = getc(file);
|
|
if (first == 0)
|
|
{
|
|
if (byte == 0)
|
|
{
|
|
/* column = *w; */
|
|
}
|
|
else if (byte == 1)
|
|
{
|
|
column = *w;
|
|
line = -1;
|
|
}
|
|
else if (byte == 2)
|
|
{
|
|
byte = getc(file);
|
|
column += byte;
|
|
linepos = column * bpp / 8;
|
|
byte = getc(file);
|
|
line += byte;
|
|
}
|
|
else
|
|
{
|
|
int absolute = byte;
|
|
|
|
for (i = 0; i < absolute; i++)
|
|
{
|
|
linepos++;
|
|
byte = getc(file);
|
|
/* possibly corrupted file? */
|
|
if (byte < ncolors && poffset < *w * *h * 3)
|
|
{
|
|
ptr[poffset] = cmap[byte].r;
|
|
ptr[poffset + 1] = cmap[byte].g;
|
|
ptr[poffset + 2] = cmap[byte].b;
|
|
}
|
|
column++;
|
|
}
|
|
if (absolute & 0x01)
|
|
byte = getc(file);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < first; i++)
|
|
{
|
|
/* possibly corrupted file? */
|
|
if (byte < ncolors && poffset < *w * *h * 3)
|
|
{
|
|
ptr[poffset] = cmap[byte].r;
|
|
ptr[poffset + 1] = cmap[byte].g;
|
|
ptr[poffset + 2] = cmap[byte].b;
|
|
}
|
|
column++;
|
|
linepos++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* possibly corrupted file? */
|
|
if (byte < ncolors && poffset < *w * *h * 3)
|
|
{
|
|
ptr[poffset] = cmap[byte].r;
|
|
ptr[poffset + 1] = cmap[byte].g;
|
|
ptr[poffset + 2] = cmap[byte].b;
|
|
}
|
|
column++;
|
|
}
|
|
}
|
|
}
|
|
else if (bpp == 24)
|
|
{
|
|
linepos += fread(bbuf, 1, 3, file);
|
|
/* possibly corrupted file? */
|
|
if (poffset < *w * *h * 3)
|
|
{
|
|
ptr[poffset] = (unsigned char)bbuf[2];
|
|
ptr[poffset + 1] = (unsigned char)bbuf[1];
|
|
ptr[poffset + 2] = (unsigned char)bbuf[0];
|
|
}
|
|
column++;
|
|
}
|
|
else if (bpp == 16)
|
|
{
|
|
unsigned char temp;
|
|
|
|
linepos += fread(&word, 2, 1, file);
|
|
/* possibly corrupted file? */
|
|
if (poffset < *w * *h * 3)
|
|
{
|
|
temp = (word & rmask) >> rshift;
|
|
ptr[poffset] = temp;
|
|
temp = (word & gmask) >> gshift;
|
|
ptr[poffset + 1] = temp;
|
|
temp = (word & bmask) >> gshift;
|
|
ptr[poffset + 2] = temp;
|
|
}
|
|
column++;
|
|
}
|
|
else
|
|
{
|
|
unsigned char temp;
|
|
|
|
linepos += fread(&dword, 4, 1, file);
|
|
/* possibly corrupted file? */
|
|
if (poffset < *w * *h * 3)
|
|
{
|
|
temp = (dword & rmask) >> rshift;
|
|
ptr[poffset] = temp;
|
|
temp = (dword & gmask) >> gshift;
|
|
ptr[poffset + 1] = temp;
|
|
temp = (dword & bmask) >> bshift;
|
|
ptr[poffset + 2] = temp;
|
|
}
|
|
column++;
|
|
}
|
|
}
|
|
while ((linepos < linesize) && (comp != 1) && (comp != 2))
|
|
{
|
|
int temp = fread(&byte, 1, 1, file);
|
|
|
|
linepos += temp;
|
|
if (!temp)
|
|
break;
|
|
}
|
|
}
|
|
if (cmap)
|
|
free(cmap);
|
|
*t = 0;
|
|
return data;
|
|
}
|
|
|
|
unsigned char *
|
|
_LoadXPM(ImlibData * id, FILE *file, int *w, int *h, int *t)
|
|
{
|
|
unsigned char *data, *ptr, *end;
|
|
int pc, c, i, j, k, ncolors, cpp, comment, transp, quote,
|
|
context, len, done;
|
|
char *line, s[256], tok[128], col[256];
|
|
XColor xcol;
|
|
int lsz = 256;
|
|
struct _cmap
|
|
{
|
|
unsigned char str[6];
|
|
unsigned char transp;
|
|
short r, g, b;
|
|
}
|
|
*cmap;
|
|
short lookup[128 - 32][128 - 32];
|
|
|
|
transp = 0;
|
|
done = 0;
|
|
if (!file)
|
|
return NULL;
|
|
i = 0;
|
|
j = 0;
|
|
cmap = NULL;
|
|
*w = 10;
|
|
*h = 10;
|
|
ptr = NULL;
|
|
data = NULL;
|
|
end = NULL;
|
|
c = ' ';
|
|
comment = 0;
|
|
quote = 0;
|
|
context = 0;
|
|
line = malloc(lsz);
|
|
while (!done)
|
|
{
|
|
pc = c;
|
|
c = fgetc(file);
|
|
if (c == EOF)
|
|
break;
|
|
if (!quote)
|
|
{
|
|
if ((pc == '/') && (c == '*'))
|
|
comment = 1;
|
|
else if ((pc == '*') && (c == '/') && (comment))
|
|
comment = 0;
|
|
}
|
|
if (!comment)
|
|
{
|
|
if ((!quote) && (c == '"'))
|
|
{
|
|
quote = 1;
|
|
i = 0;
|
|
}
|
|
else if ((quote) && (c == '"'))
|
|
{
|
|
line[i] = 0;
|
|
quote = 0;
|
|
if (context == 0)
|
|
{
|
|
/* Header */
|
|
sscanf(line, "%i %i %i %i", w, h, &ncolors, &cpp);
|
|
if (ncolors > 32766)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: XPM files wth colors > 32766 not supported\n");
|
|
free(line);
|
|
return NULL;
|
|
}
|
|
if (cpp > 5)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: XPM files with characters per pixel > 5 not supported\n");
|
|
free(line);
|
|
return NULL;
|
|
}
|
|
if (*w > 32767)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n");
|
|
free(line);
|
|
return NULL;
|
|
}
|
|
if (*h > 32767)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n");
|
|
free(line);
|
|
return NULL;
|
|
}
|
|
cmap = malloc(sizeof(struct _cmap) * ncolors);
|
|
|
|
if (!cmap)
|
|
{
|
|
free(line);
|
|
return NULL;
|
|
}
|
|
/* SAFE -- Check for w,h in earlier code */
|
|
data = malloc(*w ** h * 3);
|
|
if (!data)
|
|
{
|
|
free(cmap);
|
|
free(line);
|
|
return NULL;
|
|
}
|
|
ptr = data;
|
|
end = ptr + (*w ** h * 3);
|
|
j = 0;
|
|
context++;
|
|
}
|
|
else if (context == 1)
|
|
{
|
|
/* Color Table */
|
|
if (j < ncolors)
|
|
{
|
|
int slen;
|
|
int hascolor, iscolor;
|
|
|
|
iscolor = 0;
|
|
hascolor = 0;
|
|
tok[0] = 0;
|
|
col[0] = 0;
|
|
s[0] = 0;
|
|
len = strlen(line);
|
|
strncpy(cmap[j].str, line, cpp);
|
|
cmap[j].str[cpp] = 0;
|
|
cmap[j].r = -1;
|
|
cmap[j].transp = 0;
|
|
for (k = cpp; k < len; k++)
|
|
{
|
|
if (line[k] != ' ')
|
|
{
|
|
s[0] = 0;
|
|
sscanf(&line[k], "%256s", s);
|
|
slen = strlen(s);
|
|
k += slen;
|
|
if (!strcmp(s, "c"))
|
|
iscolor = 1;
|
|
if ((!strcmp(s, "m")) || (!strcmp(s, "s")) ||
|
|
(!strcmp(s, "g4")) || (!strcmp(s, "g")) ||
|
|
(!strcmp(s, "c")) || (k >= len))
|
|
{
|
|
if (k >= len)
|
|
{
|
|
if (col[0])
|
|
strcat(col, " ");
|
|
if (strlen(col) + strlen(s) < sizeof(col))
|
|
strcat(col, s);
|
|
}
|
|
if (col[0])
|
|
{
|
|
if (!strcasecmp(col, "none"))
|
|
{
|
|
transp = 1;
|
|
cmap[j].transp = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((((cmap[j].r < 0) ||
|
|
(!strcmp(tok, "c"))) &&
|
|
(!hascolor)))
|
|
{
|
|
XParseColor(id->x.disp,
|
|
id->x.root_cmap,
|
|
col, &xcol);
|
|
cmap[j].r = xcol.red >> 8;
|
|
cmap[j].g = xcol.green >> 8;
|
|
cmap[j].b = xcol.blue >> 8;
|
|
if ((cmap[j].r == 255) &&
|
|
(cmap[j].g == 0) &&
|
|
(cmap[j].b == 255))
|
|
cmap[j].r = 254;
|
|
if (iscolor)
|
|
hascolor = 1;
|
|
}
|
|
}
|
|
}
|
|
strcpy(tok, s);
|
|
col[0] = 0;
|
|
}
|
|
else
|
|
{
|
|
if (col[0])
|
|
strcat(col, " ");
|
|
strcat(col, s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
j++;
|
|
if (j >= ncolors)
|
|
{
|
|
if (cpp == 1)
|
|
for (i = 0; i < ncolors; i++)
|
|
lookup[(int)cmap[i].str[0] - 32][0] = i;
|
|
if (cpp == 2)
|
|
for (i = 0; i < ncolors; i++)
|
|
lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i;
|
|
context++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Image Data */
|
|
i = 0;
|
|
if (cpp == 0)
|
|
{
|
|
/* Chars per pixel = 0? well u never know */
|
|
}
|
|
if (cpp == 1)
|
|
{
|
|
if (transp)
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i];
|
|
if (cmap[lookup[(int)col[0] - 32][0]].transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i];
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][0]].b;
|
|
}
|
|
}
|
|
}
|
|
else if (cpp == 2)
|
|
{
|
|
if (transp)
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i++];
|
|
col[1] = line[i];
|
|
if (cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
col[0] = line[i++];
|
|
col[1] = line[i];
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].r;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].g;
|
|
*ptr++ = (unsigned char)cmap[lookup[(int)col[0] - 32][(int)col[1] - 32]].b;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (transp)
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
for (j = 0; j < cpp; j++, i++)
|
|
{
|
|
col[j] = line[i];
|
|
}
|
|
col[j] = 0;
|
|
i--;
|
|
for (j = 0; j < ncolors; j++)
|
|
{
|
|
if (!strcmp(col, cmap[j].str))
|
|
{
|
|
if (cmap[j].transp)
|
|
{
|
|
*ptr++ = 255;
|
|
*ptr++ = 0;
|
|
*ptr++ = 255;
|
|
}
|
|
else
|
|
{
|
|
*ptr++ = (unsigned char)cmap[j].r;
|
|
*ptr++ = (unsigned char)cmap[j].g;
|
|
*ptr++ = (unsigned char)cmap[j].b;
|
|
}
|
|
j = ncolors;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; ((i < 65536) && (ptr < end) && (line[i])); i++)
|
|
{
|
|
for (j = 0; j < cpp; j++, i++)
|
|
{
|
|
col[j] = line[i];
|
|
}
|
|
col[j] = 0;
|
|
i--;
|
|
for (j = 0; j < ncolors; j++)
|
|
{
|
|
if (!strcmp(col, cmap[j].str))
|
|
{
|
|
*ptr++ = (unsigned char)cmap[j].r;
|
|
*ptr++ = (unsigned char)cmap[j].g;
|
|
*ptr++ = (unsigned char)cmap[j].b;
|
|
j = ncolors;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* Scan in line from XPM file */
|
|
if ((!comment) && (quote) && (c != '"'))
|
|
{
|
|
if (c < 32)
|
|
c = 32;
|
|
else if (c > 127)
|
|
c = 127;
|
|
line[i++] = c;
|
|
}
|
|
if (i >= lsz)
|
|
{
|
|
lsz += 256;
|
|
line = realloc(line, lsz);
|
|
if(line == NULL)
|
|
{
|
|
free(cmap);
|
|
return NULL;
|
|
}
|
|
}
|
|
if ((ptr) && ((ptr - data) >= *w ** h * 3))
|
|
done = 1;
|
|
}
|
|
if (transp)
|
|
*t = 1;
|
|
else
|
|
*t = 0;
|
|
free(cmap);
|
|
free(line);
|
|
return data;
|
|
}
|
|
|
|
unsigned char *
|
|
_LoadPPM(ImlibData * id, FILE * f, int *w, int *h)
|
|
{
|
|
int done;
|
|
unsigned char *ptr;
|
|
unsigned char chr;
|
|
char s[256];
|
|
int a, b, i, j;
|
|
int color, scale, ascii, bw;
|
|
|
|
a = b = scale = ascii = bw = color = 0;
|
|
fgets(s, 256, f);
|
|
s[2] = 0;
|
|
if (!strcmp(s, "P6"))
|
|
color = 1;
|
|
else if (!strcmp(s, "P5"))
|
|
color = 0;
|
|
else if (!strcmp(s, "P4"))
|
|
bw = 1;
|
|
else if (!strcmp(s, "P3"))
|
|
{
|
|
color = 1;
|
|
ascii = 1;
|
|
}
|
|
else if (!strcmp(s, "P2"))
|
|
{
|
|
ascii = 1;
|
|
}
|
|
else if (!strcmp(s, "P1"))
|
|
{
|
|
ascii = 1;
|
|
bw = 1;
|
|
}
|
|
else
|
|
return NULL;
|
|
done = 1;
|
|
ptr = NULL;
|
|
while (done)
|
|
{
|
|
if (fgets(s, 256, f) == NULL)
|
|
break;
|
|
|
|
if (s[0] != '#')
|
|
{
|
|
done = 0;
|
|
sscanf(s, "%i %i", w, h);
|
|
a = *w;
|
|
b = *h;
|
|
if (a > 32767)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n");
|
|
return NULL;
|
|
}
|
|
if (b > 32767)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n");
|
|
return NULL;
|
|
}
|
|
if (!bw)
|
|
{
|
|
fgets(s, 256, f);
|
|
sscanf(s, "%i", &scale);
|
|
}
|
|
else
|
|
scale = 99999;
|
|
ptr = (unsigned char *)_imlib_malloc_image(a, b);
|
|
if (!ptr)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for RGB data in file");
|
|
return ptr;
|
|
}
|
|
if ((color) && (!ascii) && (!bw))
|
|
{
|
|
fread(ptr, a * b * 3, 1, f);
|
|
}
|
|
else if ((!color) && (!ascii) && (!bw))
|
|
{
|
|
b = (a * b * 3);
|
|
a = 0;
|
|
while ((fread(&chr, 1, 1, f)) && (a < b))
|
|
{
|
|
ptr[a++] = chr;
|
|
ptr[a++] = chr;
|
|
ptr[a++] = chr;
|
|
}
|
|
}
|
|
else if ((!color) && (!ascii) && (bw))
|
|
{
|
|
b = (a * b * 3);
|
|
a = 0;
|
|
j = 0;
|
|
while ((fread(&chr, 1, 1, f)) && (a < b))
|
|
{
|
|
for (i = 7; i >= 0; i--)
|
|
{
|
|
j++;
|
|
if (j <= *w)
|
|
{
|
|
if (chr & (1 << i))
|
|
{
|
|
ptr[a++] = 0;
|
|
ptr[a++] = 0;
|
|
ptr[a++] = 0;
|
|
}
|
|
else
|
|
{
|
|
ptr[a++] = 255;
|
|
ptr[a++] = 255;
|
|
ptr[a++] = 255;
|
|
}
|
|
}
|
|
}
|
|
if (j >= *w)
|
|
j = 0;
|
|
}
|
|
}
|
|
else if ((color) && (ascii) && (!bw))
|
|
{
|
|
b = (a * b * 3);
|
|
a = 0;
|
|
i = 0;
|
|
if (scale != 255)
|
|
{
|
|
while ((fread(&chr, 1, 1, f)) && (a < b))
|
|
{
|
|
s[i++] = chr;
|
|
if (!isdigit(chr))
|
|
{
|
|
s[i - 1] = 0;
|
|
if ((i > 1) && (isdigit(s[i - 2])))
|
|
{
|
|
ptr[a++] = ((atoi(s)) * 255) / scale;
|
|
}
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ((fread(&chr, 1, 1, f)) && (a < b))
|
|
{
|
|
s[i++] = chr;
|
|
if (!isdigit(chr))
|
|
{
|
|
s[i - 1] = 0;
|
|
if ((i > 1) && (isdigit(s[i - 2])))
|
|
{
|
|
ptr[a++] = atoi(s);
|
|
}
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
else if ((!color) && (ascii) && (!bw))
|
|
{
|
|
b = (a * b * 3);
|
|
a = 0;
|
|
i = 0;
|
|
if (scale != 255)
|
|
{
|
|
while ((fread(&chr, 1, 1, f)) && (a < b))
|
|
{
|
|
s[i++] = chr;
|
|
if (!isdigit(chr))
|
|
{
|
|
s[i - 1] = 0;
|
|
if ((i > 1) && (isdigit(s[i - 2])))
|
|
{
|
|
ptr[a++] = ((atoi(s)) * 255) / scale;
|
|
ptr[a++] = ptr[a - 1];
|
|
ptr[a++] = ptr[a - 1];
|
|
}
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ((fread(&chr, 1, 1, f)) && (a < b))
|
|
{
|
|
s[i++] = chr;
|
|
if (!isdigit(chr))
|
|
{
|
|
s[i - 1] = 0;
|
|
if ((i > 1) && (isdigit(s[i - 2])))
|
|
{
|
|
ptr[a++] = atoi(s);
|
|
ptr[a++] = ptr[a - 1];
|
|
ptr[a++] = ptr[a - 1];
|
|
}
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ((!color) && (ascii) && (bw))
|
|
{
|
|
}
|
|
}
|
|
}
|
|
if (!ptr)
|
|
return NULL;
|
|
if (scale == 0)
|
|
{
|
|
free(ptr);
|
|
return NULL;
|
|
}
|
|
if ((scale < 255) && (!ascii))
|
|
{
|
|
int rot;
|
|
unsigned char *po;
|
|
|
|
if (scale <= 1)
|
|
rot = 7;
|
|
else if (scale <= 3)
|
|
rot = 6;
|
|
else if (scale <= 7)
|
|
rot = 5;
|
|
else if (scale <= 15)
|
|
rot = 4;
|
|
else if (scale <= 31)
|
|
rot = 3;
|
|
else if (scale <= 63)
|
|
rot = 2;
|
|
else
|
|
rot = 1;
|
|
|
|
if (rot > 0)
|
|
{
|
|
po = ptr;
|
|
while (po < (ptr + (*w ** h * 3)))
|
|
{
|
|
*po++ <<= rot;
|
|
*po++ <<= rot;
|
|
*po++ <<= rot;
|
|
}
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
int
|
|
ispnm(FILE *f)
|
|
{
|
|
char buf[8];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fgets(buf, 8, f);
|
|
rewind(f);
|
|
if (!strcmp("P6", buf))
|
|
return 1;
|
|
if (!strcmp("P5", buf))
|
|
return 1;
|
|
if (!strcmp("P4", buf))
|
|
return 1;
|
|
if (!strcmp("P3", buf))
|
|
return 1;
|
|
if (!strcmp("P2", buf))
|
|
return 1;
|
|
if (!strcmp("P1", buf))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
isjpeg(FILE *f)
|
|
{
|
|
unsigned char buf[8];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fread(buf, 1, 2, f);
|
|
rewind(f);
|
|
if ((buf[0] == 0xff) && (buf[1] == 0xd8))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
ispng(FILE *f)
|
|
{
|
|
#ifdef HAVE_LIBPNG
|
|
unsigned char buf[8];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fread(buf, 1, 8, f);
|
|
rewind(f);
|
|
return (int)png_check_sig(buf, 8);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int
|
|
istiff(FILE *f)
|
|
{
|
|
char buf[8];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fgets(buf, 5, f);
|
|
rewind(f);
|
|
if ((buf[0] == 'M') && (buf[1] == 'M') && (buf[2] == 0x00) && (buf[3] == 0x2a))
|
|
return 1;
|
|
if ((buf[0] == 'I') && (buf[1] == 'I') && (buf[2] == 0x2a) && (buf[3] == 0x00))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
iseim(FILE *f)
|
|
{
|
|
char buf[8];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fread(buf, 1, 4, f);
|
|
rewind(f);
|
|
buf[4] = 0;
|
|
if (!strncmp("EIM ", buf, 4))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
isgif(FILE *f)
|
|
{
|
|
char buf[8];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fread(buf, 1, 4, f);
|
|
rewind(f);
|
|
buf[4] = 0;
|
|
if (!strcmp("GIF8", buf))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
isxpm(FILE *f)
|
|
{
|
|
char buf[11];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fread(buf, 1, 9, f);
|
|
rewind(f);
|
|
buf[9] = 0;
|
|
if (!strcmp("/* XPM */", buf))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
isbmp(FILE *f)
|
|
{
|
|
char buf[3];
|
|
|
|
if (!f)
|
|
return 0;
|
|
fread(buf, 1, 2, f);
|
|
rewind(f);
|
|
buf[2] = 0;
|
|
if (!strcmp("BM", buf))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
ImlibImage *
|
|
Imlib_load_image(ImlibData * id, char *file)
|
|
{
|
|
int w, h;
|
|
unsigned char *data;
|
|
ImlibImage *im;
|
|
char s[4096];
|
|
char fil[4096];
|
|
char *iden;
|
|
char *e;
|
|
char cmd[4096];
|
|
FILE *p;
|
|
int eim;
|
|
int fmt;
|
|
int trans;
|
|
|
|
eim = 0;
|
|
fmt = 0;
|
|
data = NULL;
|
|
|
|
if (!file)
|
|
return NULL;
|
|
if (id->cache.on_image)
|
|
if ((im = find_image(id, file)))
|
|
{
|
|
if (im->rgb_width == 0 || im->rgb_height == 0)
|
|
{
|
|
Imlib_destroy_image(id, im);
|
|
return NULL;
|
|
}
|
|
else
|
|
return im;
|
|
}
|
|
if (!strcmp(file,"-")) {
|
|
p = stdin;
|
|
}
|
|
else {
|
|
p = fopen(file, "rb");
|
|
}
|
|
if (!p)
|
|
return NULL;
|
|
strncpy(fil, file, sizeof(fil));
|
|
iden = _SplitID(fil);
|
|
e = _GetExtension(fil);
|
|
|
|
if (ispnm(p))
|
|
{
|
|
fmt = 0;
|
|
}
|
|
else if (isjpeg(p))
|
|
{
|
|
fmt = 2;
|
|
}
|
|
else if (istiff(p))
|
|
{
|
|
fmt = 3;
|
|
}
|
|
else if (iseim(p))
|
|
{
|
|
eim = 1;
|
|
fmt = 9999;
|
|
}
|
|
else if (isxpm(p))
|
|
{
|
|
fmt = 5;
|
|
}
|
|
else if (ispng(p))
|
|
{
|
|
fmt = 1;
|
|
}
|
|
else if (isgif(p))
|
|
{
|
|
fmt = 4;
|
|
}
|
|
else if (isbmp(p))
|
|
{
|
|
fmt = 6;
|
|
}
|
|
|
|
trans = 0;
|
|
if ((!eim) && (!data))
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case 6:
|
|
data = _LoadBMP(id, p, &w, &h, &trans);
|
|
break;
|
|
case 5:
|
|
data = _LoadXPM(id, p, &w, &h, &trans);
|
|
break;
|
|
#ifdef HAVE_LIBGIF
|
|
case 4:
|
|
data = _LoadGIF(id, p, &w, &h, &trans);
|
|
break;
|
|
#endif
|
|
#ifdef HAVE_LIBTIFF
|
|
case 3:
|
|
data = _LoadTIFF(id, p, file, &w, &h, &trans);
|
|
break;
|
|
#endif
|
|
#ifdef HAVE_LIBJPEG
|
|
case 2:
|
|
data = _LoadJPEG(id, p, &w, &h);
|
|
break;
|
|
#endif
|
|
#ifdef HAVE_LIBPNG
|
|
case 1:
|
|
data = _LoadPNG(id, p, &w, &h, &trans);
|
|
break;
|
|
#endif
|
|
default:
|
|
data = _LoadPPM(id, p, &w, &h);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (p != stdin)
|
|
fclose(p);
|
|
|
|
if ((!eim) && (!data))
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot load image: %s\n"
|
|
"All fallbacks failed.\n", fil);
|
|
return NULL;
|
|
}
|
|
|
|
if (!w || !h)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: zero image\n" );
|
|
if(data)
|
|
free(data);
|
|
return NULL;
|
|
}
|
|
|
|
im = (ImlibImage *) malloc(sizeof(ImlibImage));
|
|
if (!im)
|
|
{
|
|
fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for image structure\n");
|
|
if (data)
|
|
free(data);
|
|
return NULL;
|
|
}
|
|
im->alpha_data = NULL;
|
|
if (trans)
|
|
{
|
|
im->shape_color.r = 255;
|
|
im->shape_color.g = 0;
|
|
im->shape_color.b = 255;
|
|
}
|
|
else
|
|
{
|
|
im->shape_color.r = -1;
|
|
im->shape_color.g = -1;
|
|
im->shape_color.b = -1;
|
|
}
|
|
im->border.left = 0;
|
|
im->border.right = 0;
|
|
im->border.top = 0;
|
|
im->border.bottom = 0;
|
|
im->cache = 1;
|
|
im->rgb_data = data;
|
|
im->rgb_width = w;
|
|
im->rgb_height = h;
|
|
im->pixmap = 0;
|
|
im->shape_mask = 0;
|
|
if (eim)
|
|
{
|
|
char s1[256], s2[256];
|
|
int num, size;
|
|
int r, g, b;
|
|
int br, bl, bt, bb;
|
|
|
|
/* Load Native-as-can-be EIM format (Enlightenment IMlib format) */
|
|
if (!strcmp(file,"-"))
|
|
p = stdin;
|
|
else {
|
|
#ifndef __EMX__
|
|
p = fopen(file, "r");
|
|
#else
|
|
p = fopen(file, "rt");
|
|
#endif
|
|
}
|
|
|
|
if (!p)
|
|
{
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
fgets(s, 4096, p);
|
|
if ((s[0] != 'E') && (s[1] != 'I') && (s[2] != 'M') && (s[3] != ' '))
|
|
{
|
|
fclose(p);
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
sscanf(s, "%256s %i", s1, &num);
|
|
if (num <= 0)
|
|
{
|
|
fclose(p);
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
while (fgets(s, 4096, p))
|
|
{
|
|
sscanf(s, "%256s", s1);
|
|
if (!strcmp("IMAGE", s1))
|
|
{
|
|
sscanf(s, "%256s %i %256s %i %i %i %i %i %i %i %i %i", s1, &size,
|
|
s2, &w, &h, &r, &g, &b, &bl, &br, &bt, &bb);
|
|
if (!iden[0])
|
|
break;
|
|
else if (!strcmp(iden, s2))
|
|
break;
|
|
if (size > 0)
|
|
fseek(p, size, SEEK_CUR);
|
|
}
|
|
}
|
|
im->rgb_data = _imlib_malloc_image(w, h);
|
|
if (!im->rgb_data)
|
|
{
|
|
fclose(p);
|
|
free(im);
|
|
return NULL;
|
|
}
|
|
im->shape_color.r = r;
|
|
im->shape_color.g = g;
|
|
im->shape_color.b = b;
|
|
im->rgb_width = w;
|
|
im->rgb_height = h;
|
|
im->border.left = bl;
|
|
im->border.right = br;
|
|
im->border.top = bt;
|
|
im->border.bottom = bb;
|
|
fread(im->rgb_data, 1, w * h * 3, p);
|
|
fclose(p);
|
|
if (iden[0])
|
|
{
|
|
#ifndef __EMX__
|
|
strncat(fil, ":", sizeof(fil) - strlen(fil));
|
|
#else
|
|
strncat(fil, ";", sizeof(fil) - strlen(fil));
|
|
#endif
|
|
strncat(fil, iden, sizeof(fil) - strlen(fil));
|
|
}
|
|
}
|
|
im->mod.gamma = id->mod.gamma;
|
|
im->mod.brightness = id->mod.brightness;
|
|
im->mod.contrast = id->mod.contrast;
|
|
im->rmod.gamma = id->rmod.gamma;
|
|
im->rmod.brightness = id->rmod.brightness;
|
|
im->rmod.contrast = id->rmod.contrast;
|
|
im->gmod.gamma = id->gmod.gamma;
|
|
im->gmod.brightness = id->gmod.brightness;
|
|
im->gmod.contrast = id->gmod.contrast;
|
|
im->bmod.gamma = id->bmod.gamma;
|
|
im->bmod.brightness = id->bmod.brightness;
|
|
im->bmod.contrast = id->bmod.contrast;
|
|
im->filename = malloc(strlen(file) + 1);
|
|
if (im->filename)
|
|
strcpy(im->filename, file);
|
|
if ((id->cache.on_image) && (im))
|
|
add_image(id, im, fil);
|
|
calc_map_tables(id, im);
|
|
return im;
|
|
}
|
|
|
|
int
|
|
Imlib_save_image_to_eim(ImlibData * id, ImlibImage * im, char *file)
|
|
{
|
|
char fil[4096];
|
|
char *iden;
|
|
FILE *f;
|
|
int size;
|
|
|
|
if ((!id) || (!im) || (!file))
|
|
return 0;
|
|
strncpy(fil, file, sizeof(fil));
|
|
iden = _SplitID(fil);
|
|
if (!iden[0])
|
|
iden = "default";
|
|
f = fopen(fil, "w");
|
|
if (!f)
|
|
return 0;
|
|
|
|
size = im->rgb_width * im->rgb_height * 3;
|
|
fprintf(f, "EIM 1\n");
|
|
fprintf(f, "IMAGE %i %s %i %i %i %i %i %i %i %i %i\n",
|
|
size,
|
|
iden,
|
|
im->rgb_width,
|
|
im->rgb_height,
|
|
im->shape_color.r,
|
|
im->shape_color.g,
|
|
im->shape_color.b,
|
|
im->border.left,
|
|
im->border.right,
|
|
im->border.top,
|
|
im->border.bottom);
|
|
if (fwrite(im->rgb_data, size, 1, f) != 1)
|
|
{
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
fclose(f);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
Imlib_add_image_to_eim(ImlibData * id, ImlibImage * im, char *file)
|
|
{
|
|
char fil[4096];
|
|
char *iden;
|
|
FILE *f;
|
|
int size;
|
|
|
|
if ((!id) || (!im) || (!file))
|
|
return 0;
|
|
strncpy(fil, file, sizeof(fil));
|
|
|
|
iden = _SplitID(file);
|
|
if (!iden[0])
|
|
strcpy(iden, "default");
|
|
|
|
f = fopen(fil, "a");
|
|
if (!f)
|
|
return 0;
|
|
|
|
size = im->rgb_width * im->rgb_height * 3;
|
|
fprintf(f, "IMAGE %i %s %i %i %i %i %i %i %i %i %i\n",
|
|
size,
|
|
iden,
|
|
im->rgb_width,
|
|
im->rgb_height,
|
|
im->shape_color.r,
|
|
im->shape_color.g,
|
|
im->shape_color.b,
|
|
im->border.left,
|
|
im->border.right,
|
|
im->border.top,
|
|
im->border.bottom);
|
|
|
|
if (fwrite(im->rgb_data, size, 1, f) != 1)
|
|
{
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
fclose(f);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
Imlib_save_image_to_ppm(ImlibData * id, ImlibImage * im, char *file)
|
|
{
|
|
FILE *f;
|
|
|
|
if ((!id) || (!im) || (!file))
|
|
return 0;
|
|
#ifndef __EMX__
|
|
f = fopen(file, "w");
|
|
#else
|
|
f = fopen(file, "wb");
|
|
#endif
|
|
|
|
if (!f)
|
|
return 0;
|
|
|
|
fprintf(f, "P6\n");
|
|
fprintf(f, "%i %i\n255\n",
|
|
im->rgb_width,
|
|
im->rgb_height);
|
|
if (fwrite(im->rgb_data, im->rgb_width * im->rgb_height * 3, 1, f) != 1)
|
|
{
|
|
fclose(f);
|
|
return 0;
|
|
}
|
|
fclose(f);
|
|
return 1;
|
|
}
|