#define FASTJPEG 1 /* =1 for temp quick jpeg 8bpp display */
|
#define FASTJPEG 1 /* =1 for temp quick jpeg 8bpp display */
|
#ifdef __ECOS
|
#ifdef __ECOS
|
// Why isn't this handled in the global config file?
|
// Why isn't this handled in the global config file?
|
#undef HAVE_MMAP
|
#undef HAVE_MMAP
|
#else
|
#else
|
#define HAVE_MMAP 1 /* =1 to use mmap if available */
|
#define HAVE_MMAP 1 /* =1 to use mmap if available */
|
#endif
|
#endif
|
|
|
#if defined(HAVE_FILEIO) /* temp for entire file*/
|
#if defined(HAVE_FILEIO) /* temp for entire file*/
|
|
|
/*
|
/*
|
* Copyright (c) 2000, 2001 Greg Haerr <greg@censoft.com>
|
* Copyright (c) 2000, 2001 Greg Haerr <greg@censoft.com>
|
* Portions Copyright (c) 2000 Martin Jolicoeur <martinj@visuaide.com>
|
* Portions Copyright (c) 2000 Martin Jolicoeur <martinj@visuaide.com>
|
* Portions Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
|
* Portions Copyright (c) 2000 Alex Holden <alex@linuxhacker.org>
|
* Portions Copyright (c) Independant JPEG group (ijg)
|
* Portions Copyright (c) Independant JPEG group (ijg)
|
*
|
*
|
* Image load/cache/resize/display routines
|
* Image load/cache/resize/display routines
|
*
|
*
|
* GIF, BMP, JPEG, PPM, PGM, PBM, PNG, and XPM formats are supported.
|
* GIF, BMP, JPEG, PPM, PGM, PBM, PNG, and XPM formats are supported.
|
* JHC: Instead of working with a file, we work with a buffer
|
* JHC: Instead of working with a file, we work with a buffer
|
* (either provided by the user or through mmap). This
|
* (either provided by the user or through mmap). This
|
* improves speed, and provides a mechanism by which the
|
* improves speed, and provides a mechanism by which the
|
* client can send image data directly to the engine
|
* client can send image data directly to the engine
|
*/
|
*/
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
|
|
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
#include <sys/mman.h>
|
#include <sys/mman.h>
|
#endif
|
#endif
|
|
|
#include "device.h"
|
#include "device.h"
|
#include "swap.h"
|
#include "swap.h"
|
|
|
/* cached image list*/
|
/* cached image list*/
|
typedef struct {
|
typedef struct {
|
MWLIST link; /* link list*/
|
MWLIST link; /* link list*/
|
int id; /* image id*/
|
int id; /* image id*/
|
PMWIMAGEHDR pimage; /* image data*/
|
PMWIMAGEHDR pimage; /* image data*/
|
PSD psd; /* FIXME shouldn't need this*/
|
PSD psd; /* FIXME shouldn't need this*/
|
} IMAGEITEM, *PIMAGEITEM;
|
} IMAGEITEM, *PIMAGEITEM;
|
|
|
static MWLISTHEAD imagehead; /* global image list*/
|
static MWLISTHEAD imagehead; /* global image list*/
|
static int nextimageid = 1;
|
static int nextimageid = 1;
|
|
|
typedef struct { /* structure for reading images from buffer */
|
typedef struct { /* structure for reading images from buffer */
|
void *start; /* The pointer to the beginning of the buffer */
|
void *start; /* The pointer to the beginning of the buffer */
|
int offset; /* The current offset within the buffer */
|
int offset; /* The current offset within the buffer */
|
int size; /* The total size of the buffer */
|
int size; /* The total size of the buffer */
|
} buffer_t;
|
} buffer_t;
|
|
|
|
|
static void ComputePitch(int bpp, int width, int *pitch, int *bytesperpixel);
|
static void ComputePitch(int bpp, int width, int *pitch, int *bytesperpixel);
|
#if defined(HAVE_BMP_SUPPORT)
|
#if defined(HAVE_BMP_SUPPORT)
|
static int LoadBMP(buffer_t *src, PMWIMAGEHDR pimage);
|
static int LoadBMP(buffer_t *src, PMWIMAGEHDR pimage);
|
#endif
|
#endif
|
#if defined(HAVE_JPEG_SUPPORT)
|
#if defined(HAVE_JPEG_SUPPORT)
|
static int LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd,
|
static int LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd,
|
MWBOOL fast_grayscale);
|
MWBOOL fast_grayscale);
|
#endif
|
#endif
|
#if defined(HAVE_PNG_SUPPORT)
|
#if defined(HAVE_PNG_SUPPORT)
|
static int LoadPNG(buffer_t *src, PMWIMAGEHDR pimage);
|
static int LoadPNG(buffer_t *src, PMWIMAGEHDR pimage);
|
#endif
|
#endif
|
#if defined(HAVE_GIF_SUPPORT)
|
#if defined(HAVE_GIF_SUPPORT)
|
static int LoadGIF(buffer_t *src, PMWIMAGEHDR pimage);
|
static int LoadGIF(buffer_t *src, PMWIMAGEHDR pimage);
|
#endif
|
#endif
|
#if defined(HAVE_PNM_SUPPORT)
|
#if defined(HAVE_PNM_SUPPORT)
|
static int LoadPNM(buffer_t *src, PMWIMAGEHDR pimage);
|
static int LoadPNM(buffer_t *src, PMWIMAGEHDR pimage);
|
#endif
|
#endif
|
#if defined(HAVE_XPM_SUPPORT)
|
#if defined(HAVE_XPM_SUPPORT)
|
static int LoadXPM(buffer_t *src, PMWIMAGEHDR pimage, PSD psd) ;
|
static int LoadXPM(buffer_t *src, PMWIMAGEHDR pimage, PSD psd) ;
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* Buffered input functions to replace stdio functions
|
* Buffered input functions to replace stdio functions
|
*/
|
*/
|
static void
|
static void
|
binit(void *in, int size, buffer_t *dest)
|
binit(void *in, int size, buffer_t *dest)
|
{
|
{
|
dest->start = in;
|
dest->start = in;
|
dest->offset = 0;
|
dest->offset = 0;
|
dest->size = size;
|
dest->size = size;
|
}
|
}
|
|
|
static int
|
static int
|
bseek(buffer_t *buffer, int offset, int whence)
|
bseek(buffer_t *buffer, int offset, int whence)
|
{
|
{
|
int new;
|
int new;
|
|
|
switch(whence) {
|
switch(whence) {
|
case SEEK_SET:
|
case SEEK_SET:
|
if (offset >= buffer->size || offset < 0)
|
if (offset >= buffer->size || offset < 0)
|
return(-1);
|
return(-1);
|
buffer->offset = offset;
|
buffer->offset = offset;
|
return(0);
|
return(0);
|
|
|
case SEEK_CUR:
|
case SEEK_CUR:
|
new = buffer->offset + offset;
|
new = buffer->offset + offset;
|
if (new >= buffer->size || new < 0)
|
if (new >= buffer->size || new < 0)
|
return(-1);
|
return(-1);
|
buffer->offset = new;
|
buffer->offset = new;
|
return(0);
|
return(0);
|
|
|
case SEEK_END:
|
case SEEK_END:
|
if (offset >= buffer->size || offset > 0)
|
if (offset >= buffer->size || offset > 0)
|
return(-1);
|
return(-1);
|
buffer->offset = (buffer->size - 1) - offset;
|
buffer->offset = (buffer->size - 1) - offset;
|
return(0);
|
return(0);
|
|
|
default:
|
default:
|
return(-1);
|
return(-1);
|
}
|
}
|
}
|
}
|
|
|
static int
|
static int
|
bread(buffer_t *buffer, void *dest, int size)
|
bread(buffer_t *buffer, void *dest, int size)
|
{
|
{
|
int copysize = size;
|
int copysize = size;
|
|
|
if (buffer->offset == buffer->size)
|
if (buffer->offset == buffer->size)
|
return(0);
|
return(0);
|
|
|
if (buffer->offset + size > buffer->size)
|
if (buffer->offset + size > buffer->size)
|
copysize = (buffer->size - buffer->offset);
|
copysize = (buffer->size - buffer->offset);
|
|
|
memcpy((void *)dest, (void *)(buffer->start + buffer->offset),copysize);
|
memcpy((void *)dest, (void *)(buffer->start + buffer->offset),copysize);
|
|
|
buffer->offset += copysize;
|
buffer->offset += copysize;
|
return(copysize);
|
return(copysize);
|
}
|
}
|
|
|
static int
|
static int
|
bgetc(buffer_t *buffer)
|
bgetc(buffer_t *buffer)
|
{
|
{
|
int ch;
|
int ch;
|
|
|
if (buffer->offset == buffer->size)
|
if (buffer->offset == buffer->size)
|
return(EOF);
|
return(EOF);
|
|
|
ch = *((unsigned char *) (buffer->start + buffer->offset));
|
ch = *((unsigned char *) (buffer->start + buffer->offset));
|
buffer->offset++;
|
buffer->offset++;
|
return(ch);
|
return(ch);
|
}
|
}
|
|
|
static char *
|
static char *
|
bgets(buffer_t *buffer, char *dest, int size)
|
bgets(buffer_t *buffer, char *dest, int size)
|
{
|
{
|
int i,o;
|
int i,o;
|
int copysize = size - 1;
|
int copysize = size - 1;
|
|
|
if (buffer->offset == buffer->size)
|
if (buffer->offset == buffer->size)
|
return(0);
|
return(0);
|
|
|
if (buffer->offset + copysize > buffer->size)
|
if (buffer->offset + copysize > buffer->size)
|
copysize = buffer->size - buffer->offset;
|
copysize = buffer->size - buffer->offset;
|
|
|
for(o=0, i=buffer->offset; i < buffer->offset + copysize; i++, o++) {
|
for(o=0, i=buffer->offset; i < buffer->offset + copysize; i++, o++) {
|
dest[o] = *((char *) (buffer->start + i));
|
dest[o] = *((char *) (buffer->start + i));
|
if (dest[o] == '\n')
|
if (dest[o] == '\n')
|
break;
|
break;
|
}
|
}
|
|
|
buffer->offset = i + 1;
|
buffer->offset = i + 1;
|
dest[o + 1] = 0;
|
dest[o + 1] = 0;
|
|
|
return(dest);
|
return(dest);
|
}
|
}
|
|
|
static int
|
static int
|
beof(buffer_t *buffer)
|
beof(buffer_t *buffer)
|
{
|
{
|
return (buffer->offset == buffer->size);
|
return (buffer->offset == buffer->size);
|
}
|
}
|
|
|
/*
|
/*
|
* Image decoding and display
|
* Image decoding and display
|
* NOTE: This routine and APIs will change in subsequent releases.
|
* NOTE: This routine and APIs will change in subsequent releases.
|
*
|
*
|
* Decodes and loads a graphics file, then resizes to width/height,
|
* Decodes and loads a graphics file, then resizes to width/height,
|
* then displays image at x, y
|
* then displays image at x, y
|
* If width/height == -1, don't resize, use image size.
|
* If width/height == -1, don't resize, use image size.
|
* Clipping is not currently supported, just stretch/shrink to fit.
|
* Clipping is not currently supported, just stretch/shrink to fit.
|
*
|
*
|
*/
|
*/
|
|
|
static int GdDecodeImage(PSD psd, buffer_t *src, int flags);
|
static int GdDecodeImage(PSD psd, buffer_t *src, int flags);
|
|
|
int
|
int
|
GdLoadImageFromBuffer(PSD psd, void *buffer, int size, int flags)
|
GdLoadImageFromBuffer(PSD psd, void *buffer, int size, int flags)
|
{
|
{
|
buffer_t src;
|
buffer_t src;
|
binit(buffer, size, &src);
|
binit(buffer, size, &src);
|
|
|
return(GdDecodeImage(psd, &src, flags));
|
return(GdDecodeImage(psd, &src, flags));
|
}
|
}
|
|
|
void
|
void
|
GdDrawImageFromBuffer(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width,
|
GdDrawImageFromBuffer(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width,
|
MWCOORD height, void *buffer, int size, int flags)
|
MWCOORD height, void *buffer, int size, int flags)
|
{
|
{
|
int id;
|
int id;
|
buffer_t src;
|
buffer_t src;
|
|
|
binit(buffer, size, &src);
|
binit(buffer, size, &src);
|
id = GdDecodeImage(psd, &src, flags);
|
id = GdDecodeImage(psd, &src, flags);
|
|
|
if (id) {
|
if (id) {
|
GdDrawImageToFit(psd, x, y, width, height, id);
|
GdDrawImageToFit(psd, x, y, width, height, id);
|
GdFreeImage(id);
|
GdFreeImage(id);
|
}
|
}
|
}
|
}
|
|
|
void
|
void
|
GdDrawImageFromFile(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width,
|
GdDrawImageFromFile(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width,
|
MWCOORD height, char *path, int flags)
|
MWCOORD height, char *path, int flags)
|
{
|
{
|
int id;
|
int id;
|
|
|
id = GdLoadImageFromFile(psd, path, flags);
|
id = GdLoadImageFromFile(psd, path, flags);
|
if (id) {
|
if (id) {
|
GdDrawImageToFit(psd, x, y, width, height, id);
|
GdDrawImageToFit(psd, x, y, width, height, id);
|
GdFreeImage(id);
|
GdFreeImage(id);
|
}
|
}
|
}
|
}
|
|
|
int
|
int
|
GdLoadImageFromFile(PSD psd, char *path, int flags)
|
GdLoadImageFromFile(PSD psd, char *path, int flags)
|
{
|
{
|
int fd, id;
|
int fd, id;
|
struct stat s;
|
struct stat s;
|
void *buffer = 0;
|
void *buffer = 0;
|
buffer_t src;
|
buffer_t src;
|
|
|
fd = open(path, O_RDONLY);
|
fd = open(path, O_RDONLY);
|
if (fd <= 0) {
|
if (fd <= 0) {
|
EPRINTF("GdLoadImageFromFile: can't open image: %s\n", path);
|
EPRINTF("GdLoadImageFromFile: can't open image: %s\n", path);
|
return(0);
|
return(0);
|
}
|
}
|
|
|
fstat(fd, &s);
|
fstat(fd, &s);
|
|
|
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
buffer = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
buffer = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
|
if (!buffer) {
|
if (!buffer) {
|
EPRINTF("GdLoadImageFromFile: Couldn't map image %s\n", path);
|
EPRINTF("GdLoadImageFromFile: Couldn't map image %s\n", path);
|
close(fd);
|
close(fd);
|
return(0);
|
return(0);
|
}
|
}
|
#else
|
#else
|
buffer = malloc(s.st_size);
|
buffer = malloc(s.st_size);
|
if (!buffer) {
|
if (!buffer) {
|
EPRINTF("GdLoadImageFromFile: Couldn't load image %s\n", path);
|
EPRINTF("GdLoadImageFromFile: Couldn't load image %s\n", path);
|
close(fd);
|
close(fd);
|
return(0);
|
return(0);
|
}
|
}
|
|
|
if (read(fd, buffer, s.st_size) != s.st_size) {
|
if (read(fd, buffer, s.st_size) != s.st_size) {
|
EPRINTF("GdLoadImageFromFile: Couldn't load image %s\n", path);
|
EPRINTF("GdLoadImageFromFile: Couldn't load image %s\n", path);
|
close(fd);
|
close(fd);
|
return(0);
|
return(0);
|
}
|
}
|
#endif
|
#endif
|
|
|
binit(buffer, s.st_size, &src);
|
binit(buffer, s.st_size, &src);
|
id = GdDecodeImage(psd, &src, flags);
|
id = GdDecodeImage(psd, &src, flags);
|
|
|
#ifdef HAVE_MMAP
|
#ifdef HAVE_MMAP
|
munmap(buffer, s.st_size);
|
munmap(buffer, s.st_size);
|
#else
|
#else
|
free(buffer);
|
free(buffer);
|
#endif
|
#endif
|
|
|
close(fd);
|
close(fd);
|
return(id);
|
return(id);
|
}
|
}
|
|
|
static int
|
static int
|
GdDecodeImage(PSD psd, buffer_t * src, int flags)
|
GdDecodeImage(PSD psd, buffer_t * src, int flags)
|
{
|
{
|
int loadOK = 0;
|
int loadOK = 0;
|
PMWIMAGEHDR pimage;
|
PMWIMAGEHDR pimage;
|
PIMAGEITEM pItem;
|
PIMAGEITEM pItem;
|
|
|
/* allocate image struct*/
|
/* allocate image struct*/
|
pimage = (PMWIMAGEHDR)malloc(sizeof(MWIMAGEHDR));
|
pimage = (PMWIMAGEHDR)malloc(sizeof(MWIMAGEHDR));
|
if(!pimage) {
|
if(!pimage) {
|
return 0;
|
return 0;
|
}
|
}
|
pimage->imagebits = NULL;
|
pimage->imagebits = NULL;
|
pimage->palette = NULL;
|
pimage->palette = NULL;
|
pimage->transcolor = -1L;
|
pimage->transcolor = -1L;
|
|
|
#if defined(HAVE_BMP_SUPPORT)
|
#if defined(HAVE_BMP_SUPPORT)
|
if (loadOK == 0)
|
if (loadOK == 0)
|
loadOK = LoadBMP(src, pimage);
|
loadOK = LoadBMP(src, pimage);
|
#endif
|
#endif
|
#if defined(HAVE_GIF_SUPPORT)
|
#if defined(HAVE_GIF_SUPPORT)
|
if (loadOK == 0)
|
if (loadOK == 0)
|
loadOK = LoadGIF(src, pimage);
|
loadOK = LoadGIF(src, pimage);
|
#endif
|
#endif
|
#if defined(HAVE_JPEG_SUPPORT)
|
#if defined(HAVE_JPEG_SUPPORT)
|
if (loadOK == 0)
|
if (loadOK == 0)
|
loadOK = LoadJPEG(src, pimage, psd, flags);
|
loadOK = LoadJPEG(src, pimage, psd, flags);
|
#endif
|
#endif
|
#if defined(HAVE_PNG_SUPPORT)
|
#if defined(HAVE_PNG_SUPPORT)
|
if (loadOK == 0)
|
if (loadOK == 0)
|
loadOK = LoadPNG(src, pimage);
|
loadOK = LoadPNG(src, pimage);
|
#endif
|
#endif
|
#if defined(HAVE_PNM_SUPPORT)
|
#if defined(HAVE_PNM_SUPPORT)
|
if(loadOK == 0)
|
if(loadOK == 0)
|
loadOK = LoadPNM(src, pimage);
|
loadOK = LoadPNM(src, pimage);
|
#endif
|
#endif
|
#if defined(HAVE_XPM_SUPPORT)
|
#if defined(HAVE_XPM_SUPPORT)
|
if (loadOK == 0)
|
if (loadOK == 0)
|
loadOK = LoadXPM(src, pimage, psd);
|
loadOK = LoadXPM(src, pimage, psd);
|
#endif
|
#endif
|
|
|
if (loadOK == 0) {
|
if (loadOK == 0) {
|
EPRINTF("GdLoadImageFromFile: unknown image type:\n");
|
EPRINTF("GdLoadImageFromFile: unknown image type:\n");
|
// EPRINTF("GdLoadImageFromFile: unknown image type: \n", path);
|
// EPRINTF("GdLoadImageFromFile: unknown image type: \n", path);
|
goto err; /* image loading error*/
|
goto err; /* image loading error*/
|
}
|
}
|
if (loadOK != 1)
|
if (loadOK != 1)
|
goto err; /* image loading error*/
|
goto err; /* image loading error*/
|
|
|
/* allocate id*/
|
/* allocate id*/
|
pItem = GdItemNew(IMAGEITEM);
|
pItem = GdItemNew(IMAGEITEM);
|
if (!pItem)
|
if (!pItem)
|
goto err;
|
goto err;
|
pItem->id = nextimageid++;
|
pItem->id = nextimageid++;
|
pItem->pimage = pimage;
|
pItem->pimage = pimage;
|
pItem->psd = psd;
|
pItem->psd = psd;
|
GdListAdd(&imagehead, &pItem->link);
|
GdListAdd(&imagehead, &pItem->link);
|
|
|
return pItem->id;
|
return pItem->id;
|
|
|
err:
|
err:
|
free(pimage);
|
free(pimage);
|
return 0; /* image loading error*/
|
return 0; /* image loading error*/
|
}
|
}
|
|
|
static PIMAGEITEM
|
static PIMAGEITEM
|
findimage(int id)
|
findimage(int id)
|
{
|
{
|
PMWLIST p;
|
PMWLIST p;
|
PIMAGEITEM pimagelist;
|
PIMAGEITEM pimagelist;
|
|
|
for (p=imagehead.head; p; p=p->next) {
|
for (p=imagehead.head; p; p=p->next) {
|
pimagelist = GdItemAddr(p, IMAGEITEM, link);
|
pimagelist = GdItemAddr(p, IMAGEITEM, link);
|
if (pimagelist->id == id)
|
if (pimagelist->id == id)
|
return pimagelist;
|
return pimagelist;
|
}
|
}
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
void
|
void
|
GdDrawImageToFit(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
GdDrawImageToFit(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height,
|
int id)
|
int id)
|
{
|
{
|
PIMAGEITEM pItem;
|
PIMAGEITEM pItem;
|
PMWIMAGEHDR pimage;
|
PMWIMAGEHDR pimage;
|
|
|
pItem = findimage(id);
|
pItem = findimage(id);
|
if (!pItem)
|
if (!pItem)
|
return;
|
return;
|
pimage = pItem->pimage;
|
pimage = pItem->pimage;
|
|
|
/*
|
/*
|
* Display image, possibly stretch/shrink to resize
|
* Display image, possibly stretch/shrink to resize
|
*/
|
*/
|
if (height < 0)
|
if (height < 0)
|
height = pimage->height;
|
height = pimage->height;
|
if (width < 0)
|
if (width < 0)
|
width = pimage->width;
|
width = pimage->width;
|
|
|
if (height != pimage->height || width != pimage->width) {
|
if (height != pimage->height || width != pimage->width) {
|
MWCLIPRECT rcDst;
|
MWCLIPRECT rcDst;
|
MWIMAGEHDR image2;
|
MWIMAGEHDR image2;
|
|
|
/* create similar image, different width/height*/
|
/* create similar image, different width/height*/
|
|
|
image2.width = width;
|
image2.width = width;
|
image2.height = height;
|
image2.height = height;
|
image2.planes = pimage->planes;
|
image2.planes = pimage->planes;
|
image2.bpp = pimage->bpp;
|
image2.bpp = pimage->bpp;
|
ComputePitch(pimage->bpp, width, &image2.pitch,
|
ComputePitch(pimage->bpp, width, &image2.pitch,
|
&image2.bytesperpixel);
|
&image2.bytesperpixel);
|
image2.compression = pimage->compression;
|
image2.compression = pimage->compression;
|
image2.palsize = pimage->palsize;
|
image2.palsize = pimage->palsize;
|
image2.palette = pimage->palette; /* already allocated*/
|
image2.palette = pimage->palette; /* already allocated*/
|
image2.transcolor = pimage->transcolor;
|
image2.transcolor = pimage->transcolor;
|
if( (image2.imagebits = malloc(image2.pitch*height)) == NULL) {
|
if( (image2.imagebits = malloc(image2.pitch*height)) == NULL) {
|
EPRINTF("GdDrawImageToFit: no memory\n");
|
EPRINTF("GdDrawImageToFit: no memory\n");
|
return;
|
return;
|
}
|
}
|
|
|
rcDst.x = 0;
|
rcDst.x = 0;
|
rcDst.y = 0;
|
rcDst.y = 0;
|
rcDst.width = width;
|
rcDst.width = width;
|
rcDst.height = height;
|
rcDst.height = height;
|
|
|
/* Stretch full soruce to destination rectangle*/
|
/* Stretch full soruce to destination rectangle*/
|
GdStretchImage(pimage, NULL, &image2, &rcDst);
|
GdStretchImage(pimage, NULL, &image2, &rcDst);
|
GdDrawImage(psd, x, y, &image2);
|
GdDrawImage(psd, x, y, &image2);
|
free(image2.imagebits);
|
free(image2.imagebits);
|
} else
|
} else
|
GdDrawImage(psd, x, y, pimage);
|
GdDrawImage(psd, x, y, pimage);
|
}
|
}
|
|
|
void
|
void
|
GdFreeImage(int id)
|
GdFreeImage(int id)
|
{
|
{
|
PIMAGEITEM pItem;
|
PIMAGEITEM pItem;
|
PMWIMAGEHDR pimage;
|
PMWIMAGEHDR pimage;
|
|
|
pItem = findimage(id);
|
pItem = findimage(id);
|
if (pItem) {
|
if (pItem) {
|
GdListRemove(&imagehead, &pItem->link);
|
GdListRemove(&imagehead, &pItem->link);
|
pimage = pItem->pimage;
|
pimage = pItem->pimage;
|
|
|
/* delete image bits*/
|
/* delete image bits*/
|
if(pimage->imagebits)
|
if(pimage->imagebits)
|
free(pimage->imagebits);
|
free(pimage->imagebits);
|
if(pimage->palette)
|
if(pimage->palette)
|
free(pimage->palette);
|
free(pimage->palette);
|
|
|
free(pimage);
|
free(pimage);
|
GdItemFree(pItem);
|
GdItemFree(pItem);
|
}
|
}
|
}
|
}
|
|
|
MWBOOL
|
MWBOOL
|
GdGetImageInfo(int id, PMWIMAGEINFO pii)
|
GdGetImageInfo(int id, PMWIMAGEINFO pii)
|
{
|
{
|
PMWIMAGEHDR pimage;
|
PMWIMAGEHDR pimage;
|
PIMAGEITEM pItem;
|
PIMAGEITEM pItem;
|
int i;
|
int i;
|
|
|
pItem = findimage(id);
|
pItem = findimage(id);
|
if (!pItem) {
|
if (!pItem) {
|
memset(pii, 0, sizeof(*pii));
|
memset(pii, 0, sizeof(*pii));
|
return FALSE;
|
return FALSE;
|
}
|
}
|
pimage = pItem->pimage;
|
pimage = pItem->pimage;
|
pii->id = id;
|
pii->id = id;
|
pii->width = pimage->width;
|
pii->width = pimage->width;
|
pii->height = pimage->height;
|
pii->height = pimage->height;
|
pii->planes = pimage->planes;
|
pii->planes = pimage->planes;
|
pii->bpp = pimage->bpp;
|
pii->bpp = pimage->bpp;
|
pii->pitch = pimage->pitch;
|
pii->pitch = pimage->pitch;
|
pii->bytesperpixel = pimage->bytesperpixel;
|
pii->bytesperpixel = pimage->bytesperpixel;
|
pii->compression = pimage->compression;
|
pii->compression = pimage->compression;
|
pii->palsize = pimage->palsize;
|
pii->palsize = pimage->palsize;
|
if (pimage->palsize) {
|
if (pimage->palsize) {
|
if (pimage->palette) {
|
if (pimage->palette) {
|
for (i=0; i<pimage->palsize; ++i)
|
for (i=0; i<pimage->palsize; ++i)
|
pii->palette[i] = pimage->palette[i];
|
pii->palette[i] = pimage->palette[i];
|
} else {
|
} else {
|
/* FIXME handle jpeg's without palette*/
|
/* FIXME handle jpeg's without palette*/
|
GdGetPalette(pItem->psd, 0, pimage->palsize,
|
GdGetPalette(pItem->psd, 0, pimage->palsize,
|
pii->palette);
|
pii->palette);
|
}
|
}
|
}
|
}
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
#define PIX2BYTES(n) (((n)+7)/8)
|
#define PIX2BYTES(n) (((n)+7)/8)
|
/*
|
/*
|
* compute image line size and bytes per pixel
|
* compute image line size and bytes per pixel
|
* from bits per pixel and width
|
* from bits per pixel and width
|
*/
|
*/
|
static void
|
static void
|
ComputePitch(int bpp, int width, int *pitch, int *bytesperpixel)
|
ComputePitch(int bpp, int width, int *pitch, int *bytesperpixel)
|
{
|
{
|
int linesize;
|
int linesize;
|
int bytespp = 1;
|
int bytespp = 1;
|
|
|
if(bpp == 1)
|
if(bpp == 1)
|
linesize = PIX2BYTES(width);
|
linesize = PIX2BYTES(width);
|
else if(bpp <= 4)
|
else if(bpp <= 4)
|
linesize = PIX2BYTES(width<<2);
|
linesize = PIX2BYTES(width<<2);
|
else if(bpp <= 8)
|
else if(bpp <= 8)
|
linesize = width;
|
linesize = width;
|
else if(bpp <= 16) {
|
else if(bpp <= 16) {
|
linesize = width * 2;
|
linesize = width * 2;
|
bytespp = 2;
|
bytespp = 2;
|
} else if(bpp <= 24) {
|
} else if(bpp <= 24) {
|
linesize = width * 3;
|
linesize = width * 3;
|
bytespp = 3;
|
bytespp = 3;
|
} else {
|
} else {
|
linesize = width * 4;
|
linesize = width * 4;
|
bytespp = 4;
|
bytespp = 4;
|
}
|
}
|
|
|
/* rows are DWORD right aligned*/
|
/* rows are DWORD right aligned*/
|
*pitch = (linesize + 3) & ~3;
|
*pitch = (linesize + 3) & ~3;
|
*bytesperpixel = bytespp;
|
*bytesperpixel = bytespp;
|
}
|
}
|
|
|
/*
|
/*
|
* StretchImage - Resize an image
|
* StretchImage - Resize an image
|
*
|
*
|
* Major portions from SDL Simple DirectMedia Layer by Sam Lantinga
|
* Major portions from SDL Simple DirectMedia Layer by Sam Lantinga
|
* Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga <slouken@devolution.com>
|
* Copyright (C) 1997, 1998, 1999, 2000 Sam Lantinga <slouken@devolution.com>
|
* This a stretch blit implementation based on ideas given to me by
|
* This a stretch blit implementation based on ideas given to me by
|
* Tomasz Cejner - thanks! :)
|
* Tomasz Cejner - thanks! :)
|
*/
|
*/
|
/*
|
/*
|
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
|
|
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
Library General Public License for more details.
|
Library General Public License for more details.
|
|
|
You should have received a copy of the GNU Library General Public
|
You should have received a copy of the GNU Library General Public
|
License along with this library; if not, write to the Free
|
License along with this library; if not, write to the Free
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
*/
|
*/
|
|
|
#define DEFINE_COPY_ROW(name, type) \
|
#define DEFINE_COPY_ROW(name, type) \
|
static void name(type *src, int src_w, type *dst, int dst_w) \
|
static void name(type *src, int src_w, type *dst, int dst_w) \
|
{ \
|
{ \
|
int i; \
|
int i; \
|
int pos, inc; \
|
int pos, inc; \
|
type pixel = 0; \
|
type pixel = 0; \
|
\
|
\
|
pos = 0x10000; \
|
pos = 0x10000; \
|
inc = (src_w << 16) / dst_w; \
|
inc = (src_w << 16) / dst_w; \
|
for ( i=dst_w; i>0; --i ) { \
|
for ( i=dst_w; i>0; --i ) { \
|
while ( pos >= 0x10000L ) { \
|
while ( pos >= 0x10000L ) { \
|
pixel = *src++; \
|
pixel = *src++; \
|
pos -= 0x10000L; \
|
pos -= 0x10000L; \
|
} \
|
} \
|
*dst++ = pixel; \
|
*dst++ = pixel; \
|
pos += inc; \
|
pos += inc; \
|
} \
|
} \
|
}
|
}
|
|
|
DEFINE_COPY_ROW(copy_row1, unsigned char)
|
DEFINE_COPY_ROW(copy_row1, unsigned char)
|
DEFINE_COPY_ROW(copy_row2, unsigned short)
|
DEFINE_COPY_ROW(copy_row2, unsigned short)
|
DEFINE_COPY_ROW(copy_row4, unsigned long)
|
DEFINE_COPY_ROW(copy_row4, unsigned long)
|
|
|
static void copy_row3(unsigned char *src, int src_w, unsigned char *dst,
|
static void copy_row3(unsigned char *src, int src_w, unsigned char *dst,
|
int dst_w)
|
int dst_w)
|
{
|
{
|
int i;
|
int i;
|
int pos, inc;
|
int pos, inc;
|
unsigned char r = 0;
|
unsigned char r = 0;
|
unsigned char g = 0;
|
unsigned char g = 0;
|
unsigned char b = 0;
|
unsigned char b = 0;
|
|
|
pos = 0x10000;
|
pos = 0x10000;
|
inc = (src_w << 16) / dst_w;
|
inc = (src_w << 16) / dst_w;
|
for ( i=dst_w; i>0; --i ) {
|
for ( i=dst_w; i>0; --i ) {
|
while ( pos >= 0x10000L ) {
|
while ( pos >= 0x10000L ) {
|
b = *src++;
|
b = *src++;
|
g = *src++;
|
g = *src++;
|
r = *src++;
|
r = *src++;
|
pos -= 0x10000L;
|
pos -= 0x10000L;
|
}
|
}
|
*dst++ = b;
|
*dst++ = b;
|
*dst++ = g;
|
*dst++ = g;
|
*dst++ = r;
|
*dst++ = r;
|
pos += inc;
|
pos += inc;
|
}
|
}
|
}
|
}
|
|
|
/* Perform a stretch blit between two image structs of the same format.*/
|
/* Perform a stretch blit between two image structs of the same format.*/
|
void
|
void
|
GdStretchImage(PMWIMAGEHDR src, MWCLIPRECT *srcrect, PMWIMAGEHDR dst,
|
GdStretchImage(PMWIMAGEHDR src, MWCLIPRECT *srcrect, PMWIMAGEHDR dst,
|
MWCLIPRECT *dstrect)
|
MWCLIPRECT *dstrect)
|
{
|
{
|
int pos, inc;
|
int pos, inc;
|
int bytesperpixel;
|
int bytesperpixel;
|
int dst_maxrow;
|
int dst_maxrow;
|
int src_row, dst_row;
|
int src_row, dst_row;
|
MWUCHAR *srcp = 0;
|
MWUCHAR *srcp = 0;
|
MWUCHAR *dstp;
|
MWUCHAR *dstp;
|
MWCLIPRECT full_src;
|
MWCLIPRECT full_src;
|
MWCLIPRECT full_dst;
|
MWCLIPRECT full_dst;
|
|
|
if ( src->bytesperpixel != dst->bytesperpixel ) {
|
if ( src->bytesperpixel != dst->bytesperpixel ) {
|
EPRINTF("GdStretchImage: bytesperpixel mismatch\n");
|
EPRINTF("GdStretchImage: bytesperpixel mismatch\n");
|
return;
|
return;
|
}
|
}
|
|
|
/* Verify the blit rectangles */
|
/* Verify the blit rectangles */
|
if ( srcrect ) {
|
if ( srcrect ) {
|
if ( (srcrect->x < 0) || (srcrect->y < 0) ||
|
if ( (srcrect->x < 0) || (srcrect->y < 0) ||
|
((srcrect->x+srcrect->width) > src->width) ||
|
((srcrect->x+srcrect->width) > src->width) ||
|
((srcrect->y+srcrect->height) > src->height) ) {
|
((srcrect->y+srcrect->height) > src->height) ) {
|
EPRINTF("GdStretchImage: invalid source rect\n");
|
EPRINTF("GdStretchImage: invalid source rect\n");
|
return;
|
return;
|
}
|
}
|
} else {
|
} else {
|
full_src.x = 0;
|
full_src.x = 0;
|
full_src.y = 0;
|
full_src.y = 0;
|
full_src.width = src->width;
|
full_src.width = src->width;
|
full_src.height = src->height;
|
full_src.height = src->height;
|
srcrect = &full_src;
|
srcrect = &full_src;
|
}
|
}
|
if ( dstrect ) {
|
if ( dstrect ) {
|
/* if stretching to nothing, return*/
|
/* if stretching to nothing, return*/
|
if (!dstrect->width || !dstrect->height)
|
if (!dstrect->width || !dstrect->height)
|
return;
|
return;
|
if ( (dstrect->x < 0) || (dstrect->y < 0) ||
|
if ( (dstrect->x < 0) || (dstrect->y < 0) ||
|
((dstrect->x+dstrect->width) > dst->width) ||
|
((dstrect->x+dstrect->width) > dst->width) ||
|
((dstrect->y+dstrect->height) > dst->height) ) {
|
((dstrect->y+dstrect->height) > dst->height) ) {
|
EPRINTF("GdStretchImage: invalid dest rect\n");
|
EPRINTF("GdStretchImage: invalid dest rect\n");
|
return;
|
return;
|
}
|
}
|
} else {
|
} else {
|
full_dst.x = 0;
|
full_dst.x = 0;
|
full_dst.y = 0;
|
full_dst.y = 0;
|
full_dst.width = dst->width;
|
full_dst.width = dst->width;
|
full_dst.height = dst->height;
|
full_dst.height = dst->height;
|
dstrect = &full_dst;
|
dstrect = &full_dst;
|
}
|
}
|
|
|
/* Set up the data... */
|
/* Set up the data... */
|
pos = 0x10000;
|
pos = 0x10000;
|
inc = (srcrect->height << 16) / dstrect->height;
|
inc = (srcrect->height << 16) / dstrect->height;
|
src_row = srcrect->y;
|
src_row = srcrect->y;
|
dst_row = dstrect->y;
|
dst_row = dstrect->y;
|
bytesperpixel = dst->bytesperpixel;
|
bytesperpixel = dst->bytesperpixel;
|
|
|
/* Perform the stretch blit */
|
/* Perform the stretch blit */
|
for ( dst_maxrow = dst_row+dstrect->height; dst_row<dst_maxrow;
|
for ( dst_maxrow = dst_row+dstrect->height; dst_row<dst_maxrow;
|
++dst_row ) {
|
++dst_row ) {
|
dstp = (MWUCHAR *)dst->imagebits + (dst_row*dst->pitch)
|
dstp = (MWUCHAR *)dst->imagebits + (dst_row*dst->pitch)
|
+ (dstrect->x*bytesperpixel);
|
+ (dstrect->x*bytesperpixel);
|
while ( pos >= 0x10000L ) {
|
while ( pos >= 0x10000L ) {
|
srcp = (MWUCHAR *)src->imagebits + (src_row*src->pitch)
|
srcp = (MWUCHAR *)src->imagebits + (src_row*src->pitch)
|
+ (srcrect->x*bytesperpixel);
|
+ (srcrect->x*bytesperpixel);
|
++src_row;
|
++src_row;
|
pos -= 0x10000L;
|
pos -= 0x10000L;
|
}
|
}
|
|
|
switch (bytesperpixel) {
|
switch (bytesperpixel) {
|
case 1:
|
case 1:
|
copy_row1(srcp, srcrect->width, dstp, dstrect->width);
|
copy_row1(srcp, srcrect->width, dstp, dstrect->width);
|
break;
|
break;
|
case 2:
|
case 2:
|
copy_row2((unsigned short *)srcp, srcrect->width,
|
copy_row2((unsigned short *)srcp, srcrect->width,
|
(unsigned short *)dstp, dstrect->width);
|
(unsigned short *)dstp, dstrect->width);
|
break;
|
break;
|
case 3:
|
case 3:
|
copy_row3(srcp, srcrect->width, dstp, dstrect->width);
|
copy_row3(srcp, srcrect->width, dstp, dstrect->width);
|
break;
|
break;
|
case 4:
|
case 4:
|
copy_row4((unsigned long *)srcp, srcrect->width,
|
copy_row4((unsigned long *)srcp, srcrect->width,
|
(unsigned long *)dstp, dstrect->width);
|
(unsigned long *)dstp, dstrect->width);
|
break;
|
break;
|
}
|
}
|
|
|
pos += inc;
|
pos += inc;
|
}
|
}
|
}
|
}
|
|
|
#if defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)
|
#if defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)
|
#include "jpeglib.h"
|
#include "jpeglib.h"
|
/*
|
/*
|
* JPEG decompression routine
|
* JPEG decompression routine
|
*
|
*
|
* JPEG support must be enabled (see README.txt in contrib/jpeg)
|
* JPEG support must be enabled (see README.txt in contrib/jpeg)
|
*
|
*
|
* SOME FINE POINTS: (from libjpeg)
|
* SOME FINE POINTS: (from libjpeg)
|
* In the below code, we ignored the return value of jpeg_read_scanlines,
|
* In the below code, we ignored the return value of jpeg_read_scanlines,
|
* which is the number of scanlines actually read. We could get away with
|
* which is the number of scanlines actually read. We could get away with
|
* this because we asked for only one line at a time and we weren't using
|
* this because we asked for only one line at a time and we weren't using
|
* a suspending data source. See libjpeg.doc for more info.
|
* a suspending data source. See libjpeg.doc for more info.
|
*
|
*
|
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
|
* We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
|
* we should have done it beforehand to ensure that the space would be
|
* we should have done it beforehand to ensure that the space would be
|
* counted against the JPEG max_memory setting. In some systems the above
|
* counted against the JPEG max_memory setting. In some systems the above
|
* code would risk an out-of-memory error. However, in general we don't
|
* code would risk an out-of-memory error. However, in general we don't
|
* know the output image dimensions before jpeg_start_decompress(), unless we
|
* know the output image dimensions before jpeg_start_decompress(), unless we
|
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
|
* call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this.
|
*
|
*
|
* Scanlines are returned in the same order as they appear in the JPEG file,
|
* Scanlines are returned in the same order as they appear in the JPEG file,
|
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
|
* which is standardly top-to-bottom. If you must emit data bottom-to-top,
|
* you can use one of the virtual arrays provided by the JPEG memory manager
|
* you can use one of the virtual arrays provided by the JPEG memory manager
|
* to invert the data. See wrbmp.c for an example.
|
* to invert the data. See wrbmp.c for an example.
|
*
|
*
|
* As with compression, some operating modes may require temporary files.
|
* As with compression, some operating modes may require temporary files.
|
* On some systems you may need to set up a signal handler to ensure that
|
* On some systems you may need to set up a signal handler to ensure that
|
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
|
* temporary files are deleted if the program is interrupted. See libjpeg.doc.
|
*/
|
*/
|
static int
|
static int
|
LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd, MWBOOL fast_grayscale)
|
LoadJPEG(buffer_t *src, PMWIMAGEHDR pimage, PSD psd, MWBOOL fast_grayscale)
|
{
|
{
|
int i;
|
int i;
|
int ret = 2; /* image load error*/
|
int ret = 2; /* image load error*/
|
unsigned char magic[4];
|
unsigned char magic[4];
|
|
|
#if FASTJPEG
|
#if FASTJPEG
|
extern MWPALENTRY mwstdpal8[256];
|
extern MWPALENTRY mwstdpal8[256];
|
#else
|
#else
|
MWPALENTRY palette[256];
|
MWPALENTRY palette[256];
|
#endif
|
#endif
|
|
|
struct jpeg_source_mgr smgr;
|
struct jpeg_source_mgr smgr;
|
struct jpeg_decompress_struct cinfo;
|
struct jpeg_decompress_struct cinfo;
|
struct jpeg_error_mgr jerr;
|
struct jpeg_error_mgr jerr;
|
|
|
static void init_source(j_compress_ptr dinfo) {
|
static void init_source(j_compress_ptr dinfo) {
|
smgr.next_input_byte = src->start;
|
smgr.next_input_byte = src->start;
|
smgr.bytes_in_buffer = src->size;
|
smgr.bytes_in_buffer = src->size;
|
}
|
}
|
|
|
static void fill_input_buffer(j_compress_ptr dinfo) {
|
static void fill_input_buffer(j_compress_ptr dinfo) {
|
return;
|
return;
|
}
|
}
|
|
|
static void skip_input_data(j_compress_ptr dinfo, int num_bytes) {
|
static void skip_input_data(j_compress_ptr dinfo, int num_bytes) {
|
if (num_bytes >= src->size) return;
|
if (num_bytes >= src->size) return;
|
smgr.next_input_byte += num_bytes;
|
smgr.next_input_byte += num_bytes;
|
smgr.bytes_in_buffer -= num_bytes;
|
smgr.bytes_in_buffer -= num_bytes;
|
}
|
}
|
|
|
static int resync_to_restart(j_compress_ptr dinfo, int desired ) {
|
static int resync_to_restart(j_compress_ptr dinfo, int desired ) {
|
return(jpeg_resync_to_restart(dinfo, desired));
|
return(jpeg_resync_to_restart(dinfo, desired));
|
}
|
}
|
|
|
static void term_source(j_compress_ptr dinfo) {
|
static void term_source(j_compress_ptr dinfo) {
|
return;
|
return;
|
}
|
}
|
|
|
/* first determine if JPEG file since decoder will error if not*/
|
/* first determine if JPEG file since decoder will error if not*/
|
bseek(src, 0, SEEK_SET);
|
bseek(src, 0, SEEK_SET);
|
|
|
if (!bread(src, magic, 2))
|
if (!bread(src, magic, 2))
|
return(0);
|
return(0);
|
|
|
if (magic[0] != 0xFF || magic[1] != 0xD8)
|
if (magic[0] != 0xFF || magic[1] != 0xD8)
|
return(0); /* not JPEG image*/
|
return(0); /* not JPEG image*/
|
|
|
|
|
bread(src, magic, 4);
|
bread(src, magic, 4);
|
bread(src, magic, 4);
|
bread(src, magic, 4);
|
|
|
if (strncmp(magic, "JFIF", 4) != 0)
|
if (strncmp(magic, "JFIF", 4) != 0)
|
return(0); /* not JPEG image*/
|
return(0); /* not JPEG image*/
|
|
|
bread(src, 0, SEEK_SET);
|
bread(src, 0, SEEK_SET);
|
pimage->imagebits = NULL;
|
pimage->imagebits = NULL;
|
pimage->palette = NULL;
|
pimage->palette = NULL;
|
|
|
/* Step 1: allocate and initialize JPEG decompression object */
|
/* Step 1: allocate and initialize JPEG decompression object */
|
|
|
/* We set up the normal JPEG error routines. */
|
/* We set up the normal JPEG error routines. */
|
cinfo.err = jpeg_std_error (&jerr);
|
cinfo.err = jpeg_std_error (&jerr);
|
|
|
/* Now we can initialize the JPEG decompression object. */
|
/* Now we can initialize the JPEG decompression object. */
|
jpeg_create_decompress (&cinfo);
|
jpeg_create_decompress (&cinfo);
|
|
|
|
|
/* Step 2: Setup the source manager */
|
/* Step 2: Setup the source manager */
|
|
|
smgr.init_source = init_source;
|
smgr.init_source = init_source;
|
smgr.fill_input_buffer = fill_input_buffer;
|
smgr.fill_input_buffer = fill_input_buffer;
|
smgr.skip_input_data = skip_input_data;
|
smgr.skip_input_data = skip_input_data;
|
smgr.resync_to_restart = resync_to_restart;
|
smgr.resync_to_restart = resync_to_restart;
|
smgr.term_source = term_source;
|
smgr.term_source = term_source;
|
|
|
cinfo.src = &smgr;
|
cinfo.src = &smgr;
|
|
|
/* Step 2: specify data source (eg, a file) */
|
/* Step 2: specify data source (eg, a file) */
|
/* jpeg_stdio_src (&cinfo, fp); */
|
/* jpeg_stdio_src (&cinfo, fp); */
|
|
|
/* Step 3: read file parameters with jpeg_read_header() */
|
/* Step 3: read file parameters with jpeg_read_header() */
|
jpeg_read_header (&cinfo, TRUE);
|
jpeg_read_header (&cinfo, TRUE);
|
|
|
/* Step 4: set parameters for decompression */
|
/* Step 4: set parameters for decompression */
|
cinfo.out_color_space = fast_grayscale? JCS_GRAYSCALE: JCS_RGB;
|
cinfo.out_color_space = fast_grayscale? JCS_GRAYSCALE: JCS_RGB;
|
cinfo.quantize_colors = FALSE;
|
cinfo.quantize_colors = FALSE;
|
|
|
#if FASTJPEG
|
#if FASTJPEG
|
goto fastjpeg;
|
goto fastjpeg;
|
#endif
|
#endif
|
if (!fast_grayscale)
|
if (!fast_grayscale)
|
{
|
{
|
if (psd->pixtype == MWPF_PALETTE)
|
if (psd->pixtype == MWPF_PALETTE)
|
{
|
{
|
fastjpeg:
|
fastjpeg:
|
cinfo.quantize_colors = TRUE;
|
cinfo.quantize_colors = TRUE;
|
|
|
#if FASTJPEG
|
#if FASTJPEG
|
cinfo.actual_number_of_colors = 256;
|
cinfo.actual_number_of_colors = 256;
|
#else
|
#else
|
/* Get system palette */
|
/* Get system palette */
|
cinfo.actual_number_of_colors =
|
cinfo.actual_number_of_colors =
|
GdGetPalette(psd, 0, psd->ncolors, palette);
|
GdGetPalette(psd, 0, psd->ncolors, palette);
|
#endif
|
#endif
|
|
|
/* Allocate jpeg colormap space */
|
/* Allocate jpeg colormap space */
|
cinfo.colormap = (*cinfo.mem->alloc_sarray)
|
cinfo.colormap = (*cinfo.mem->alloc_sarray)
|
((j_common_ptr) &cinfo, JPOOL_IMAGE,
|
((j_common_ptr) &cinfo, JPOOL_IMAGE,
|
(JDIMENSION)cinfo.actual_number_of_colors,
|
(JDIMENSION)cinfo.actual_number_of_colors,
|
(JDIMENSION)3);
|
(JDIMENSION)3);
|
|
|
/* Set colormap from system palette */
|
/* Set colormap from system palette */
|
for(i = 0; i < cinfo.actual_number_of_colors; ++i)
|
for(i = 0; i < cinfo.actual_number_of_colors; ++i)
|
{
|
{
|
#if FASTJPEG
|
#if FASTJPEG
|
cinfo.colormap[0][i] = mwstdpal8[i].r;
|
cinfo.colormap[0][i] = mwstdpal8[i].r;
|
cinfo.colormap[1][i] = mwstdpal8[i].g;
|
cinfo.colormap[1][i] = mwstdpal8[i].g;
|
cinfo.colormap[2][i] = mwstdpal8[i].b;
|
cinfo.colormap[2][i] = mwstdpal8[i].b;
|
#else
|
#else
|
cinfo.colormap[0][i] = palette[i].r;
|
cinfo.colormap[0][i] = palette[i].r;
|
cinfo.colormap[1][i] = palette[i].g;
|
cinfo.colormap[1][i] = palette[i].g;
|
cinfo.colormap[2][i] = palette[i].b;
|
cinfo.colormap[2][i] = palette[i].b;
|
#endif
|
#endif
|
}
|
}
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Grayscale output asked */
|
/* Grayscale output asked */
|
cinfo.quantize_colors = TRUE;
|
cinfo.quantize_colors = TRUE;
|
cinfo.out_color_space = JCS_GRAYSCALE;
|
cinfo.out_color_space = JCS_GRAYSCALE;
|
cinfo.desired_number_of_colors = psd->ncolors;
|
cinfo.desired_number_of_colors = psd->ncolors;
|
}
|
}
|
jpeg_calc_output_dimensions(&cinfo);
|
jpeg_calc_output_dimensions(&cinfo);
|
|
|
pimage->width = cinfo.output_width;
|
pimage->width = cinfo.output_width;
|
pimage->height = cinfo.output_height;
|
pimage->height = cinfo.output_height;
|
pimage->planes = 1;
|
pimage->planes = 1;
|
#if FASTJPEG
|
#if FASTJPEG
|
pimage->bpp = 8;
|
pimage->bpp = 8;
|
#else
|
#else
|
pimage->bpp = (fast_grayscale || psd->pixtype == MWPF_PALETTE)?
|
pimage->bpp = (fast_grayscale || psd->pixtype == MWPF_PALETTE)?
|
8: cinfo.output_components*8;
|
8: cinfo.output_components*8;
|
#endif
|
#endif
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
&pimage->bytesperpixel);
|
&pimage->bytesperpixel);
|
pimage->compression = MWIMAGE_RGB; /* RGB not BGR order*/
|
pimage->compression = MWIMAGE_RGB; /* RGB not BGR order*/
|
pimage->palsize = (pimage->bpp == 8)? 256: 0;
|
pimage->palsize = (pimage->bpp == 8)? 256: 0;
|
pimage->imagebits = malloc(pimage->pitch * pimage->height);
|
pimage->imagebits = malloc(pimage->pitch * pimage->height);
|
if(!pimage->imagebits)
|
if(!pimage->imagebits)
|
goto err;
|
goto err;
|
pimage->palette = NULL;
|
pimage->palette = NULL;
|
#if FASTJPEG
|
#if FASTJPEG
|
if(pimage->bpp == 8) {
|
if(pimage->bpp == 8) {
|
pimage->palette = malloc(256*sizeof(MWPALENTRY));
|
pimage->palette = malloc(256*sizeof(MWPALENTRY));
|
if(!pimage->palette)
|
if(!pimage->palette)
|
goto err;
|
goto err;
|
for (i=0; i<256; ++i)
|
for (i=0; i<256; ++i)
|
pimage->palette[i] = mwstdpal8[i];
|
pimage->palette[i] = mwstdpal8[i];
|
}
|
}
|
#endif
|
#endif
|
|
|
/* Step 5: Start decompressor */
|
/* Step 5: Start decompressor */
|
jpeg_start_decompress (&cinfo);
|
jpeg_start_decompress (&cinfo);
|
|
|
/* Step 6: while (scan lines remain to be read) */
|
/* Step 6: while (scan lines remain to be read) */
|
while(cinfo.output_scanline < cinfo.output_height) {
|
while(cinfo.output_scanline < cinfo.output_height) {
|
JSAMPROW rowptr[1];
|
JSAMPROW rowptr[1];
|
rowptr[0] = (JSAMPROW)(pimage->imagebits +
|
rowptr[0] = (JSAMPROW)(pimage->imagebits +
|
cinfo.output_scanline * pimage->pitch);
|
cinfo.output_scanline * pimage->pitch);
|
jpeg_read_scanlines (&cinfo, rowptr, 1);
|
jpeg_read_scanlines (&cinfo, rowptr, 1);
|
}
|
}
|
ret = 1;
|
ret = 1;
|
|
|
err:
|
err:
|
/* Step 7: Finish decompression */
|
/* Step 7: Finish decompression */
|
jpeg_finish_decompress (&cinfo);
|
jpeg_finish_decompress (&cinfo);
|
|
|
/* Step 8: Release JPEG decompression object */
|
/* Step 8: Release JPEG decompression object */
|
jpeg_destroy_decompress (&cinfo);
|
jpeg_destroy_decompress (&cinfo);
|
|
|
/* May want to check to see whether any corrupt-data
|
/* May want to check to see whether any corrupt-data
|
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
* warnings occurred (test whether jerr.pub.num_warnings is nonzero).
|
*/
|
*/
|
return ret;
|
return ret;
|
}
|
}
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)*/
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_JPEG_SUPPORT)*/
|
|
|
#if defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)
|
#if defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)
|
#include "png.h"
|
#include "png.h"
|
/* png_jmpbuf() macro is not defined prior to libpng-1.0.6*/
|
/* png_jmpbuf() macro is not defined prior to libpng-1.0.6*/
|
#ifndef png_jmpbuf
|
#ifndef png_jmpbuf
|
#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
|
#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
|
#endif
|
#endif
|
/*
|
/*
|
* Load a PNG file.
|
* Load a PNG file.
|
* Currently for simplicity we get the PNG library to convert the file to
|
* Currently for simplicity we get the PNG library to convert the file to
|
* 24 bit RGB format with no alpha channel information even if we could
|
* 24 bit RGB format with no alpha channel information even if we could
|
* potentially store the image more efficiently by taking note of the image
|
* potentially store the image more efficiently by taking note of the image
|
* type and depth and acting accordingly. Similarly, > 8 bits per channel,
|
* type and depth and acting accordingly. Similarly, > 8 bits per channel,
|
* gamma correction, etc. are not supported.
|
* gamma correction, etc. are not supported.
|
*/
|
*/
|
static int
|
static int
|
LoadPNG(buffer_t * src, PMWIMAGEHDR pimage)
|
LoadPNG(buffer_t * src, PMWIMAGEHDR pimage)
|
{
|
{
|
unsigned char hdr[8], **rows;
|
unsigned char hdr[8], **rows;
|
png_structp state;
|
png_structp state;
|
png_infop pnginfo;
|
png_infop pnginfo;
|
png_uint_32 width, height;
|
png_uint_32 width, height;
|
int bit_depth, colourtype, i;
|
int bit_depth, colourtype, i;
|
|
|
bseek(src, 0L, 0);
|
bseek(src, 0L, 0);
|
|
|
if(bread(src, hdr, 8) != 8) return 0;
|
if(bread(src, hdr, 8) != 8) return 0;
|
|
|
if(png_sig_cmp(hdr, 0, 8)) return 0;
|
if(png_sig_cmp(hdr, 0, 8)) return 0;
|
|
|
if(!(state = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
if(!(state = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL,
|
NULL, NULL))) goto nomem;
|
NULL, NULL))) goto nomem;
|
|
|
if(!(pnginfo = png_create_info_struct(state))) {
|
if(!(pnginfo = png_create_info_struct(state))) {
|
png_destroy_read_struct(&state, NULL, NULL);
|
png_destroy_read_struct(&state, NULL, NULL);
|
goto nomem;
|
goto nomem;
|
}
|
}
|
|
|
if(setjmp(png_jmpbuf(state))) {
|
if(setjmp(png_jmpbuf(state))) {
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
return 2;
|
return 2;
|
}
|
}
|
|
|
png_init_io(state, fp);
|
png_init_io(state, fp);
|
png_set_sig_bytes(state, 8);
|
png_set_sig_bytes(state, 8);
|
png_read_info(state, pnginfo);
|
png_read_info(state, pnginfo);
|
png_get_IHDR(state, pnginfo, &width, &height, &bit_depth, &colourtype,
|
png_get_IHDR(state, pnginfo, &width, &height, &bit_depth, &colourtype,
|
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
|
|
pimage->width = width;
|
pimage->width = width;
|
pimage->height = height;
|
pimage->height = height;
|
pimage->bpp = 24;
|
pimage->bpp = 24;
|
pimage->planes = 1;
|
pimage->planes = 1;
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
&pimage->bytesperpixel);
|
&pimage->bytesperpixel);
|
pimage->compression = MWIMAGE_RGB;
|
pimage->compression = MWIMAGE_RGB;
|
if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
|
if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
goto nomem;
|
goto nomem;
|
}
|
}
|
if(!(rows = malloc(pimage->height * sizeof(unsigned char *)))) {
|
if(!(rows = malloc(pimage->height * sizeof(unsigned char *)))) {
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
goto nomem;
|
goto nomem;
|
}
|
}
|
for(i = 0; i < pimage->height; i++)
|
for(i = 0; i < pimage->height; i++)
|
rows[i] = pimage->imagebits + (i * pimage->pitch);
|
rows[i] = pimage->imagebits + (i * pimage->pitch);
|
|
|
png_set_expand(state);
|
png_set_expand(state);
|
if(bit_depth == 16)
|
if(bit_depth == 16)
|
png_set_strip_16(state);
|
png_set_strip_16(state);
|
if(colourtype & PNG_COLOR_MASK_ALPHA)
|
if(colourtype & PNG_COLOR_MASK_ALPHA)
|
png_set_strip_alpha(state);
|
png_set_strip_alpha(state);
|
if(colourtype == PNG_COLOR_TYPE_GRAY ||
|
if(colourtype == PNG_COLOR_TYPE_GRAY ||
|
colourtype == PNG_COLOR_TYPE_GRAY_ALPHA)
|
colourtype == PNG_COLOR_TYPE_GRAY_ALPHA)
|
png_set_gray_to_rgb(state);
|
png_set_gray_to_rgb(state);
|
|
|
png_read_image(state, rows);
|
png_read_image(state, rows);
|
|
|
png_read_end(state, NULL);
|
png_read_end(state, NULL);
|
free(rows);
|
free(rows);
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
png_destroy_read_struct(&state, &pnginfo, NULL);
|
|
|
return 1;
|
return 1;
|
|
|
nomem:
|
nomem:
|
EPRINTF("LoadPNG: Out of memory\n");
|
EPRINTF("LoadPNG: Out of memory\n");
|
return 2;
|
return 2;
|
}
|
}
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)*/
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNG_SUPPORT)*/
|
|
|
#if defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)
|
#if defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)
|
/* BMP stuff*/
|
/* BMP stuff*/
|
#define BI_RGB 0L
|
#define BI_RGB 0L
|
#define BI_RLE8 1L
|
#define BI_RLE8 1L
|
#define BI_RLE4 2L
|
#define BI_RLE4 2L
|
#define BI_BITFIELDS 3L
|
#define BI_BITFIELDS 3L
|
|
|
typedef unsigned char BYTE;
|
typedef unsigned char BYTE;
|
typedef unsigned short WORD;
|
typedef unsigned short WORD;
|
typedef unsigned long DWORD;
|
typedef unsigned long DWORD;
|
typedef long LONG;
|
typedef long LONG;
|
|
|
typedef struct {
|
typedef struct {
|
/* BITMAPFILEHEADER*/
|
/* BITMAPFILEHEADER*/
|
BYTE bfType[2];
|
BYTE bfType[2];
|
DWORD bfSize;
|
DWORD bfSize;
|
WORD bfReserved1;
|
WORD bfReserved1;
|
WORD bfReserved2;
|
WORD bfReserved2;
|
DWORD bfOffBits;
|
DWORD bfOffBits;
|
} BMPFILEHEAD;
|
} BMPFILEHEAD;
|
|
|
#define FILEHEADSIZE 14
|
#define FILEHEADSIZE 14
|
|
|
/* windows style*/
|
/* windows style*/
|
typedef struct {
|
typedef struct {
|
/* BITMAPINFOHEADER*/
|
/* BITMAPINFOHEADER*/
|
DWORD BiSize;
|
DWORD BiSize;
|
DWORD BiWidth;
|
DWORD BiWidth;
|
DWORD BiHeight;
|
DWORD BiHeight;
|
WORD BiPlanes;
|
WORD BiPlanes;
|
WORD BiBitCount;
|
WORD BiBitCount;
|
DWORD BiCompression;
|
DWORD BiCompression;
|
DWORD BiSizeImage;
|
DWORD BiSizeImage;
|
DWORD BiXpelsPerMeter;
|
DWORD BiXpelsPerMeter;
|
DWORD BiYpelsPerMeter;
|
DWORD BiYpelsPerMeter;
|
DWORD BiClrUsed;
|
DWORD BiClrUsed;
|
DWORD BiClrImportant;
|
DWORD BiClrImportant;
|
} BMPINFOHEAD;
|
} BMPINFOHEAD;
|
|
|
#define INFOHEADSIZE 40
|
#define INFOHEADSIZE 40
|
|
|
/* os/2 style*/
|
/* os/2 style*/
|
typedef struct {
|
typedef struct {
|
/* BITMAPCOREHEADER*/
|
/* BITMAPCOREHEADER*/
|
DWORD bcSize;
|
DWORD bcSize;
|
WORD bcWidth;
|
WORD bcWidth;
|
WORD bcHeight;
|
WORD bcHeight;
|
WORD bcPlanes;
|
WORD bcPlanes;
|
WORD bcBitCount;
|
WORD bcBitCount;
|
} BMPCOREHEAD;
|
} BMPCOREHEAD;
|
|
|
#define COREHEADSIZE 12
|
#define COREHEADSIZE 12
|
|
|
static int DecodeRLE8(MWUCHAR *buf, buffer_t *src);
|
static int DecodeRLE8(MWUCHAR *buf, buffer_t *src);
|
static int DecodeRLE4(MWUCHAR *buf, buffer_t *src);
|
static int DecodeRLE4(MWUCHAR *buf, buffer_t *src);
|
static void put4(int b);
|
static void put4(int b);
|
|
|
/*
|
/*
|
* BMP decoding routine
|
* BMP decoding routine
|
*/
|
*/
|
|
|
/* Changed by JHC to allow a buffer instead of a filename */
|
/* Changed by JHC to allow a buffer instead of a filename */
|
|
|
static int
|
static int
|
LoadBMP(buffer_t *src, PMWIMAGEHDR pimage)
|
LoadBMP(buffer_t *src, PMWIMAGEHDR pimage)
|
{
|
{
|
int h, i, compression;
|
int h, i, compression;
|
int headsize;
|
int headsize;
|
MWUCHAR *imagebits;
|
MWUCHAR *imagebits;
|
BMPFILEHEAD bmpf;
|
BMPFILEHEAD bmpf;
|
BMPINFOHEAD bmpi;
|
BMPINFOHEAD bmpi;
|
BMPCOREHEAD bmpc;
|
BMPCOREHEAD bmpc;
|
MWUCHAR headbuffer[INFOHEADSIZE];
|
MWUCHAR headbuffer[INFOHEADSIZE];
|
|
|
bseek(src, 0, SEEK_SET);
|
bseek(src, 0, SEEK_SET);
|
|
|
pimage->imagebits = NULL;
|
pimage->imagebits = NULL;
|
pimage->palette = NULL;
|
pimage->palette = NULL;
|
|
|
/* read BMP file header*/
|
/* read BMP file header*/
|
if (bread(src, &headbuffer, FILEHEADSIZE) != FILEHEADSIZE)
|
if (bread(src, &headbuffer, FILEHEADSIZE) != FILEHEADSIZE)
|
return(0);
|
return(0);
|
|
|
bmpf.bfType[0] = headbuffer[0];
|
bmpf.bfType[0] = headbuffer[0];
|
bmpf.bfType[1] = headbuffer[1];
|
bmpf.bfType[1] = headbuffer[1];
|
|
|
/* Is it really a bmp file ? */
|
/* Is it really a bmp file ? */
|
if (*(WORD*)&bmpf.bfType[0] != wswap(0x4D42)) /* 'BM' */
|
if (*(WORD*)&bmpf.bfType[0] != wswap(0x4D42)) /* 'BM' */
|
return 0; /* not bmp image*/
|
return 0; /* not bmp image*/
|
|
|
/*bmpf.bfSize = dwswap(dwread(&headbuffer[2]));*/
|
/*bmpf.bfSize = dwswap(dwread(&headbuffer[2]));*/
|
bmpf.bfOffBits = dwswap(dwread(&headbuffer[10]));
|
bmpf.bfOffBits = dwswap(dwread(&headbuffer[10]));
|
|
|
/* Read remaining header size */
|
/* Read remaining header size */
|
if (bread(src,&headsize,sizeof(DWORD)) != sizeof(DWORD))
|
if (bread(src,&headsize,sizeof(DWORD)) != sizeof(DWORD))
|
return 0; /* not bmp image*/
|
return 0; /* not bmp image*/
|
headsize = dwswap(headsize);
|
headsize = dwswap(headsize);
|
|
|
/* might be windows or os/2 header */
|
/* might be windows or os/2 header */
|
if(headsize == COREHEADSIZE) {
|
if(headsize == COREHEADSIZE) {
|
|
|
/* read os/2 header */
|
/* read os/2 header */
|
if(bread(src, &headbuffer, COREHEADSIZE-sizeof(DWORD)) !=
|
if(bread(src, &headbuffer, COREHEADSIZE-sizeof(DWORD)) !=
|
COREHEADSIZE-sizeof(DWORD))
|
COREHEADSIZE-sizeof(DWORD))
|
return 0; /* not bmp image*/
|
return 0; /* not bmp image*/
|
|
|
/* Get data */
|
/* Get data */
|
bmpc.bcWidth = wswap(*(WORD*)&headbuffer[0]);
|
bmpc.bcWidth = wswap(*(WORD*)&headbuffer[0]);
|
bmpc.bcHeight = wswap(*(WORD*)&headbuffer[2]);
|
bmpc.bcHeight = wswap(*(WORD*)&headbuffer[2]);
|
bmpc.bcPlanes = wswap(*(WORD*)&headbuffer[4]);
|
bmpc.bcPlanes = wswap(*(WORD*)&headbuffer[4]);
|
bmpc.bcBitCount = wswap(*(WORD*)&headbuffer[6]);
|
bmpc.bcBitCount = wswap(*(WORD*)&headbuffer[6]);
|
|
|
pimage->width = (int)bmpc.bcWidth;
|
pimage->width = (int)bmpc.bcWidth;
|
pimage->height = (int)bmpc.bcHeight;
|
pimage->height = (int)bmpc.bcHeight;
|
pimage->bpp = bmpc.bcBitCount;
|
pimage->bpp = bmpc.bcBitCount;
|
if (pimage->bpp <= 8)
|
if (pimage->bpp <= 8)
|
pimage->palsize = 1 << pimage->bpp;
|
pimage->palsize = 1 << pimage->bpp;
|
else pimage->palsize = 0;
|
else pimage->palsize = 0;
|
compression = BI_RGB;
|
compression = BI_RGB;
|
} else {
|
} else {
|
/* read windows header */
|
/* read windows header */
|
if(bread(src, &headbuffer, INFOHEADSIZE-sizeof(DWORD)) !=
|
if(bread(src, &headbuffer, INFOHEADSIZE-sizeof(DWORD)) !=
|
INFOHEADSIZE-sizeof(DWORD))
|
INFOHEADSIZE-sizeof(DWORD))
|
return 0; /* not bmp image*/
|
return 0; /* not bmp image*/
|
|
|
/* Get data */
|
/* Get data */
|
bmpi.BiWidth = dwswap(*(DWORD*)&headbuffer[0]);
|
bmpi.BiWidth = dwswap(*(DWORD*)&headbuffer[0]);
|
bmpi.BiHeight = dwswap(*(DWORD*)&headbuffer[4]);
|
bmpi.BiHeight = dwswap(*(DWORD*)&headbuffer[4]);
|
bmpi.BiPlanes = wswap(*(WORD*)&headbuffer[8]);
|
bmpi.BiPlanes = wswap(*(WORD*)&headbuffer[8]);
|
bmpi.BiBitCount = wswap(*(WORD*)&headbuffer[10]);
|
bmpi.BiBitCount = wswap(*(WORD*)&headbuffer[10]);
|
bmpi.BiCompression = dwswap(*(DWORD*)&headbuffer[12]);
|
bmpi.BiCompression = dwswap(*(DWORD*)&headbuffer[12]);
|
bmpi.BiSizeImage = dwswap(*(DWORD*)&headbuffer[16]);
|
bmpi.BiSizeImage = dwswap(*(DWORD*)&headbuffer[16]);
|
bmpi.BiXpelsPerMeter = dwswap(*(DWORD*)&headbuffer[20]);
|
bmpi.BiXpelsPerMeter = dwswap(*(DWORD*)&headbuffer[20]);
|
bmpi.BiYpelsPerMeter = dwswap(*(DWORD*)&headbuffer[24]);
|
bmpi.BiYpelsPerMeter = dwswap(*(DWORD*)&headbuffer[24]);
|
bmpi.BiClrUsed = dwswap(*(DWORD*)&headbuffer[28]);
|
bmpi.BiClrUsed = dwswap(*(DWORD*)&headbuffer[28]);
|
bmpi.BiClrImportant = dwswap(*(DWORD*)&headbuffer[32]);
|
bmpi.BiClrImportant = dwswap(*(DWORD*)&headbuffer[32]);
|
|
|
pimage->width = (int)bmpi.BiWidth;
|
pimage->width = (int)bmpi.BiWidth;
|
pimage->height = (int)bmpi.BiHeight;
|
pimage->height = (int)bmpi.BiHeight;
|
pimage->bpp = bmpi.BiBitCount;
|
pimage->bpp = bmpi.BiBitCount;
|
pimage->palsize = (int)bmpi.BiClrUsed;
|
pimage->palsize = (int)bmpi.BiClrUsed;
|
if (pimage->palsize > 256)
|
if (pimage->palsize > 256)
|
pimage->palsize = 0;
|
pimage->palsize = 0;
|
else if(pimage->palsize == 0 && pimage->bpp <= 8)
|
else if(pimage->palsize == 0 && pimage->bpp <= 8)
|
pimage->palsize = 1 << pimage->bpp;
|
pimage->palsize = 1 << pimage->bpp;
|
compression = bmpi.BiCompression;
|
compression = bmpi.BiCompression;
|
}
|
}
|
pimage->compression = MWIMAGE_BGR; /* right side up, BGR order*/
|
pimage->compression = MWIMAGE_BGR; /* right side up, BGR order*/
|
pimage->planes = 1;
|
pimage->planes = 1;
|
|
|
/* currently only 1, 4, 8 and 24 bpp bitmaps*/
|
/* currently only 1, 4, 8 and 24 bpp bitmaps*/
|
if(pimage->bpp > 8 && pimage->bpp != 24) {
|
if(pimage->bpp > 8 && pimage->bpp != 24) {
|
EPRINTF("LoadBMP: image bpp not 1, 4, 8 or 24\n");
|
EPRINTF("LoadBMP: image bpp not 1, 4, 8 or 24\n");
|
return 2; /* image loading error*/
|
return 2; /* image loading error*/
|
}
|
}
|
|
|
/* compute byte line size and bytes per pixel*/
|
/* compute byte line size and bytes per pixel*/
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
&pimage->bytesperpixel);
|
&pimage->bytesperpixel);
|
|
|
/* Allocate image */
|
/* Allocate image */
|
if( (pimage->imagebits = malloc(pimage->pitch*pimage->height)) == NULL)
|
if( (pimage->imagebits = malloc(pimage->pitch*pimage->height)) == NULL)
|
goto err;
|
goto err;
|
if( (pimage->palette = malloc(256*sizeof(MWPALENTRY))) == NULL)
|
if( (pimage->palette = malloc(256*sizeof(MWPALENTRY))) == NULL)
|
goto err;
|
goto err;
|
|
|
/* get colormap*/
|
/* get colormap*/
|
if(pimage->bpp <= 8) {
|
if(pimage->bpp <= 8) {
|
for(i=0; i<pimage->palsize; i++) {
|
for(i=0; i<pimage->palsize; i++) {
|
pimage->palette[i].b = bgetc(src);
|
pimage->palette[i].b = bgetc(src);
|
pimage->palette[i].g = bgetc(src);
|
pimage->palette[i].g = bgetc(src);
|
pimage->palette[i].r = bgetc(src);
|
pimage->palette[i].r = bgetc(src);
|
if(headsize != COREHEADSIZE)
|
if(headsize != COREHEADSIZE)
|
bgetc(src);
|
bgetc(src);
|
}
|
}
|
}
|
}
|
|
|
/* decode image data*/
|
/* decode image data*/
|
bseek(src, bmpf.bfOffBits, SEEK_SET);
|
bseek(src, bmpf.bfOffBits, SEEK_SET);
|
|
|
h = pimage->height;
|
h = pimage->height;
|
/* For every row ... */
|
/* For every row ... */
|
while (--h >= 0) {
|
while (--h >= 0) {
|
/* turn image rightside up*/
|
/* turn image rightside up*/
|
imagebits = pimage->imagebits + h*pimage->pitch;
|
imagebits = pimage->imagebits + h*pimage->pitch;
|
|
|
/* Get row data from file */
|
/* Get row data from file */
|
if(compression == BI_RLE8) {
|
if(compression == BI_RLE8) {
|
if(!DecodeRLE8(imagebits, src))
|
if(!DecodeRLE8(imagebits, src))
|
break;
|
break;
|
} else if(compression == BI_RLE4) {
|
} else if(compression == BI_RLE4) {
|
if(!DecodeRLE4(imagebits, src))
|
if(!DecodeRLE4(imagebits, src))
|
break;
|
break;
|
} else {
|
} else {
|
if(bread(src, imagebits, pimage->pitch) !=
|
if(bread(src, imagebits, pimage->pitch) !=
|
pimage->pitch)
|
pimage->pitch)
|
goto err;
|
goto err;
|
}
|
}
|
}
|
}
|
return 1; /* bmp image ok*/
|
return 1; /* bmp image ok*/
|
|
|
err:
|
err:
|
EPRINTF("LoadBMP: image loading error\n");
|
EPRINTF("LoadBMP: image loading error\n");
|
if(pimage->imagebits)
|
if(pimage->imagebits)
|
free(pimage->imagebits);
|
free(pimage->imagebits);
|
if(pimage->palette)
|
if(pimage->palette)
|
free(pimage->palette);
|
free(pimage->palette);
|
return 2; /* bmp image error*/
|
return 2; /* bmp image error*/
|
}
|
}
|
|
|
/*
|
/*
|
* Decode one line of RLE8, return 0 when done with all bitmap data
|
* Decode one line of RLE8, return 0 when done with all bitmap data
|
*/
|
*/
|
static int
|
static int
|
DecodeRLE8(MWUCHAR *buf, buffer_t *src)
|
DecodeRLE8(MWUCHAR *buf, buffer_t *src)
|
{
|
{
|
int c, n;
|
int c, n;
|
MWUCHAR * p = buf;
|
MWUCHAR * p = buf;
|
|
|
for( ;;) {
|
for( ;;) {
|
switch( n = bgetc(src)) {
|
switch( n = bgetc(src)) {
|
case EOF:
|
case EOF:
|
return( 0);
|
return( 0);
|
case 0: /* 0 = escape*/
|
case 0: /* 0 = escape*/
|
switch( n = bgetc(src)) {
|
switch( n = bgetc(src)) {
|
case 0: /* 0 0 = end of current scan line*/
|
case 0: /* 0 0 = end of current scan line*/
|
return( 1);
|
return( 1);
|
case 1: /* 0 1 = end of data*/
|
case 1: /* 0 1 = end of data*/
|
return( 1);
|
return( 1);
|
case 2: /* 0 2 xx yy delta mode NOT SUPPORTED*/
|
case 2: /* 0 2 xx yy delta mode NOT SUPPORTED*/
|
(void)bgetc(src);
|
(void)bgetc(src);
|
(void)bgetc(src);
|
(void)bgetc(src);
|
continue;
|
continue;
|
default: /* 0 3..255 xx nn uncompressed data*/
|
default: /* 0 3..255 xx nn uncompressed data*/
|
for( c=0; c<n; c++)
|
for( c=0; c<n; c++)
|
*p++ = bgetc(src);
|
*p++ = bgetc(src);
|
if( n & 1)
|
if( n & 1)
|
(void)bgetc(src);
|
(void)bgetc(src);
|
continue;
|
continue;
|
}
|
}
|
default:
|
default:
|
c = bgetc(src);
|
c = bgetc(src);
|
while( n--)
|
while( n--)
|
*p++ = c;
|
*p++ = c;
|
continue;
|
continue;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
/*
|
/*
|
* Decode one line of RLE4, return 0 when done with all bitmap data
|
* Decode one line of RLE4, return 0 when done with all bitmap data
|
*/
|
*/
|
static MWUCHAR *p;
|
static MWUCHAR *p;
|
static int once;
|
static int once;
|
|
|
static void
|
static void
|
put4(int b)
|
put4(int b)
|
{
|
{
|
static int last;
|
static int last;
|
|
|
last = (last << 4) | b;
|
last = (last << 4) | b;
|
if( ++once == 2) {
|
if( ++once == 2) {
|
*p++ = last;
|
*p++ = last;
|
once = 0;
|
once = 0;
|
}
|
}
|
}
|
}
|
|
|
static int
|
static int
|
DecodeRLE4(MWUCHAR *buf, buffer_t *src)
|
DecodeRLE4(MWUCHAR *buf, buffer_t *src)
|
{
|
{
|
int c, n, c1, c2;
|
int c, n, c1, c2;
|
|
|
p = buf;
|
p = buf;
|
once = 0;
|
once = 0;
|
c1 = 0;
|
c1 = 0;
|
|
|
for( ;;) {
|
for( ;;) {
|
switch( n = bgetc(src)) {
|
switch( n = bgetc(src)) {
|
case EOF:
|
case EOF:
|
return( 0);
|
return( 0);
|
case 0: /* 0 = escape*/
|
case 0: /* 0 = escape*/
|
switch( n = bgetc(src)) {
|
switch( n = bgetc(src)) {
|
case 0: /* 0 0 = end of current scan line*/
|
case 0: /* 0 0 = end of current scan line*/
|
if( once)
|
if( once)
|
put4( 0);
|
put4( 0);
|
return( 1);
|
return( 1);
|
case 1: /* 0 1 = end of data*/
|
case 1: /* 0 1 = end of data*/
|
if( once)
|
if( once)
|
put4( 0);
|
put4( 0);
|
return( 1);
|
return( 1);
|
case 2: /* 0 2 xx yy delta mode NOT SUPPORTED*/
|
case 2: /* 0 2 xx yy delta mode NOT SUPPORTED*/
|
(void)bgetc(src);
|
(void)bgetc(src);
|
(void)bgetc(src);
|
(void)bgetc(src);
|
continue;
|
continue;
|
default: /* 0 3..255 xx nn uncompressed data*/
|
default: /* 0 3..255 xx nn uncompressed data*/
|
c2 = (n+3) & ~3;
|
c2 = (n+3) & ~3;
|
for( c=0; c<c2; c++) {
|
for( c=0; c<c2; c++) {
|
if( (c & 1) == 0)
|
if( (c & 1) == 0)
|
c1 = bgetc(src);
|
c1 = bgetc(src);
|
if( c < n)
|
if( c < n)
|
put4( (c1 >> 4) & 0x0f);
|
put4( (c1 >> 4) & 0x0f);
|
c1 <<= 4;
|
c1 <<= 4;
|
}
|
}
|
continue;
|
continue;
|
}
|
}
|
default:
|
default:
|
c = bgetc(src);
|
c = bgetc(src);
|
c1 = (c >> 4) & 0x0f;
|
c1 = (c >> 4) & 0x0f;
|
c2 = c & 0x0f;
|
c2 = c & 0x0f;
|
for( c=0; c<n; c++)
|
for( c=0; c<n; c++)
|
put4( (c&1)? c2: c1);
|
put4( (c&1)? c2: c1);
|
continue;
|
continue;
|
}
|
}
|
}
|
}
|
}
|
}
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)*/
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_BMP_SUPPORT)*/
|
|
|
#if 0
|
#if 0
|
void print_image(PMWIMAGEHDR image)
|
void print_image(PMWIMAGEHDR image)
|
{
|
{
|
int i;
|
int i;
|
|
|
DPRINTF("Image:\n\n");
|
DPRINTF("Image:\n\n");
|
DPRINTF("height: %d\n", image->height);
|
DPRINTF("height: %d\n", image->height);
|
DPRINTF("width: %d\n", image->width);
|
DPRINTF("width: %d\n", image->width);
|
DPRINTF("planes: %d\n", image->planes);
|
DPRINTF("planes: %d\n", image->planes);
|
DPRINTF("bpp: %d\n", image->bpp);
|
DPRINTF("bpp: %d\n", image->bpp);
|
DPRINTF("compression: %d\n", image->compression);
|
DPRINTF("compression: %d\n", image->compression);
|
DPRINTF("palsize: %d\n", image->palsize);
|
DPRINTF("palsize: %d\n", image->palsize);
|
|
|
for (i=0;i<image->palsize;i++)
|
for (i=0;i<image->palsize;i++)
|
DPRINTF("palette: %d, %d, %d\n", image->palette[i].r,
|
DPRINTF("palette: %d, %d, %d\n", image->palette[i].r,
|
image->palette[i].g, image->palette[i].b);
|
image->palette[i].g, image->palette[i].b);
|
|
|
for(i=0;i<(image->width*image->height);i++)
|
for(i=0;i<(image->width*image->height);i++)
|
DPRINTF("imagebits: %d\n", image->imagebits[i]);
|
DPRINTF("imagebits: %d\n", image->imagebits[i]);
|
}
|
}
|
#endif
|
#endif
|
|
|
#if defined(HAVE_FILEIO) && defined(HAVE_GIF_SUPPORT)
|
#if defined(HAVE_FILEIO) && defined(HAVE_GIF_SUPPORT)
|
/* Code for GIF decoding has been adapted from XPaint: */
|
/* Code for GIF decoding has been adapted from XPaint: */
|
/* +-------------------------------------------------------------------+ */
|
/* +-------------------------------------------------------------------+ */
|
/* | Copyright 1990, 1991, 1993 David Koblas. | */
|
/* | Copyright 1990, 1991, 1993 David Koblas. | */
|
/* | Copyright 1996 Torsten Martinsen. | */
|
/* | Copyright 1996 Torsten Martinsen. | */
|
/* | Permission to use, copy, modify, and distribute this software | */
|
/* | Permission to use, copy, modify, and distribute this software | */
|
/* | and its documentation for any purpose and without fee is hereby | */
|
/* | and its documentation for any purpose and without fee is hereby | */
|
/* | granted, provided that the above copyright notice appear in all | */
|
/* | granted, provided that the above copyright notice appear in all | */
|
/* | copies and that both that copyright notice and this permission | */
|
/* | copies and that both that copyright notice and this permission | */
|
/* | notice appear in supporting documentation. This software is | */
|
/* | notice appear in supporting documentation. This software is | */
|
/* | provided "as is" without express or implied warranty. | */
|
/* | provided "as is" without express or implied warranty. | */
|
/* +-------------------------------------------------------------------+ */
|
/* +-------------------------------------------------------------------+ */
|
/* Portions Copyright (C) 1999 Sam Lantinga*/
|
/* Portions Copyright (C) 1999 Sam Lantinga*/
|
/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
|
/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
|
/*
|
/*
|
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
modify it under the terms of the GNU Library General Public
|
modify it under the terms of the GNU Library General Public
|
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
version 2 of the License, or (at your option) any later version.
|
version 2 of the License, or (at your option) any later version.
|
|
|
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
Library General Public License for more details.
|
Library General Public License for more details.
|
|
|
You should have received a copy of the GNU Library General Public
|
You should have received a copy of the GNU Library General Public
|
License along with this library; if not, write to the Free
|
License along with this library; if not, write to the Free
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
*/
|
*/
|
/* GIF stuff*/
|
/* GIF stuff*/
|
/*
|
/*
|
* GIF decoding routine
|
* GIF decoding routine
|
*/
|
*/
|
#define MAXCOLORMAPSIZE 256
|
#define MAXCOLORMAPSIZE 256
|
#define MAX_LWZ_BITS 12
|
#define MAX_LWZ_BITS 12
|
#define INTERLACE 0x40
|
#define INTERLACE 0x40
|
#define LOCALCOLORMAP 0x80
|
#define LOCALCOLORMAP 0x80
|
|
|
#define CM_RED 0
|
#define CM_RED 0
|
#define CM_GREEN 1
|
#define CM_GREEN 1
|
#define CM_BLUE 2
|
#define CM_BLUE 2
|
|
|
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
|
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
|
#define ReadOK(src,buffer,len) bread(src, buffer, len)
|
#define ReadOK(src,buffer,len) bread(src, buffer, len)
|
#define LM_to_uint(a,b) (((b)<<8)|(a))
|
#define LM_to_uint(a,b) (((b)<<8)|(a))
|
|
|
struct {
|
struct {
|
unsigned int Width;
|
unsigned int Width;
|
unsigned int Height;
|
unsigned int Height;
|
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
|
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
|
unsigned int BitPixel;
|
unsigned int BitPixel;
|
unsigned int ColorResolution;
|
unsigned int ColorResolution;
|
unsigned int Background;
|
unsigned int Background;
|
unsigned int AspectRatio;
|
unsigned int AspectRatio;
|
int GrayScale;
|
int GrayScale;
|
} GifScreen;
|
} GifScreen;
|
|
|
static struct {
|
static struct {
|
int transparent;
|
int transparent;
|
int delayTime;
|
int delayTime;
|
int inputFlag;
|
int inputFlag;
|
int disposal;
|
int disposal;
|
} Gif89;
|
} Gif89;
|
|
|
static int ReadColorMap(buffer_t *src, int number,
|
static int ReadColorMap(buffer_t *src, int number,
|
unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag);
|
unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag);
|
static int DoExtension(buffer_t *src, int label);
|
static int DoExtension(buffer_t *src, int label);
|
static int GetDataBlock(buffer_t *src, unsigned char *buf);
|
static int GetDataBlock(buffer_t *src, unsigned char *buf);
|
static int GetCode(buffer_t *src, int code_size, int flag);
|
static int GetCode(buffer_t *src, int code_size, int flag);
|
static int LWZReadByte(buffer_t *src, int flag, int input_code_size);
|
static int LWZReadByte(buffer_t *src, int flag, int input_code_size);
|
static int ReadImage(buffer_t *src, PMWIMAGEHDR pimage, int len, int height, int,
|
static int ReadImage(buffer_t *src, PMWIMAGEHDR pimage, int len, int height, int,
|
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
int gray, int interlace, int ignore);
|
int gray, int interlace, int ignore);
|
|
|
static int
|
static int
|
LoadGIF(buffer_t *src, PMWIMAGEHDR pimage)
|
LoadGIF(buffer_t *src, PMWIMAGEHDR pimage)
|
{
|
{
|
unsigned char buf[16];
|
unsigned char buf[16];
|
unsigned char c;
|
unsigned char c;
|
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
|
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
|
int grayScale;
|
int grayScale;
|
int useGlobalColormap;
|
int useGlobalColormap;
|
int bitPixel;
|
int bitPixel;
|
int imageCount = 0;
|
int imageCount = 0;
|
char version[4];
|
char version[4];
|
int imageNumber = 1;
|
int imageNumber = 1;
|
int ok = 0;
|
int ok = 0;
|
|
|
bseek(src, 0, SEEK_SET);
|
bseek(src, 0, SEEK_SET);
|
|
|
pimage->imagebits = NULL;
|
pimage->imagebits = NULL;
|
pimage->palette = NULL;
|
pimage->palette = NULL;
|
|
|
if (!ReadOK(src, buf, 6))
|
if (!ReadOK(src, buf, 6))
|
return 0; /* not gif image*/
|
return 0; /* not gif image*/
|
if (strncmp((char *) buf, "GIF", 3) != 0)
|
if (strncmp((char *) buf, "GIF", 3) != 0)
|
return 0;
|
return 0;
|
strncpy(version, (char *) buf + 3, 3);
|
strncpy(version, (char *) buf + 3, 3);
|
version[3] = '\0';
|
version[3] = '\0';
|
|
|
if (strcmp(version, "87a") != 0 && strcmp(version, "89a") != 0) {
|
if (strcmp(version, "87a") != 0 && strcmp(version, "89a") != 0) {
|
EPRINTF("LoadGIF: GIF version number not 87a or 89a\n");
|
EPRINTF("LoadGIF: GIF version number not 87a or 89a\n");
|
return 2; /* image loading error*/
|
return 2; /* image loading error*/
|
}
|
}
|
Gif89.transparent = -1;
|
Gif89.transparent = -1;
|
Gif89.delayTime = -1;
|
Gif89.delayTime = -1;
|
Gif89.inputFlag = -1;
|
Gif89.inputFlag = -1;
|
Gif89.disposal = 0;
|
Gif89.disposal = 0;
|
|
|
if (!ReadOK(src, buf, 7)) {
|
if (!ReadOK(src, buf, 7)) {
|
EPRINTF("LoadGIF: bad screen descriptor\n");
|
EPRINTF("LoadGIF: bad screen descriptor\n");
|
return 2; /* image loading error*/
|
return 2; /* image loading error*/
|
}
|
}
|
GifScreen.Width = LM_to_uint(buf[0], buf[1]);
|
GifScreen.Width = LM_to_uint(buf[0], buf[1]);
|
GifScreen.Height = LM_to_uint(buf[2], buf[3]);
|
GifScreen.Height = LM_to_uint(buf[2], buf[3]);
|
GifScreen.BitPixel = 2 << (buf[4] & 0x07);
|
GifScreen.BitPixel = 2 << (buf[4] & 0x07);
|
GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
|
GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
|
GifScreen.Background = buf[5];
|
GifScreen.Background = buf[5];
|
GifScreen.AspectRatio = buf[6];
|
GifScreen.AspectRatio = buf[6];
|
|
|
if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
|
if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
|
if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap,
|
if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap,
|
&GifScreen.GrayScale)) {
|
&GifScreen.GrayScale)) {
|
EPRINTF("LoadGIF: bad global colormap\n");
|
EPRINTF("LoadGIF: bad global colormap\n");
|
return 2; /* image loading error*/
|
return 2; /* image loading error*/
|
}
|
}
|
}
|
}
|
|
|
do {
|
do {
|
if (!ReadOK(src, &c, 1)) {
|
if (!ReadOK(src, &c, 1)) {
|
EPRINTF("LoadGIF: EOF on image data\n");
|
EPRINTF("LoadGIF: EOF on image data\n");
|
goto done;
|
goto done;
|
}
|
}
|
if (c == ';') { /* GIF terminator */
|
if (c == ';') { /* GIF terminator */
|
if (imageCount < imageNumber) {
|
if (imageCount < imageNumber) {
|
EPRINTF("LoadGIF: no image %d of %d\n", imageNumber,imageCount);
|
EPRINTF("LoadGIF: no image %d of %d\n", imageNumber,imageCount);
|
goto done;
|
goto done;
|
}
|
}
|
}
|
}
|
if (c == '!') { /* Extension */
|
if (c == '!') { /* Extension */
|
if (!ReadOK(src, &c, 1)) {
|
if (!ReadOK(src, &c, 1)) {
|
EPRINTF("LoadGIF: EOF on extension function code\n");
|
EPRINTF("LoadGIF: EOF on extension function code\n");
|
goto done;
|
goto done;
|
}
|
}
|
DoExtension(src, c);
|
DoExtension(src, c);
|
continue;
|
continue;
|
}
|
}
|
if (c != ',') { /* Not a valid start character */
|
if (c != ',') { /* Not a valid start character */
|
continue;
|
continue;
|
}
|
}
|
++imageCount;
|
++imageCount;
|
|
|
if (!ReadOK(src, buf, 9)) {
|
if (!ReadOK(src, buf, 9)) {
|
EPRINTF("LoadGIF: bad image size\n");
|
EPRINTF("LoadGIF: bad image size\n");
|
goto done;
|
goto done;
|
}
|
}
|
useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
|
useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
|
|
|
bitPixel = 1 << ((buf[8] & 0x07) + 1);
|
bitPixel = 1 << ((buf[8] & 0x07) + 1);
|
|
|
if (!useGlobalColormap) {
|
if (!useGlobalColormap) {
|
if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) {
|
if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) {
|
EPRINTF("LoadGIF: bad local colormap\n");
|
EPRINTF("LoadGIF: bad local colormap\n");
|
goto done;
|
goto done;
|
}
|
}
|
ok = ReadImage(src, pimage, LM_to_uint(buf[4], buf[5]),
|
ok = ReadImage(src, pimage, LM_to_uint(buf[4], buf[5]),
|
LM_to_uint(buf[6], buf[7]),
|
LM_to_uint(buf[6], buf[7]),
|
bitPixel, localColorMap, grayScale,
|
bitPixel, localColorMap, grayScale,
|
BitSet(buf[8], INTERLACE),
|
BitSet(buf[8], INTERLACE),
|
imageCount != imageNumber);
|
imageCount != imageNumber);
|
} else {
|
} else {
|
ok = ReadImage(src, pimage, LM_to_uint(buf[4], buf[5]),
|
ok = ReadImage(src, pimage, LM_to_uint(buf[4], buf[5]),
|
LM_to_uint(buf[6], buf[7]),
|
LM_to_uint(buf[6], buf[7]),
|
GifScreen.BitPixel, GifScreen.ColorMap,
|
GifScreen.BitPixel, GifScreen.ColorMap,
|
GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
|
GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
|
imageCount != imageNumber);
|
imageCount != imageNumber);
|
}
|
}
|
} while (ok == 0);
|
} while (ok == 0);
|
|
|
/* set transparent color, if any*/
|
/* set transparent color, if any*/
|
pimage->transcolor = Gif89.transparent;
|
pimage->transcolor = Gif89.transparent;
|
|
|
if (ok)
|
if (ok)
|
return 1; /* image load ok*/
|
return 1; /* image load ok*/
|
|
|
done:
|
done:
|
if (pimage->imagebits)
|
if (pimage->imagebits)
|
free(pimage->imagebits);
|
free(pimage->imagebits);
|
if (pimage->palette)
|
if (pimage->palette)
|
free(pimage->palette);
|
free(pimage->palette);
|
return 2; /* image load error*/
|
return 2; /* image load error*/
|
}
|
}
|
|
|
static int
|
static int
|
ReadColorMap(buffer_t *src, int number, unsigned char buffer[3][MAXCOLORMAPSIZE],
|
ReadColorMap(buffer_t *src, int number, unsigned char buffer[3][MAXCOLORMAPSIZE],
|
int *gray)
|
int *gray)
|
{
|
{
|
int i;
|
int i;
|
unsigned char rgb[3];
|
unsigned char rgb[3];
|
int flag;
|
int flag;
|
|
|
flag = TRUE;
|
flag = TRUE;
|
|
|
for (i = 0; i < number; ++i) {
|
for (i = 0; i < number; ++i) {
|
if (!ReadOK(src, rgb, sizeof(rgb)))
|
if (!ReadOK(src, rgb, sizeof(rgb)))
|
return 1;
|
return 1;
|
buffer[CM_RED][i] = rgb[0];
|
buffer[CM_RED][i] = rgb[0];
|
buffer[CM_GREEN][i] = rgb[1];
|
buffer[CM_GREEN][i] = rgb[1];
|
buffer[CM_BLUE][i] = rgb[2];
|
buffer[CM_BLUE][i] = rgb[2];
|
flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
|
flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
|
}
|
}
|
|
|
#if 0
|
#if 0
|
if (flag)
|
if (flag)
|
*gray = (number == 2) ? PBM_TYPE : PGM_TYPE;
|
*gray = (number == 2) ? PBM_TYPE : PGM_TYPE;
|
else
|
else
|
*gray = PPM_TYPE;
|
*gray = PPM_TYPE;
|
#else
|
#else
|
*gray = 0;
|
*gray = 0;
|
#endif
|
#endif
|
|
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
static int
|
static int
|
DoExtension(buffer_t *src, int label)
|
DoExtension(buffer_t *src, int label)
|
{
|
{
|
static unsigned char buf[256];
|
static unsigned char buf[256];
|
|
|
switch (label) {
|
switch (label) {
|
case 0x01: /* Plain Text Extension */
|
case 0x01: /* Plain Text Extension */
|
break;
|
break;
|
case 0xff: /* Application Extension */
|
case 0xff: /* Application Extension */
|
break;
|
break;
|
case 0xfe: /* Comment Extension */
|
case 0xfe: /* Comment Extension */
|
while (GetDataBlock(src, (unsigned char *) buf) != 0);
|
while (GetDataBlock(src, (unsigned char *) buf) != 0);
|
return FALSE;
|
return FALSE;
|
case 0xf9: /* Graphic Control Extension */
|
case 0xf9: /* Graphic Control Extension */
|
GetDataBlock(src, (unsigned char *) buf);
|
GetDataBlock(src, (unsigned char *) buf);
|
Gif89.disposal = (buf[0] >> 2) & 0x7;
|
Gif89.disposal = (buf[0] >> 2) & 0x7;
|
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
|
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
|
Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
|
Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
|
if ((buf[0] & 0x1) != 0)
|
if ((buf[0] & 0x1) != 0)
|
Gif89.transparent = buf[3];
|
Gif89.transparent = buf[3];
|
|
|
while (GetDataBlock(src, (unsigned char *) buf) != 0);
|
while (GetDataBlock(src, (unsigned char *) buf) != 0);
|
return FALSE;
|
return FALSE;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
|
|
while (GetDataBlock(src, (unsigned char *) buf) != 0);
|
while (GetDataBlock(src, (unsigned char *) buf) != 0);
|
|
|
return FALSE;
|
return FALSE;
|
}
|
}
|
|
|
static int ZeroDataBlock = FALSE;
|
static int ZeroDataBlock = FALSE;
|
|
|
static int
|
static int
|
GetDataBlock(buffer_t *src, unsigned char *buf)
|
GetDataBlock(buffer_t *src, unsigned char *buf)
|
{
|
{
|
unsigned char count;
|
unsigned char count;
|
|
|
if (!ReadOK(src, &count, 1))
|
if (!ReadOK(src, &count, 1))
|
return -1;
|
return -1;
|
ZeroDataBlock = count == 0;
|
ZeroDataBlock = count == 0;
|
|
|
if ((count != 0) && (!ReadOK(src, buf, count)))
|
if ((count != 0) && (!ReadOK(src, buf, count)))
|
return -1;
|
return -1;
|
return count;
|
return count;
|
}
|
}
|
|
|
static int
|
static int
|
GetCode(buffer_t *src, int code_size, int flag)
|
GetCode(buffer_t *src, int code_size, int flag)
|
{
|
{
|
static unsigned char buf[280];
|
static unsigned char buf[280];
|
static int curbit, lastbit, done, last_byte;
|
static int curbit, lastbit, done, last_byte;
|
int i, j, ret;
|
int i, j, ret;
|
unsigned char count;
|
unsigned char count;
|
|
|
if (flag) {
|
if (flag) {
|
curbit = 0;
|
curbit = 0;
|
lastbit = 0;
|
lastbit = 0;
|
done = FALSE;
|
done = FALSE;
|
return 0;
|
return 0;
|
}
|
}
|
if ((curbit + code_size) >= lastbit) {
|
if ((curbit + code_size) >= lastbit) {
|
if (done) {
|
if (done) {
|
if (curbit >= lastbit)
|
if (curbit >= lastbit)
|
EPRINTF("LoadGIF: bad decode\n");
|
EPRINTF("LoadGIF: bad decode\n");
|
return -1;
|
return -1;
|
}
|
}
|
buf[0] = buf[last_byte - 2];
|
buf[0] = buf[last_byte - 2];
|
buf[1] = buf[last_byte - 1];
|
buf[1] = buf[last_byte - 1];
|
|
|
if ((count = GetDataBlock(src, &buf[2])) == 0)
|
if ((count = GetDataBlock(src, &buf[2])) == 0)
|
done = TRUE;
|
done = TRUE;
|
|
|
last_byte = 2 + count;
|
last_byte = 2 + count;
|
curbit = (curbit - lastbit) + 16;
|
curbit = (curbit - lastbit) + 16;
|
lastbit = (2 + count) * 8;
|
lastbit = (2 + count) * 8;
|
}
|
}
|
ret = 0;
|
ret = 0;
|
for (i = curbit, j = 0; j < code_size; ++i, ++j)
|
for (i = curbit, j = 0; j < code_size; ++i, ++j)
|
ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
|
ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
|
|
|
curbit += code_size;
|
curbit += code_size;
|
|
|
return ret;
|
return ret;
|
}
|
}
|
|
|
static int
|
static int
|
LWZReadByte(buffer_t *src, int flag, int input_code_size)
|
LWZReadByte(buffer_t *src, int flag, int input_code_size)
|
{
|
{
|
int code, incode;
|
int code, incode;
|
register int i;
|
register int i;
|
static int fresh = FALSE;
|
static int fresh = FALSE;
|
static int code_size, set_code_size;
|
static int code_size, set_code_size;
|
static int max_code, max_code_size;
|
static int max_code, max_code_size;
|
static int firstcode, oldcode;
|
static int firstcode, oldcode;
|
static int clear_code, end_code;
|
static int clear_code, end_code;
|
static int table[2][(1 << MAX_LWZ_BITS)];
|
static int table[2][(1 << MAX_LWZ_BITS)];
|
static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
|
static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
|
|
|
if (flag) {
|
if (flag) {
|
set_code_size = input_code_size;
|
set_code_size = input_code_size;
|
code_size = set_code_size + 1;
|
code_size = set_code_size + 1;
|
clear_code = 1 << set_code_size;
|
clear_code = 1 << set_code_size;
|
end_code = clear_code + 1;
|
end_code = clear_code + 1;
|
max_code_size = 2 * clear_code;
|
max_code_size = 2 * clear_code;
|
max_code = clear_code + 2;
|
max_code = clear_code + 2;
|
|
|
GetCode(src, 0, TRUE);
|
GetCode(src, 0, TRUE);
|
|
|
fresh = TRUE;
|
fresh = TRUE;
|
|
|
for (i = 0; i < clear_code; ++i) {
|
for (i = 0; i < clear_code; ++i) {
|
table[0][i] = 0;
|
table[0][i] = 0;
|
table[1][i] = i;
|
table[1][i] = i;
|
}
|
}
|
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
table[0][i] = table[1][0] = 0;
|
table[0][i] = table[1][0] = 0;
|
|
|
sp = stack;
|
sp = stack;
|
|
|
return 0;
|
return 0;
|
} else if (fresh) {
|
} else if (fresh) {
|
fresh = FALSE;
|
fresh = FALSE;
|
do {
|
do {
|
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
} while (firstcode == clear_code);
|
} while (firstcode == clear_code);
|
return firstcode;
|
return firstcode;
|
}
|
}
|
if (sp > stack)
|
if (sp > stack)
|
return *--sp;
|
return *--sp;
|
|
|
while ((code = GetCode(src, code_size, FALSE)) >= 0) {
|
while ((code = GetCode(src, code_size, FALSE)) >= 0) {
|
if (code == clear_code) {
|
if (code == clear_code) {
|
for (i = 0; i < clear_code; ++i) {
|
for (i = 0; i < clear_code; ++i) {
|
table[0][i] = 0;
|
table[0][i] = 0;
|
table[1][i] = i;
|
table[1][i] = i;
|
}
|
}
|
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
table[0][i] = table[1][i] = 0;
|
table[0][i] = table[1][i] = 0;
|
code_size = set_code_size + 1;
|
code_size = set_code_size + 1;
|
max_code_size = 2 * clear_code;
|
max_code_size = 2 * clear_code;
|
max_code = clear_code + 2;
|
max_code = clear_code + 2;
|
sp = stack;
|
sp = stack;
|
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
return firstcode;
|
return firstcode;
|
} else if (code == end_code) {
|
} else if (code == end_code) {
|
int count;
|
int count;
|
unsigned char buf[260];
|
unsigned char buf[260];
|
|
|
if (ZeroDataBlock)
|
if (ZeroDataBlock)
|
return -2;
|
return -2;
|
|
|
while ((count = GetDataBlock(src, buf)) > 0);
|
while ((count = GetDataBlock(src, buf)) > 0);
|
|
|
if (count != 0) {
|
if (count != 0) {
|
/*
|
/*
|
* EPRINTF("missing EOD in data stream (common occurence)");
|
* EPRINTF("missing EOD in data stream (common occurence)");
|
*/
|
*/
|
}
|
}
|
return -2;
|
return -2;
|
}
|
}
|
incode = code;
|
incode = code;
|
|
|
if (code >= max_code) {
|
if (code >= max_code) {
|
*sp++ = firstcode;
|
*sp++ = firstcode;
|
code = oldcode;
|
code = oldcode;
|
}
|
}
|
while (code >= clear_code) {
|
while (code >= clear_code) {
|
*sp++ = table[1][code];
|
*sp++ = table[1][code];
|
if (code == table[0][code])
|
if (code == table[0][code])
|
EPRINTF("LoadGIF: circular table entry\n");
|
EPRINTF("LoadGIF: circular table entry\n");
|
code = table[0][code];
|
code = table[0][code];
|
}
|
}
|
|
|
*sp++ = firstcode = table[1][code];
|
*sp++ = firstcode = table[1][code];
|
|
|
if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
|
if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
|
table[0][code] = oldcode;
|
table[0][code] = oldcode;
|
table[1][code] = firstcode;
|
table[1][code] = firstcode;
|
++max_code;
|
++max_code;
|
if ((max_code >= max_code_size) &&
|
if ((max_code >= max_code_size) &&
|
(max_code_size < (1 << MAX_LWZ_BITS))) {
|
(max_code_size < (1 << MAX_LWZ_BITS))) {
|
max_code_size *= 2;
|
max_code_size *= 2;
|
++code_size;
|
++code_size;
|
}
|
}
|
}
|
}
|
oldcode = incode;
|
oldcode = incode;
|
|
|
if (sp > stack)
|
if (sp > stack)
|
return *--sp;
|
return *--sp;
|
}
|
}
|
return code;
|
return code;
|
}
|
}
|
|
|
static int
|
static int
|
ReadImage(buffer_t* src, PMWIMAGEHDR pimage, int len, int height, int cmapSize,
|
ReadImage(buffer_t* src, PMWIMAGEHDR pimage, int len, int height, int cmapSize,
|
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
int gray, int interlace, int ignore)
|
int gray, int interlace, int ignore)
|
{
|
{
|
unsigned char c;
|
unsigned char c;
|
int i, v;
|
int i, v;
|
int xpos = 0, ypos = 0, pass = 0;
|
int xpos = 0, ypos = 0, pass = 0;
|
|
|
/*
|
/*
|
* Initialize the compression routines
|
* Initialize the compression routines
|
*/
|
*/
|
if (!ReadOK(src, &c, 1)) {
|
if (!ReadOK(src, &c, 1)) {
|
EPRINTF("LoadGIF: EOF on image data\n");
|
EPRINTF("LoadGIF: EOF on image data\n");
|
return 0;
|
return 0;
|
}
|
}
|
if (LWZReadByte(src, TRUE, c) < 0) {
|
if (LWZReadByte(src, TRUE, c) < 0) {
|
EPRINTF("LoadGIF: error reading image\n");
|
EPRINTF("LoadGIF: error reading image\n");
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/*
|
/*
|
* If this is an "uninteresting picture" ignore it.
|
* If this is an "uninteresting picture" ignore it.
|
*/
|
*/
|
if (ignore) {
|
if (ignore) {
|
while (LWZReadByte(src, FALSE, c) >= 0);
|
while (LWZReadByte(src, FALSE, c) >= 0);
|
return 0;
|
return 0;
|
}
|
}
|
/*image = ImageNewCmap(len, height, cmapSize);*/
|
/*image = ImageNewCmap(len, height, cmapSize);*/
|
pimage->width = len;
|
pimage->width = len;
|
pimage->height = height;
|
pimage->height = height;
|
pimage->planes = 1;
|
pimage->planes = 1;
|
pimage->bpp = 8;
|
pimage->bpp = 8;
|
ComputePitch(8, len, &pimage->pitch, &pimage->bytesperpixel);
|
ComputePitch(8, len, &pimage->pitch, &pimage->bytesperpixel);
|
pimage->compression = 0;
|
pimage->compression = 0;
|
pimage->palsize = cmapSize;
|
pimage->palsize = cmapSize;
|
pimage->palette = malloc(256*sizeof(MWPALENTRY));
|
pimage->palette = malloc(256*sizeof(MWPALENTRY));
|
pimage->imagebits = malloc(height*pimage->pitch);
|
pimage->imagebits = malloc(height*pimage->pitch);
|
if(!pimage->imagebits || !pimage->palette)
|
if(!pimage->imagebits || !pimage->palette)
|
return 0;
|
return 0;
|
|
|
for (i = 0; i < cmapSize; i++) {
|
for (i = 0; i < cmapSize; i++) {
|
/*ImageSetCmap(image, i, cmap[CM_RED][i],
|
/*ImageSetCmap(image, i, cmap[CM_RED][i],
|
cmap[CM_GREEN][i], cmap[CM_BLUE][i]);*/
|
cmap[CM_GREEN][i], cmap[CM_BLUE][i]);*/
|
pimage->palette[i].r = cmap[CM_RED][i];
|
pimage->palette[i].r = cmap[CM_RED][i];
|
pimage->palette[i].g = cmap[CM_GREEN][i];
|
pimage->palette[i].g = cmap[CM_GREEN][i];
|
pimage->palette[i].b = cmap[CM_BLUE][i];
|
pimage->palette[i].b = cmap[CM_BLUE][i];
|
}
|
}
|
|
|
while ((v = LWZReadByte(src, FALSE, c)) >= 0) {
|
while ((v = LWZReadByte(src, FALSE, c)) >= 0) {
|
pimage->imagebits[ypos * pimage->pitch + xpos] = v;
|
pimage->imagebits[ypos * pimage->pitch + xpos] = v;
|
|
|
++xpos;
|
++xpos;
|
if (xpos == len) {
|
if (xpos == len) {
|
xpos = 0;
|
xpos = 0;
|
if (interlace) {
|
if (interlace) {
|
switch (pass) {
|
switch (pass) {
|
case 0:
|
case 0:
|
case 1:
|
case 1:
|
ypos += 8;
|
ypos += 8;
|
break;
|
break;
|
case 2:
|
case 2:
|
ypos += 4;
|
ypos += 4;
|
break;
|
break;
|
case 3:
|
case 3:
|
ypos += 2;
|
ypos += 2;
|
break;
|
break;
|
}
|
}
|
|
|
if (ypos >= height) {
|
if (ypos >= height) {
|
++pass;
|
++pass;
|
switch (pass) {
|
switch (pass) {
|
case 1:
|
case 1:
|
ypos = 4;
|
ypos = 4;
|
break;
|
break;
|
case 2:
|
case 2:
|
ypos = 2;
|
ypos = 2;
|
break;
|
break;
|
case 3:
|
case 3:
|
ypos = 1;
|
ypos = 1;
|
break;
|
break;
|
default:
|
default:
|
goto fini;
|
goto fini;
|
}
|
}
|
}
|
}
|
} else {
|
} else {
|
++ypos;
|
++ypos;
|
}
|
}
|
}
|
}
|
if (ypos >= height)
|
if (ypos >= height)
|
break;
|
break;
|
}
|
}
|
|
|
fini:
|
fini:
|
return 1;
|
return 1;
|
}
|
}
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_GIF_SUPPORT)*/
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_GIF_SUPPORT)*/
|
|
|
#if defined(HAVE_FILEIO) && defined(HAVE_PNM_SUPPORT)
|
#if defined(HAVE_FILEIO) && defined(HAVE_PNM_SUPPORT)
|
enum {
|
enum {
|
PNM_TYPE_NOTPNM,
|
PNM_TYPE_NOTPNM,
|
PNM_TYPE_PBM,
|
PNM_TYPE_PBM,
|
PNM_TYPE_PGM,
|
PNM_TYPE_PGM,
|
PNM_TYPE_PPM
|
PNM_TYPE_PPM
|
};
|
};
|
static int LoadPNM(buffer_t *src, PMWIMAGEHDR pimage)
|
static int LoadPNM(buffer_t *src, PMWIMAGEHDR pimage)
|
{
|
{
|
char buf[256], *p;
|
char buf[256], *p;
|
int type = PNM_TYPE_NOTPNM, binary = 0, gothdrs = 0, scale = 0;
|
int type = PNM_TYPE_NOTPNM, binary = 0, gothdrs = 0, scale = 0;
|
int ch, x = 0, y = 0, i, n, mask, col1, col2, col3;
|
int ch, x = 0, y = 0, i, n, mask, col1, col2, col3;
|
|
|
bseek(src, 0L, 0);
|
bseek(src, 0L, 0);
|
|
|
if(!bgets(src,buf, 4)) return 0;
|
if(!bgets(src,buf, 4)) return 0;
|
|
|
if(!strcmp("P1\n", buf)) type = PNM_TYPE_PBM;
|
if(!strcmp("P1\n", buf)) type = PNM_TYPE_PBM;
|
else if(!strcmp("P2\n", buf)) type = PNM_TYPE_PGM;
|
else if(!strcmp("P2\n", buf)) type = PNM_TYPE_PGM;
|
else if(!strcmp("P3\n", buf)) type = PNM_TYPE_PPM;
|
else if(!strcmp("P3\n", buf)) type = PNM_TYPE_PPM;
|
else if(!strcmp("P4\n", buf)) {
|
else if(!strcmp("P4\n", buf)) {
|
type = PNM_TYPE_PBM;
|
type = PNM_TYPE_PBM;
|
binary = 1;
|
binary = 1;
|
}
|
}
|
else if(!strcmp("P5\n", buf)) {
|
else if(!strcmp("P5\n", buf)) {
|
type = PNM_TYPE_PGM;
|
type = PNM_TYPE_PGM;
|
binary = 1;
|
binary = 1;
|
}
|
}
|
else if(!strcmp("P6\n", buf)) {
|
else if(!strcmp("P6\n", buf)) {
|
type = PNM_TYPE_PPM;
|
type = PNM_TYPE_PPM;
|
binary = 1;
|
binary = 1;
|
}
|
}
|
|
|
if(type == PNM_TYPE_NOTPNM) return 0;
|
if(type == PNM_TYPE_NOTPNM) return 0;
|
|
|
n = 0;
|
n = 0;
|
while((p = bgets(src, buf, 256))) {
|
while((p = bgets(src, buf, 256))) {
|
if(*buf == '#') continue;
|
if(*buf == '#') continue;
|
if(type == PNM_TYPE_PBM) {
|
if(type == PNM_TYPE_PBM) {
|
if(sscanf(buf, "%i %i", &pimage->width,
|
if(sscanf(buf, "%i %i", &pimage->width,
|
&pimage->height) == 2) {
|
&pimage->height) == 2) {
|
pimage->bpp = 1;
|
pimage->bpp = 1;
|
gothdrs = 1;
|
gothdrs = 1;
|
if(!(pimage->palette = malloc(
|
if(!(pimage->palette = malloc(
|
sizeof(MWPALENTRY) * 2))) {
|
sizeof(MWPALENTRY) * 2))) {
|
EPRINTF("Out of memory\n");
|
EPRINTF("Out of memory\n");
|
return 2;
|
return 2;
|
}
|
}
|
pimage->palsize = 2;
|
pimage->palsize = 2;
|
pimage->palette[0].r = 0xff;
|
pimage->palette[0].r = 0xff;
|
pimage->palette[0].g = 0xff;
|
pimage->palette[0].g = 0xff;
|
pimage->palette[0].b = 0xff;
|
pimage->palette[0].b = 0xff;
|
pimage->palette[1].r = 0;
|
pimage->palette[1].r = 0;
|
pimage->palette[1].g = 0;
|
pimage->palette[1].g = 0;
|
pimage->palette[1].b = 0;
|
pimage->palette[1].b = 0;
|
}
|
}
|
break;
|
break;
|
}
|
}
|
if((type == PNM_TYPE_PGM) || (type == PNM_TYPE_PPM)) {
|
if((type == PNM_TYPE_PGM) || (type == PNM_TYPE_PPM)) {
|
if(!n++) {
|
if(!n++) {
|
if(sscanf(buf, "%i %i", &pimage->width,
|
if(sscanf(buf, "%i %i", &pimage->width,
|
&pimage->height) != 2) break;
|
&pimage->height) != 2) break;
|
} else {
|
} else {
|
if(sscanf(buf, "%i", &i) != 1) break;
|
if(sscanf(buf, "%i", &i) != 1) break;
|
pimage->bpp = 24;
|
pimage->bpp = 24;
|
if(i > 255) {
|
if(i > 255) {
|
EPRINTF("LoadPNM: PPM files must be "
|
EPRINTF("LoadPNM: PPM files must be "
|
"24bpp\n");
|
"24bpp\n");
|
return 2;
|
return 2;
|
}
|
}
|
for(scale = 7, n = 2; scale; scale--, n *= 2)
|
for(scale = 7, n = 2; scale; scale--, n *= 2)
|
if(i < n) break;
|
if(i < n) break;
|
gothdrs = 1;
|
gothdrs = 1;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
if(!gothdrs) {
|
if(!gothdrs) {
|
EPRINTF("LoadPNM: bad image headers\n");
|
EPRINTF("LoadPNM: bad image headers\n");
|
if(pimage->palette) free(pimage->palette);
|
if(pimage->palette) free(pimage->palette);
|
return 2;
|
return 2;
|
}
|
}
|
|
|
pimage->planes = 1;
|
pimage->planes = 1;
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
ComputePitch(pimage->bpp, pimage->width, &pimage->pitch,
|
&pimage->bytesperpixel);
|
&pimage->bytesperpixel);
|
pimage->compression = MWIMAGE_RGB;
|
pimage->compression = MWIMAGE_RGB;
|
if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
|
if(!(pimage->imagebits = malloc(pimage->pitch * pimage->height))) {
|
EPRINTF("LoadPNM: couldn't allocate memory for image\n");
|
EPRINTF("LoadPNM: couldn't allocate memory for image\n");
|
if(pimage->palette) free(pimage->palette);
|
if(pimage->palette) free(pimage->palette);
|
return 2;
|
return 2;
|
}
|
}
|
|
|
p = pimage->imagebits;
|
p = pimage->imagebits;
|
|
|
if(type == PNM_TYPE_PBM) {
|
if(type == PNM_TYPE_PBM) {
|
if(binary) {
|
if(binary) {
|
x = 0;
|
x = 0;
|
y = 0;
|
y = 0;
|
while((ch = bgetc(src)) != EOF) {
|
while((ch = bgetc(src)) != EOF) {
|
for(i = 0; i < 8; i++) {
|
for(i = 0; i < 8; i++) {
|
mask = 0x80 >> i;
|
mask = 0x80 >> i;
|
if(ch & mask) *p |= mask;
|
if(ch & mask) *p |= mask;
|
else *p &= ~mask;
|
else *p &= ~mask;
|
if(++x == pimage->width) {
|
if(++x == pimage->width) {
|
if(++y == pimage->height)
|
if(++y == pimage->height)
|
return 1;
|
return 1;
|
p = pimage->imagebits - 1 +
|
p = pimage->imagebits - 1 +
|
(y * pimage->pitch);
|
(y * pimage->pitch);
|
x = 0;
|
x = 0;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
p++;
|
p++;
|
}
|
}
|
} else {
|
} else {
|
n = 0;
|
n = 0;
|
while((ch = bgetc(src)) != EOF) {
|
while((ch = bgetc(src)) != EOF) {
|
if(isspace(ch)) continue;
|
if(isspace(ch)) continue;
|
mask = 0x80 >> n;
|
mask = 0x80 >> n;
|
if(ch == '1') *p |= mask;
|
if(ch == '1') *p |= mask;
|
else if(ch == '0') *p &= ~mask;
|
else if(ch == '0') *p &= ~mask;
|
else goto baddata;
|
else goto baddata;
|
if(++n == 8) {
|
if(++n == 8) {
|
n = 0;
|
n = 0;
|
p++;
|
p++;
|
}
|
}
|
if(++x == pimage->width) {
|
if(++x == pimage->width) {
|
if(++y == pimage->height)
|
if(++y == pimage->height)
|
return 1;
|
return 1;
|
p = pimage->imagebits +
|
p = pimage->imagebits +
|
(y * pimage->pitch);
|
(y * pimage->pitch);
|
n = 0;
|
n = 0;
|
x = 0;
|
x = 0;
|
}
|
}
|
}
|
}
|
}
|
}
|
} else {
|
} else {
|
while(1) {
|
while(1) {
|
if(type == PNM_TYPE_PGM) {
|
if(type == PNM_TYPE_PGM) {
|
if(binary) {
|
if(binary) {
|
if((ch = bgetc(src)) == EOF)
|
if((ch = bgetc(src)) == EOF)
|
goto baddata;
|
goto baddata;
|
} else {
|
} else {
|
// if(fscanf(fp, "%i", &ch) != 1)
|
// if(fscanf(fp, "%i", &ch) != 1)
|
goto baddata;
|
goto baddata;
|
}
|
}
|
*p++ = ch << scale;
|
*p++ = ch << scale;
|
*p++ = ch << scale;
|
*p++ = ch << scale;
|
*p++ = ch << scale;
|
*p++ = ch << scale;
|
} else {
|
} else {
|
if(binary) {
|
if(binary) {
|
if(((col1 = bgetc(src)) == EOF) ||
|
if(((col1 = bgetc(src)) == EOF) ||
|
((col2 = bgetc(src)) == EOF) ||
|
((col2 = bgetc(src)) == EOF) ||
|
((col3 = bgetc(src)) == EOF))
|
((col3 = bgetc(src)) == EOF))
|
goto baddata;
|
goto baddata;
|
} else {
|
} else {
|
// if(fscanf(fp, "%i %i %i", &col1, &col2,
|
// if(fscanf(fp, "%i %i %i", &col1, &col2,
|
// &col3) != 3)
|
// &col3) != 3)
|
goto baddata;
|
goto baddata;
|
}
|
}
|
*p++ = col1 << scale;
|
*p++ = col1 << scale;
|
*p++ = col2 << scale;
|
*p++ = col2 << scale;
|
*p++ = col3 << scale;
|
*p++ = col3 << scale;
|
}
|
}
|
if(++x == pimage->width) {
|
if(++x == pimage->width) {
|
if(++y == pimage->height) return 1;
|
if(++y == pimage->height) return 1;
|
p = pimage->imagebits + (y * pimage->pitch);
|
p = pimage->imagebits + (y * pimage->pitch);
|
x = 0;
|
x = 0;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
baddata:
|
baddata:
|
EPRINTF("LoadPNM: bad image data\n");
|
EPRINTF("LoadPNM: bad image data\n");
|
free(pimage->imagebits);
|
free(pimage->imagebits);
|
if(pimage->palette) free(pimage->palette);
|
if(pimage->palette) free(pimage->palette);
|
return 2;
|
return 2;
|
}
|
}
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNM_SUPPORT) */
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_PNM_SUPPORT) */
|
|
|
#if defined(HAVE_FILEIO) && defined(HAVE_XPM_SUPPORT)
|
#if defined(HAVE_FILEIO) && defined(HAVE_XPM_SUPPORT)
|
struct xpm_cmap {
|
struct xpm_cmap {
|
char mapstr[3];
|
char mapstr[3];
|
long palette_entry;
|
long palette_entry;
|
long color;
|
long color;
|
struct xpm_cmap *next;
|
struct xpm_cmap *next;
|
};
|
};
|
|
|
|
|
static long XPM_parse_color(char *color)
|
static long XPM_parse_color(char *color)
|
{
|
{
|
/* This will parse the string into a color value of some sort */
|
/* This will parse the string into a color value of some sort */
|
|
|
if (color[0] != '#')
|
if (color[0] != '#')
|
{
|
{
|
if (!strcmp(color, "None"))
|
if (!strcmp(color, "None"))
|
return(-1); /* Transparent */
|
return(-1); /* Transparent */
|
else
|
else
|
return(0); /* If its an X color, then we bail */
|
return(0); /* If its an X color, then we bail */
|
}
|
}
|
else
|
else
|
{
|
{
|
/* This is ugly! */
|
/* This is ugly! */
|
|
|
char *sptr = color + 1;
|
char *sptr = color + 1;
|
char rstr[5], gstr[5], bstr[5];
|
char rstr[5], gstr[5], bstr[5];
|
long r,g,b;
|
long r,g,b;
|
|
|
switch(strlen(sptr))
|
switch(strlen(sptr))
|
{
|
{
|
case 6:
|
case 6:
|
return(strtol(sptr, NULL, 16));
|
return(strtol(sptr, NULL, 16));
|
|
|
case 9: /* RRRGGGBBB */
|
case 9: /* RRRGGGBBB */
|
strncpy(rstr, sptr, 3);
|
strncpy(rstr, sptr, 3);
|
strncpy(gstr, sptr + 3, 3);
|
strncpy(gstr, sptr + 3, 3);
|
strncpy(bstr, sptr + 6, 3);
|
strncpy(bstr, sptr + 6, 3);
|
|
|
rstr[3] = 0;
|
rstr[3] = 0;
|
gstr[3] = 0;
|
gstr[3] = 0;
|
bstr[3] = 0;
|
bstr[3] = 0;
|
|
|
r = strtol(rstr, NULL, 16) >> 4;
|
r = strtol(rstr, NULL, 16) >> 4;
|
g = strtol(gstr, NULL, 16) >> 4;
|
g = strtol(gstr, NULL, 16) >> 4;
|
b = strtol(bstr, NULL, 16) >> 4;
|
b = strtol(bstr, NULL, 16) >> 4;
|
|
|
return( (long) ( r << 16 | g << 8 | b));
|
return( (long) ( r << 16 | g << 8 | b));
|
|
|
case 12:
|
case 12:
|
strncpy(rstr, sptr, 4);
|
strncpy(rstr, sptr, 4);
|
strncpy(gstr, sptr + 4, 4);
|
strncpy(gstr, sptr + 4, 4);
|
strncpy(bstr, sptr + 8, 4);
|
strncpy(bstr, sptr + 8, 4);
|
|
|
rstr[4] = 0;
|
rstr[4] = 0;
|
gstr[4] = 0;
|
gstr[4] = 0;
|
bstr[4] = 0;
|
bstr[4] = 0;
|
|
|
r = strtol(rstr, NULL, 16) >> 8;
|
r = strtol(rstr, NULL, 16) >> 8;
|
g = strtol(gstr, NULL, 16) >> 8;
|
g = strtol(gstr, NULL, 16) >> 8;
|
b = strtol(bstr, NULL, 16) >> 8;
|
b = strtol(bstr, NULL, 16) >> 8;
|
|
|
return( (long) ( (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)));
|
return( (long) ( (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF)));
|
}
|
}
|
}
|
}
|
|
|
return(0);
|
return(0);
|
}
|
}
|
|
|
/* A series of status indicators that let us know whats going on */
|
/* A series of status indicators that let us know whats going on */
|
/* It could be an enum if you want */
|
/* It could be an enum if you want */
|
|
|
#define LOAD_HEADER 1
|
#define LOAD_HEADER 1
|
#define LOAD_COLORS 2
|
#define LOAD_COLORS 2
|
#define LOAD_PALETTE 3
|
#define LOAD_PALETTE 3
|
#define LOAD_PIXELS 4
|
#define LOAD_PIXELS 4
|
#define LOAD_DONE 5
|
#define LOAD_DONE 5
|
|
|
/* The magic that "should" indicate an XPM (does it really?) */
|
/* The magic that "should" indicate an XPM (does it really?) */
|
#define XPM_MAGIC "/* XPM */"
|
#define XPM_MAGIC "/* XPM */"
|
#define XPM_TRANSCOLOR 0x01000000
|
#define XPM_TRANSCOLOR 0x01000000
|
|
|
static int LoadXPM(buffer_t *src, PMWIMAGEHDR pimage, PSD psd)
|
static int LoadXPM(buffer_t *src, PMWIMAGEHDR pimage, PSD psd)
|
{
|
{
|
struct xpm_cmap *colorheap = 0; /* A "heap" of color structs */
|
struct xpm_cmap *colorheap = 0; /* A "heap" of color structs */
|
struct xpm_cmap *colormap[256]; /* A quick hash of 256 spots for colors */
|
struct xpm_cmap *colormap[256]; /* A quick hash of 256 spots for colors */
|
|
|
unsigned char *imageptr = 0;
|
unsigned char *imageptr = 0;
|
|
|
MWSCREENINFO sinfo;
|
MWSCREENINFO sinfo;
|
|
|
char xline[300];
|
char xline[300];
|
char dline[300];
|
char dline[300];
|
|
|
char *c;
|
char *c;
|
int a;
|
int a;
|
|
|
int col, row, colors, cpp;
|
int col, row, colors, cpp;
|
int in_color = 0;
|
int in_color = 0;
|
int read_xline = 0;
|
int read_xline = 0;
|
|
|
int status = LOAD_HEADER;
|
int status = LOAD_HEADER;
|
|
|
/* Very first thing, get the screen info */
|
/* Very first thing, get the screen info */
|
GdGetScreenInfo(psd, &sinfo);
|
GdGetScreenInfo(psd, &sinfo);
|
|
|
for(a = 0; a < 256; a++)
|
for(a = 0; a < 256; a++)
|
colormap[a] = 0;
|
colormap[a] = 0;
|
|
|
pimage->imagebits = NULL;
|
pimage->imagebits = NULL;
|
pimage->palette = NULL;
|
pimage->palette = NULL;
|
|
|
/* Start over at the beginning with the file */
|
/* Start over at the beginning with the file */
|
bseek(src, 0, SEEK_SET);
|
bseek(src, 0, SEEK_SET);
|
|
|
bgets(src, xline, 300);
|
bgets(src, xline, 300);
|
|
|
/* Chop the EOL */
|
/* Chop the EOL */
|
xline[strlen(xline) - 1] = 0;
|
xline[strlen(xline) - 1] = 0;
|
|
|
/* Check the magic */
|
/* Check the magic */
|
if (strncmp(xline, XPM_MAGIC, sizeof(XPM_MAGIC))) return(0);
|
if (strncmp(xline, XPM_MAGIC, sizeof(XPM_MAGIC))) return(0);
|
|
|
while(!beof(src))
|
while(!beof(src))
|
{
|
{
|
/* Get the next line from the file */
|
/* Get the next line from the file */
|
bgets(src,xline, 300);
|
bgets(src,xline, 300);
|
xline[strlen(xline) - 1] = 0;
|
xline[strlen(xline) - 1] = 0;
|
|
|
/* Check it out */
|
/* Check it out */
|
if (xline[0] == '/' && xline[1] == '*') /* Comment */
|
if (xline[0] == '/' && xline[1] == '*') /* Comment */
|
continue;
|
continue;
|
|
|
if (xline[0] != '\"')
|
if (xline[0] != '\"')
|
continue;
|
continue;
|
|
|
/* remove the quotes from the line */
|
/* remove the quotes from the line */
|
for(c = xline + 1, a = 0; *c != '\"' && *c != 0; c++, a++)
|
for(c = xline + 1, a = 0; *c != '\"' && *c != 0; c++, a++)
|
dline[a] = *c;
|
dline[a] = *c;
|
|
|
dline[a] = 0;
|
dline[a] = 0;
|
|
|
/* Is it the header? */
|
/* Is it the header? */
|
if (status == LOAD_HEADER)
|
if (status == LOAD_HEADER)
|
{
|
{
|
sscanf(dline, "%i %i %i %i", &col, &row, &colors, &cpp);
|
sscanf(dline, "%i %i %i %i", &col, &row, &colors, &cpp);
|
|
|
pimage->width = col;
|
pimage->width = col;
|
pimage->height = row;
|
pimage->height = row;
|
pimage->planes = 1;
|
pimage->planes = 1;
|
|
|
if (sinfo.bpp <= 8)
|
if (sinfo.bpp <= 8)
|
{
|
{
|
pimage->bpp = sinfo.bpp;
|
pimage->bpp = sinfo.bpp;
|
pimage->compression = 0;
|
pimage->compression = 0;
|
pimage->transcolor = -1;
|
pimage->transcolor = -1;
|
}
|
}
|
else
|
else
|
{
|
{
|
pimage->bpp = 32;
|
pimage->bpp = 32;
|
pimage->transcolor = XPM_TRANSCOLOR;
|
pimage->transcolor = XPM_TRANSCOLOR;
|
pimage->compression = MWIMAGE_BGR;
|
pimage->compression = MWIMAGE_BGR;
|
}
|
}
|
|
|
pimage->palsize = colors;
|
pimage->palsize = colors;
|
|
|
ComputePitch(pimage->bpp, col, &pimage->pitch, &pimage->bytesperpixel);
|
ComputePitch(pimage->bpp, col, &pimage->pitch, &pimage->bytesperpixel);
|
|
|
pimage->imagebits = malloc(pimage->pitch * pimage->height);
|
pimage->imagebits = malloc(pimage->pitch * pimage->height);
|
imageptr = (unsigned char *) pimage->imagebits;
|
imageptr = (unsigned char *) pimage->imagebits;
|
|
|
/* Allocate enough room for all the colors */
|
/* Allocate enough room for all the colors */
|
colorheap = (struct xpm_cmap *) malloc(colors * sizeof(struct xpm_cmap));
|
colorheap = (struct xpm_cmap *) malloc(colors * sizeof(struct xpm_cmap));
|
|
|
/* Allocate the palette space (if required) */
|
/* Allocate the palette space (if required) */
|
|
|
if (sinfo.bpp <= 8)
|
if (sinfo.bpp <= 8)
|
pimage->palette = malloc(256*sizeof(MWPALENTRY));
|
pimage->palette = malloc(256*sizeof(MWPALENTRY));
|
|
|
if (!colorheap)
|
if (!colorheap)
|
{
|
{
|
EPRINTF("Couldn't allocate any memory for the colors\n");
|
EPRINTF("Couldn't allocate any memory for the colors\n");
|
return(0);
|
return(0);
|
}
|
}
|
|
|
status = LOAD_COLORS;
|
status = LOAD_COLORS;
|
in_color = 0;
|
in_color = 0;
|
continue;
|
continue;
|
}
|
}
|
|
|
/* Are we in load colors? */
|
/* Are we in load colors? */
|
if (status == LOAD_COLORS)
|
if (status == LOAD_COLORS)
|
{
|
{
|
struct xpm_cmap *n;
|
struct xpm_cmap *n;
|
|
|
char tstr[5];
|
char tstr[5];
|
char cstr[256];
|
char cstr[256];
|
|
|
unsigned char m;
|
unsigned char m;
|
|
|
c = dline;
|
c = dline;
|
|
|
/* Go at at least 1 charater, and then count until we have
|
/* Go at at least 1 charater, and then count until we have
|
two spaces in a row */
|
two spaces in a row */
|
|
|
strncpy(tstr, c, cpp);
|
strncpy(tstr, c, cpp);
|
|
|
c += cpp;
|
c += cpp;
|
for(; *c == '\t' || *c == ' '; c++); /* Skip over whitespace */
|
for(; *c == '\t' || *c == ' '; c++); /* Skip over whitespace */
|
|
|
/* FIXME: We assume that a 'c' follows. What if it doesn't? */
|
/* FIXME: We assume that a 'c' follows. What if it doesn't? */
|
c +=2;
|
c +=2;
|
|
|
tstr[cpp] = 0;
|
tstr[cpp] = 0;
|
|
|
/* Now we put it into the array for easy lookup */
|
/* Now we put it into the array for easy lookup */
|
/* We base it off the first charater, even though */
|
/* We base it off the first charater, even though */
|
/* there may be up to 4 */
|
/* there may be up to 4 */
|
|
|
m = tstr[0];
|
m = tstr[0];
|
|
|
if (colormap[m])
|
if (colormap[m])
|
{
|
{
|
n = colormap[m];
|
n = colormap[m];
|
|
|
while(n->next) n = n->next;
|
while(n->next) n = n->next;
|
n->next = &colorheap[in_color];
|
n->next = &colorheap[in_color];
|
n = n->next;
|
n = n->next;
|
}
|
}
|
else
|
else
|
{
|
{
|
colormap[m] = &colorheap[in_color];
|
colormap[m] = &colorheap[in_color];
|
n = colormap[m];
|
n = colormap[m];
|
}
|
}
|
|
|
n->next = 0;
|
n->next = 0;
|
|
|
/* Record the string */
|
/* Record the string */
|
strncpy(n->mapstr, tstr, cpp);
|
strncpy(n->mapstr, tstr, cpp);
|
n->mapstr[cpp] = 0;
|
n->mapstr[cpp] = 0;
|
|
|
/* Now record the palette entry */
|
/* Now record the palette entry */
|
n->palette_entry = (long) in_color;
|
n->palette_entry = (long) in_color;
|
|
|
/* This is the color */
|
/* This is the color */
|
sscanf(c, "%65535s", cstr);
|
sscanf(c, "%65535s", cstr);
|
|
|
/* Turn it into a real value */
|
/* Turn it into a real value */
|
n->color = XPM_parse_color(cstr);
|
n->color = XPM_parse_color(cstr);
|
|
|
/* If we are in palette mode, then we need to */
|
/* If we are in palette mode, then we need to */
|
/* load the palette (duh..) */
|
/* load the palette (duh..) */
|
|
|
if (sinfo.bpp <= 8)
|
if (sinfo.bpp <= 8)
|
{
|
{
|
if (n->color == -1)
|
if (n->color == -1)
|
{
|
{
|
pimage->transcolor = in_color;
|
pimage->transcolor = in_color;
|
n->color = -1;
|
n->color = -1;
|
}
|
}
|
|
|
pimage->palette[in_color].r = (n->color >> 16) & 0xFF;
|
pimage->palette[in_color].r = (n->color >> 16) & 0xFF;
|
pimage->palette[in_color].g = (n->color >> 8) & 0xFF;
|
pimage->palette[in_color].g = (n->color >> 8) & 0xFF;
|
pimage->palette[in_color].b = n->color & 0xFF;
|
pimage->palette[in_color].b = n->color & 0xFF;
|
}
|
}
|
else
|
else
|
{
|
{
|
if (n->color == -1)
|
if (n->color == -1)
|
n->color = XPM_TRANSCOLOR;
|
n->color = XPM_TRANSCOLOR;
|
}
|
}
|
|
|
if (++in_color == colors)
|
if (++in_color == colors)
|
{
|
{
|
read_xline = 0;
|
read_xline = 0;
|
status = LOAD_PIXELS;
|
status = LOAD_PIXELS;
|
}
|
}
|
|
|
continue;
|
continue;
|
}
|
}
|
|
|
if (status == LOAD_PIXELS)
|
if (status == LOAD_PIXELS)
|
{
|
{
|
int bytecount = 0;
|
int bytecount = 0;
|
int bitcount = 0;
|
int bitcount = 0;
|
long dwordcolor = 0;
|
long dwordcolor = 0;
|
int i;
|
int i;
|
char pxlstr[3];
|
char pxlstr[3];
|
|
|
c = dline;
|
c = dline;
|
|
|
while(*c)
|
while(*c)
|
{
|
{
|
unsigned char z = 0;
|
unsigned char z = 0;
|
|
|
if (cpp == 1)
|
if (cpp == 1)
|
{
|
{
|
z = *c;
|
z = *c;
|
|
|
if (!colormap[z])
|
if (!colormap[z])
|
{
|
{
|
EPRINTF("No color entry for (%c)\n", z);
|
EPRINTF("No color entry for (%c)\n", z);
|
return(0);
|
return(0);
|
}
|
}
|
|
|
if (sinfo.bpp <= 8)
|
if (sinfo.bpp <= 8)
|
dwordcolor = (long) colormap[z]->palette_entry;
|
dwordcolor = (long) colormap[z]->palette_entry;
|
else
|
else
|
dwordcolor = colormap[z]->color;
|
dwordcolor = colormap[z]->color;
|
|
|
c++;
|
c++;
|
}
|
}
|
else
|
else
|
{
|
{
|
struct xpm_cmap *n;
|
struct xpm_cmap *n;
|
|
|
/* We grab the largest possible, and then compare */
|
/* We grab the largest possible, and then compare */
|
|
|
strncpy(pxlstr, c, cpp);
|
strncpy(pxlstr, c, cpp);
|
z = pxlstr[0];
|
z = pxlstr[0];
|
|
|
if (!colormap[z])
|
if (!colormap[z])
|
{
|
{
|
EPRINTF("No color entry for (%s)\n", pxlstr);
|
EPRINTF("No color entry for (%s)\n", pxlstr);
|
return(0);
|
return(0);
|
}
|
}
|
|
|
n = colormap[z];
|
n = colormap[z];
|
|
|
while(n)
|
while(n)
|
{
|
{
|
if (!strncmp(n->mapstr, pxlstr, cpp))
|
if (!strncmp(n->mapstr, pxlstr, cpp))
|
break;
|
break;
|
|
|
n = n->next;
|
n = n->next;
|
}
|
}
|
|
|
if (!n)
|
if (!n)
|
{
|
{
|
EPRINTF("No color found for (%s)\n", pxlstr);
|
EPRINTF("No color found for (%s)\n", pxlstr);
|
return(0);
|
return(0);
|
}
|
}
|
|
|
if (sinfo.bpp <= 8)
|
if (sinfo.bpp <= 8)
|
dwordcolor = (long) n->palette_entry;
|
dwordcolor = (long) n->palette_entry;
|
else
|
else
|
dwordcolor = n->color;
|
dwordcolor = n->color;
|
|
|
c += cpp;
|
c += cpp;
|
}
|
}
|
|
|
/*
|
/*
|
* This ugly thing is needed to ensure that we
|
* This ugly thing is needed to ensure that we
|
* work well in all modes.
|
* work well in all modes.
|
*/
|
*/
|
switch(sinfo.bpp)
|
switch(sinfo.bpp)
|
{
|
{
|
case 2:
|
case 2:
|
if (bitcount == 0)
|
if (bitcount == 0)
|
imageptr[0] = 0;
|
imageptr[0] = 0;
|
|
|
imageptr[0] |= (dwordcolor & 0x3) << (4 - bitcount);
|
imageptr[0] |= (dwordcolor & 0x3) << (4 - bitcount);
|
bitcount++;
|
bitcount++;
|
|
|
if (bitcount == 4)
|
if (bitcount == 4)
|
{
|
{
|
imageptr++;
|
imageptr++;
|
bytecount += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
bitcount = 0;
|
bitcount = 0;
|
}
|
}
|
|
|
break;
|
break;
|
|
|
case 4:
|
case 4:
|
if (bitcount == 0)
|
if (bitcount == 0)
|
imageptr[0] = 0;
|
imageptr[0] = 0;
|
|
|
imageptr[0] |= (dwordcolor & 0xF) << (2 - bitcount);
|
imageptr[0] |= (dwordcolor & 0xF) << (2 - bitcount);
|
bitcount++;
|
bitcount++;
|
|
|
if (bitcount == 2)
|
if (bitcount == 2)
|
{
|
{
|
imageptr++;
|
imageptr++;
|
bytecount += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
bitcount = 0;
|
bitcount = 0;
|
}
|
}
|
|
|
break;
|
break;
|
|
|
case 8:
|
case 8:
|
case 16:
|
case 16:
|
case 24:
|
case 24:
|
case 32:
|
case 32:
|
|
|
for(i = 0; i < pimage->bytesperpixel; i++)
|
for(i = 0; i < pimage->bytesperpixel; i++)
|
imageptr[i] = (dwordcolor >> (8 * i)) & 0xFF;
|
imageptr[i] = (dwordcolor >> (8 * i)) & 0xFF;
|
|
|
imageptr += pimage->bytesperpixel;
|
imageptr += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
break;
|
break;
|
|
|
#ifdef NOTUSED
|
#ifdef NOTUSED
|
case 8:
|
case 8:
|
imageptr[0] = (unsigned char) (dwordcolor & 0xFF);
|
imageptr[0] = (unsigned char) (dwordcolor & 0xFF);
|
imageptr += pimage->bytesperpixel;
|
imageptr += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
break;
|
break;
|
|
|
case 16:
|
case 16:
|
case 24:
|
case 24:
|
case 32:
|
case 32:
|
imageptr[0] = (unsigned char) (dwordcolor >> 24) & 0xFF;
|
imageptr[0] = (unsigned char) (dwordcolor >> 24) & 0xFF;
|
imageptr[1] = (unsigned char) (dwordcolor >> 16) & 0xFF;
|
imageptr[1] = (unsigned char) (dwordcolor >> 16) & 0xFF;
|
imageptr[2] = (unsigned char) (dwordcolor >> 8) & 0xFF;
|
imageptr[2] = (unsigned char) (dwordcolor >> 8) & 0xFF;
|
imageptr[3] = (unsigned char) (dwordcolor & 0xFF);
|
imageptr[3] = (unsigned char) (dwordcolor & 0xFF);
|
imageptr += pimage->bytesperpixel;
|
imageptr += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
bytecount += pimage->bytesperpixel;
|
break;
|
break;
|
#endif
|
#endif
|
}
|
}
|
}
|
}
|
|
|
/* Pad to the end of the line */
|
/* Pad to the end of the line */
|
if (bytecount < pimage->pitch)
|
if (bytecount < pimage->pitch)
|
for(i = 0; i < (pimage->pitch - bytecount); i++)
|
for(i = 0; i < (pimage->pitch - bytecount); i++)
|
*imageptr++ = 0x00;
|
*imageptr++ = 0x00;
|
|
|
read_xline++;
|
read_xline++;
|
|
|
if (read_xline == row)
|
if (read_xline == row)
|
status = LOAD_DONE;
|
status = LOAD_DONE;
|
|
|
continue;
|
continue;
|
}
|
}
|
}
|
}
|
|
|
free(colorheap);
|
free(colorheap);
|
|
|
if (status != LOAD_DONE)
|
if (status != LOAD_DONE)
|
return(-1);
|
return(-1);
|
return(1);
|
return(1);
|
}
|
}
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_XPM_SUPPORT)*/
|
#endif /* defined(HAVE_FILEIO) && defined(HAVE_XPM_SUPPORT)*/
|
|
|
#endif /* defined(HAVE_FILEIO)*/
|
#endif /* defined(HAVE_FILEIO)*/
|
|
|