Update GDISP image code to fully use new GFILE's

ugfx_release_2.6
inmarket 2014-02-07 14:06:08 +10:00
parent a86bab4a77
commit 695bcbee5b
5 changed files with 229 additions and 286 deletions

View File

@ -104,10 +104,10 @@ typedef struct gdispImage {
gdispImageFlags flags; /* @< The image flags */
color_t bgcolor; /* @< The default background color */
coord_t width, height; /* @< The image dimensions */
gdispImageIO io; /* @< The image IO functions */
GFILE * f; /* @< The underlying GFILE */
#if GDISP_NEED_IMAGE_ACCOUNTING
uint32_t memused; /* @< How much RAM is currently allocated */
uint32_t maxmemused; /* @< How much RAM has been allocated (maximum) */
uint32_t memused; /* @< How much RAM is currently allocated */
uint32_t maxmemused; /* @< How much RAM has been allocated (maximum) */
#endif
const struct gdispImageHandlers * fns; /* @< Don't mess with this! */
struct gdispImagePrivate * priv; /* @< Don't mess with this! */
@ -117,78 +117,28 @@ typedef struct gdispImage {
extern "C" {
#endif
gdispImageError DEPRECATED("If possible please use gdispImageOpenFile(), gdispImageOpenMemory() or gdispImageOpenBaseFileStream() instead")
gdispImageOpen(gdispImage *img);
bool_t DEPRECATED("Use gdispImageOpenMemory() instead. GFX_USE_GFILE, GFILE_NEED_MEMFS must also be TRUE") gdispImageSetMemoryReader(gdispImage *img, const void *memimage);
/**
* Deprecated Functions.
*/
gdispImageError DEPRECATED("Use gdispImageOpenGFile() instead") gdispImageOpen(gdispImage *img);
bool_t DEPRECATED("Use gdispImageOpenMemory() instead") gdispImageSetMemoryReader(gdispImage *img, const void *memimage);
#if GFX_USE_OS_CHIBIOS
bool_t DEPRECATED("Use gdispImageOpenBaseFileStream() instead. GFX_USE_GFILE, GFILE_NEED_CHIBIOSFS must also be TRUE") gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr);
bool_t DEPRECATED("Use gdispImageOpenBaseFileStream() instead") gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr);
#endif
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX
bool_t DEPRECATED("Please use gdispImageOpenFile() instead. GFX_USE_GFILE must also be TRUE")
gdispImageSetFileReader(gdispImage *img, const char *filename);
bool_t DEPRECATED("Please use gdispImageOpenFile() instead") gdispImageSetFileReader(gdispImage *img, const char *filename);
#define gdispImageSetSimulFileReader(img, fname) gdispImageSetFileReader(img, fname)
#endif
#if GFX_USE_GFILE || defined(__DOXYGEN__)
/**
* @brief Open an image in a file and get it ready for drawing
* @details Determine the image format and get ready to decode the first image frame
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
* @pre GFX_USE_GFILE must be TRUE and you must have included the file-system support
* you want to use.
*
* @param[in] img The image structure
* @param[in] filename The filename to open
*
* @note This determines which decoder to use and then initialises all other fields
* in the gdispImage structure.
* @note The image background color is set to White.
* @note There are three types of return - everything OK, partial success and unrecoverable
* failures. For everything OK it returns GDISP_IMAGE_ERR_OK. A partial success can
* be distinguished from a unrecoverable failure by testing the GDISP_IMAGE_ERR_UNRECOVERABLE
* bit in the error code.
* A partial success return code means an image can still be drawn but perhaps with
* reduced functionality eg only the first page of a multi-page image.
* @note @p gdispImageClose() should be called even after a partial failure in order to
* properly close the file.
*/
gdispImageError gdispImageOpenFile(gdispImage *img, const char *filename);
#endif
#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
/**
* @brief Open an image in a ChibiOS basefilestream and get it ready for drawing
* @details Determine the image format and get ready to decode the first image frame
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
* @pre This only makes sense on the ChibiOS operating system.
*
* @param[in] img The image structure
* @param[in] BaseFileStreamPtr A pointer to an open BaseFileStream
*
* @note This determines which decoder to use and then initialises all other fields
* in the gdispImage structure.
* @note The image background color is set to White.
* @note There are three types of return - everything OK, partial success and unrecoverable
* failures. For everything OK it returns GDISP_IMAGE_ERR_OK. A partial success can
* be distinguished from a unrecoverable failure by testing the GDISP_IMAGE_ERR_UNRECOVERABLE
* bit in the error code.
* A partial success return code means an image can still be drawn but perhaps with
* reduced functionality eg only the first page of a multi-page image.
* @note @p gdispImageClose() should be called even after a partial failure in order to
* properly close the file.
*/
gdispImageError gdispImageOpenBaseFileStream(gdispImage *img, void *BaseFileStreamPtr);
#endif
/**
* @brief Open an image in memory and get it ready for drawing
* @brief Open an image using an open GFILE and get it ready for drawing
* @details Determine the image format and get ready to decode the first image frame
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
*
* @param[in] img The image structure
* @param[in] memimage A pointer to the image bytes in memory
* @param[in] f The open GFILE stream.
*
* @pre The GFILE must be open for reading.
*
* @note This determines which decoder to use and then initialises all other fields
* in the gdispImage structure.
@ -199,10 +149,55 @@ extern "C" {
* bit in the error code.
* A partial success return code means an image can still be drawn but perhaps with
* reduced functionality eg only the first page of a multi-page image.
* @note @p gdispImageClose() should be called even after a partial failure in order to
* properly close the file.
* @note @p gdispImageClose() should be called when finished with the image. This will close
* the image and its underlying GFILE file. Note that images opened with partial success
* (eg GDISP_IMAGE_ERR_UNSUPPORTED_OK)
* still need to be closed when you are finished with them.
*/
gdispImageError gdispImageOpenMemory(gdispImage *img, const void *memimage);
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *filename);
/**
* @brief Open an image in a file and get it ready for drawing
* @details Determine the image format and get ready to decode the first image frame
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
* @pre You must have included the file-system support into GFILE that you want to use.
*
* @param[in] img The image structure
* @param[in] filename The filename to open
*
* @note This function just opens the GFILE using the filename and passes it to @p gdispImageOpenGFile().
*/
#define gdispImageOpenFile(img, filename) gdispImageOpenGFile((img), gfileOpen((filename), "rb"))
/**
* @brief Open an image in a ChibiOS basefilestream and get it ready for drawing
* @details Determine the image format and get ready to decode the first image frame
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
* @pre GFILE_NEED_CHIBIOSFS and GFX_USE_OS_CHIBIOS must be TRUE. This only makes sense on the ChibiOS
* operating system.
*
* @param[in] img The image structure
* @param[in] BaseFileStreamPtr A pointer to an open BaseFileStream
*
* @note This function just opens the GFILE using the basefilestream and passes it to @p gdispImageOpenGFile().
*/
#define gdispImageOpenBaseFileStream(img, BaseFileStreamPtr) gdispImageOpenGFile((img), gfileOpenBaseFileStream((BaseFileStreamPtr), "rb"))
/**
* @brief Open an image in memory and get it ready for drawing
* @details Determine the image format and get ready to decode the first image frame
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
*
* @pre GFILE_NEED_MEMFS must be TRUE
*
* @param[in] img The image structure
* @param[in] ptr A pointer to the image bytes in memory
*
* @note This function just opens the GFILE using the basefilestream and passes it to @p gdispImageOpenGFile().
*/
#define gdispImageOpenMemory(img, ptr) gdispImageOpenGFile((img), gfileOpenMemory((void *)(ptr), "rb"))
/**
* @brief Close an image and release any dynamically allocated working storage.

View File

@ -16,39 +16,6 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE
#include <string.h>
static gdispImageError imageOpen(gdispImage *img) {
gdispImageError err;
img->bgcolor = White;
for(img->fns = ImageHandlers; img->fns < ImageHandlers+sizeof(ImageHandlers)/sizeof(ImageHandlers[0]); img->fns++) {
err = img->fns->open(img);
if (err != GDISP_IMAGE_ERR_BADFORMAT) {
if (!(err & GDISP_IMAGE_ERR_UNRECOVERABLE))
return err;
goto unrecoverable;
}
img->io.fns->seek(&img->io, 0);
}
err = GDISP_IMAGE_ERR_BADFORMAT;
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
unrecoverable:
img->fns->close(img);
img->flags = 0;
img->fns = 0;
img->priv = 0;
return err;
}
gdispImageError
DEPRECATED("If possible please use gdispImageOpenFile(), gdispImageOpenMemory() or gdispImageOpenBaseFileStream() instead")
gdispImageOpen(gdispImage *img) {
return imageOpen(img);
}
#if GDISP_NEED_IMAGE_NATIVE
extern gdispImageError gdispImageOpen_NATIVE(gdispImage *img);
extern void gdispImageClose_NATIVE(gdispImage *img);
@ -130,92 +97,76 @@ static gdispImageHandlers ImageHandlers[] = {
#endif
};
static size_t ImageGFileRead(struct gdispImageIO *pio, void *buf, size_t len) {
if (!pio->fd) return 0;
len = gfileRead((GFILE *)pio->fd, buf, len);
if ((int)len < 0) len = 0;
pio->pos += len;
return len;
gdispImageError
DEPRECATED("Use gdispImageOpenGFile() instead")
gdispImageOpen(gdispImage *img) {
return gdispImageOpenGFile(img, img->f);
}
static void ImageGFileSeek(struct gdispImageIO *pio, size_t pos) {
if (!pio->fd) return;
if (pio->pos != pos) {
gfileSetPos((GFILE *)pio->fd, pos);
pio->pos = pos;
}
}
static void ImageGFileClose(struct gdispImageIO *pio) {
if (!pio->fd) return;
gfileClose((GFILE *)pio->fd);
pio->fd = 0;
pio->pos = 0;
}
static const gdispImageIOFunctions ImageGFileFunctions =
{ ImageGFileRead, ImageGFileSeek, ImageGFileClose };
#if GFILE_NEED_MEMFS
gdispImageError gdispImageOpenMemory(gdispImage *img, const void *memimage) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = gfileOpenMemory(memimage, "rb");
if (!img->io.fd)
return GDISP_IMAGE_ERR_NOSUCHFILE;
return imageOpen(img);
}
bool_t DEPRECATED("Use gdispImageOpenMemory() instead. GFX_USE_GFILE, GFILE_NEED_MEMFS must also be TRUE") gdispImageSetMemoryReader(gdispImage *img, const void *memimage) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = gfileOpenMemory(memimage, "rb");
return img->io.fd != 0;
bool_t
DEPRECATED("Use gdispImageOpenMemory() instead")
gdispImageSetMemoryReader(gdispImage *img, const void *memimage) {
img->f = gfileOpenMemory((void *)memimage, "rb");
return img->f != 0;
}
#endif
gdispImageError gdispImageOpenFile(gdispImage *img, const char *filename) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = gfileOpen(filename, "rb");
if (!img->io.fd)
return GDISP_IMAGE_ERR_NOSUCHFILE;
return imageOpen(img);
}
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX
bool_t DEPRECATED("Please use gdispImageOpenFile() instead. GFX_USE_GFILE must also be TRUE") gdispImageSetFileReader(gdispImage *img, const char *filename) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = gfileOpen(filename, "rb");
return img->io.fd != 0;
bool_t
DEPRECATED("Use gdispImageOpenFile() instead")
gdispImageSetFileReader(gdispImage *img, const char *filename) {
img->f = gfileOpen(filename, "rb");
return img->f != 0;
}
#endif
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
bool_t DEPRECATED("Use gdispImageOpenBaseFileStream() instead. GFX_USE_GFILE, GFILE_NEED_CHIBIOSFS must also be TRUE") gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = gfileOpenBaseFileStream(BaseFileStreamPtr, "rb");
return img->io.fd != 0;
bool_t
DEPRECATED("Use gdispImageOpenBaseFileStream() instead")
gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
img->f = gfileOpenBaseFileStream(BaseFileStreamPtr, "rb");
return img->f != 0;
}
gdispImageError gdispImageOpenBaseFileStream(gdispImage *img, void *BaseFileStreamPtr) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = gfileOpenBaseFileStream(BaseFileStreamPtr, "rb");
if (!img->io.fd)
return GDISP_IMAGE_ERR_NOSUCHFILE;
return imageOpen(img);
}
#endif
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f) {
gdispImageError err;
if (!f)
return GDISP_IMAGE_ERR_NOSUCHFILE;
img->f = f;
img->bgcolor = White;
for(img->fns = ImageHandlers; img->fns < ImageHandlers+sizeof(ImageHandlers)/sizeof(ImageHandlers[0]); img->fns++) {
err = img->fns->open(img);
if (err != GDISP_IMAGE_ERR_BADFORMAT) {
if ((err & GDISP_IMAGE_ERR_UNRECOVERABLE))
goto unrecoverable;
// Everything is possible
return err;
}
// Try the next decoder
gfileSetPos(img->f, 0);
}
err = GDISP_IMAGE_ERR_BADFORMAT;
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
unrecoverable:
gfileClose(img->f);
img->f = 0;
img->flags = 0;
img->fns = 0;
img->priv = 0;
return err;
}
void gdispImageClose(gdispImage *img) {
if (img->fns)
img->fns->close(img);
else
img->io.fns->close(&img->io);
gfileClose(img->f);
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
img->flags = 0;
img->fns = 0;
@ -223,7 +174,7 @@ void gdispImageClose(gdispImage *img) {
}
bool_t gdispImageIsOpen(gdispImage *img) {
return img->type != GDISP_IMAGE_TYPE_UNKNOWN && img->fns != 0;
return img->fns != 0;
}
void gdispImageSetBgColor(gdispImage *img, color_t bgcolor) {

View File

@ -118,6 +118,19 @@ typedef struct gdispImagePrivate {
pixel_t buf[BLIT_BUFFER_SIZE];
} gdispImagePrivate;
void gdispImageClose_BMP(gdispImage *img) {
if (img->priv) {
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
if (img->priv->palette)
gdispImageFree(img, (void *)img->priv->palette, img->priv->palsize*sizeof(color_t));
#endif
if (img->priv->frame0cache)
gdispImageFree(img, (void *)img->priv->frame0cache, img->width*img->height*sizeof(pixel_t));
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
}
gdispImageError gdispImageOpen_BMP(gdispImage *img) {
gdispImagePrivate *priv;
uint8_t hdr[2];
@ -126,7 +139,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
uint32_t offsetColorTable;
/* Read the file identifier */
if (img->io.fns->read(&img->io, hdr, 2) != 2)
if (gfileRead(img->f, hdr, 2) != 2)
return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
/* Process the BITMAPFILEHEADER structure */
@ -154,18 +167,18 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
#endif
/* Skip the size field and the 2 reserved fields */
if (img->io.fns->read(&img->io, priv->buf, 8) != 8)
if (gfileRead(img->f, priv->buf, 8) != 8)
goto baddatacleanup;
/* Get the offset to the bitmap data */
if (img->io.fns->read(&img->io, &priv->frame0pos, 4) != 4)
if (gfileRead(img->f, &priv->frame0pos, 4) != 4)
goto baddatacleanup;
CONVERT_FROM_DWORD_LE(priv->frame0pos);
/* Process the BITMAPCOREHEADER structure */
/* Get the offset to the colour data */
if (img->io.fns->read(&img->io, &offsetColorTable, 4) != 4)
if (gfileRead(img->f, &offsetColorTable, 4) != 4)
goto baddatacleanup;
CONVERT_FROM_DWORD_LE(offsetColorTable);
offsetColorTable += 14; // Add the size of the BITMAPFILEHEADER
@ -175,7 +188,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
img->priv->bmpflags |= BMP_V2;
// Read the header
if (img->io.fns->read(&img->io, priv->buf, 12-4) != 12-4)
if (gfileRead(img->f, priv->buf, 12-4) != 12-4)
goto baddatacleanup;
// Get the width
img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
@ -224,7 +237,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
priv->bmpflags |= BMP_V4;
// Read the header
if (img->io.fns->read(&img->io, priv->buf, 40-4) != 40-4)
if (gfileRead(img->f, priv->buf, 40-4) != 40-4)
goto baddatacleanup;
// Get the width
adword = *(uint32_t *)(((uint8_t *)priv->buf)+0);
@ -327,18 +340,18 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
/* Load the palette tables */
if (priv->bmpflags & BMP_PALETTE) {
img->io.fns->seek(&img->io, offsetColorTable);
gfileSetPos(img->f, offsetColorTable);
if (!(priv->palette = (color_t *)gdispImageAlloc(img, priv->palsize*sizeof(color_t))))
return GDISP_IMAGE_ERR_NOMEMORY;
if (priv->bmpflags & BMP_V2) {
for(aword = 0; aword < priv->palsize; aword++) {
if (img->io.fns->read(&img->io, &priv->buf, 3) != 3) goto baddatacleanup;
if (gfileRead(img->f, &priv->buf, 3) != 3) goto baddatacleanup;
priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[2], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[0]);
}
} else {
for(aword = 0; aword < priv->palsize; aword++) {
if (img->io.fns->read(&img->io, &priv->buf, 4) != 4) goto baddatacleanup;
if (gfileRead(img->f, &priv->buf, 4) != 4) goto baddatacleanup;
priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[2], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[0]);
}
}
@ -349,15 +362,15 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
#if GDISP_NEED_IMAGE_BMP_16 || GDISP_NEED_IMAGE_BMP_32
/* Load the bit masks */
if (priv->bmpflags & BMP_COMP_MASK) {
img->io.fns->seek(&img->io, offsetColorTable);
if (img->io.fns->read(&img->io, &priv->maskred, 4) != 4) goto baddatacleanup;
gfileSetPos(img->f, offsetColorTable);
if (gfileRead(img->f, &priv->maskred, 4) != 4) goto baddatacleanup;
CONVERT_FROM_DWORD_LE(priv->maskred);
if (img->io.fns->read(&img->io, &priv->maskgreen, 4) != 4) goto baddatacleanup;
if (gfileRead(img->f, &priv->maskgreen, 4) != 4) goto baddatacleanup;
CONVERT_FROM_DWORD_LE(priv->maskgreen);
if (img->io.fns->read(&img->io, &priv->maskblue, 4) != 4) goto baddatacleanup;
if (gfileRead(img->f, &priv->maskblue, 4) != 4) goto baddatacleanup;
CONVERT_FROM_DWORD_LE(priv->maskblue);
if (priv->bmpflags & BMP_V4) {
if (img->io.fns->read(&img->io, &priv->maskalpha, 4) != 4) goto baddatacleanup;
if (gfileRead(img->f, &priv->maskalpha, 4) != 4) goto baddatacleanup;
CONVERT_FROM_DWORD_LE(priv->maskalpha);
} else
priv->maskalpha = 0;
@ -419,20 +432,6 @@ unsupportedcleanup:
return GDISP_IMAGE_ERR_UNSUPPORTED; // Not supported
}
void gdispImageClose_BMP(gdispImage *img) {
if (img->priv) {
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
if (img->priv->palette)
gdispImageFree(img, (void *)img->priv->palette, img->priv->palsize*sizeof(color_t));
#endif
if (img->priv->frame0cache)
gdispImageFree(img, (void *)img->priv->frame0cache, img->width*img->height*sizeof(pixel_t));
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
img->io.fns->close(&img->io);
}
static coord_t getPixels(gdispImage *img, coord_t x) {
gdispImagePrivate * priv;
color_t * pc;
@ -454,7 +453,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
len = 0;
while(x < img->width && len <= BLIT_BUFFER_SIZE-32) {
if (img->io.fns->read(&img->io, &b, 4) != 4)
if (gfileRead(img->f, &b, 4) != 4)
return 0;
for(m=0x80; m; m >>= 1, pc++)
@ -499,7 +498,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
return len;
} else if (priv->bmpflags & BMP_RLE_ABS) {
while (priv->rlerun && len <= BLIT_BUFFER_SIZE-2 && x < img->width) {
if (img->io.fns->read(&img->io, &b, 1) != 1)
if (gfileRead(img->f, &b, 1) != 1)
return 0;
*pc++ = priv->palette[b[0] >> 4];
priv->rlerun--;
@ -514,8 +513,8 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
}
if (priv->rlerun) // Return if we have more run to do
return len;
if ((img->io.pos - priv->frame0pos)&1) { // Make sure we are on a word boundary
if (img->io.fns->read(&img->io, &b, 1) != 1)
if ((gfileGetPos(img->f) - priv->frame0pos)&1) { // Make sure we are on a word boundary
if (gfileRead(img->f, &b, 1) != 1)
return 0;
}
}
@ -524,7 +523,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
priv->bmpflags &= ~(BMP_RLE_ENC|BMP_RLE_ABS);
// There are always at least 2 bytes in an RLE code
if (img->io.fns->read(&img->io, &b, 2) != 2)
if (gfileRead(img->f, &b, 2) != 2)
return 0;
if (b[0]) { // Encoded mode
@ -541,7 +540,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
return len;
} else if (b[1] == 2) { // Delta x, y
// There are always at least 2 bytes in an RLE code
if (img->io.fns->read(&img->io, &b, 2) != 2)
if (gfileRead(img->f, &b, 2) != 2)
return 0;
priv->rlerun = b[0] + (uint16_t)b[1] * img->width;
priv->rlecode = 0; // Who knows what color this should really be
@ -559,7 +558,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
uint8_t b[4];
while(x < img->width && len <= BLIT_BUFFER_SIZE-8) {
if (img->io.fns->read(&img->io, &b, 4) != 4)
if (gfileRead(img->f, &b, 4) != 4)
return 0;
*pc++ = priv->palette[b[0] >> 4];
@ -599,7 +598,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
return len;
} else if (priv->bmpflags & BMP_RLE_ABS) {
while (priv->rlerun && len < BLIT_BUFFER_SIZE && x < img->width) {
if (img->io.fns->read(&img->io, &b, 1) != 1)
if (gfileRead(img->f, &b, 1) != 1)
return 0;
*pc++ = priv->palette[b[0]];
priv->rlerun--;
@ -608,8 +607,8 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
}
if (priv->rlerun) // Return if we have more run to do
return len;
if ((img->io.pos - priv->frame0pos)&1) { // Make sure we are on a word boundary
if (img->io.fns->read(&img->io, &b, 1) != 1)
if ((gfileGetPos(img->f) - priv->frame0pos)&1) { // Make sure we are on a word boundary
if (gfileRead(img->f, &b, 1) != 1)
return 0;
}
}
@ -618,7 +617,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
priv->bmpflags &= ~(BMP_RLE_ENC|BMP_RLE_ABS);
// There are always at least 2 bytes in an RLE code
if (img->io.fns->read(&img->io, &b, 2) != 2)
if (gfileRead(img->f, &b, 2) != 2)
return 0;
if (b[0]) { // Encoded mode
@ -635,7 +634,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
return len;
} else if (b[1] == 2) { // Delta x, y
// There are always at least 2 bytes in an RLE code
if (img->io.fns->read(&img->io, &b, 2) != 2)
if (gfileRead(img->f, &b, 2) != 2)
return GDISP_IMAGE_ERR_BADDATA;
priv->rlerun = b[0] + (uint16_t)b[1] * img->width;
priv->rlecode = 0; // Who knows what color this should really be
@ -653,7 +652,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
uint8_t b[4];
while(x < img->width && len <= BLIT_BUFFER_SIZE-4) {
if (img->io.fns->read(&img->io, &b, 4) != 4)
if (gfileRead(img->f, &b, 4) != 4)
return 0;
*pc++ = priv->palette[b[0]];
@ -675,7 +674,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
color_t r, g, b;
while(x < img->width && len <= BLIT_BUFFER_SIZE-2) {
if (img->io.fns->read(&img->io, &w, 4) != 4)
if (gfileRead(img->f, &w, 4) != 4)
return 0;
CONVERT_FROM_WORD_LE(w[0]);
CONVERT_FROM_WORD_LE(w[1]);
@ -720,7 +719,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
uint8_t b[3];
while(x < img->width && len < BLIT_BUFFER_SIZE) {
if (img->io.fns->read(&img->io, &b, 3) != 3)
if (gfileRead(img->f, &b, 3) != 3)
return 0;
*pc++ = RGB2COLOR(b[2], b[1], b[0]);
x++;
@ -729,7 +728,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
if (x >= img->width) {
// Make sure we have read a multiple of 4 bytes for the line
if ((x & 3) && img->io.fns->read(&img->io, &b, x & 3) != (x & 3))
if ((x & 3) && gfileRead(img->f, &b, x & 3) != (x & 3))
return 0;
}
}
@ -743,7 +742,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
color_t r, g, b;
while(x < img->width && len < BLIT_BUFFER_SIZE) {
if (img->io.fns->read(&img->io, &dw, 4) != 4)
if (gfileRead(img->f, &dw, 4) != 4)
return 0;
CONVERT_FROM_DWORD_LE(dw);
if (priv->shiftred < 0)
@ -791,7 +790,7 @@ gdispImageError gdispImageCache_BMP(gdispImage *img) {
return GDISP_IMAGE_ERR_NOMEMORY;
/* Read the entire bitmap into cache */
img->io.fns->seek(&img->io, priv->frame0pos);
gfileSetPos(img->f, priv->frame0pos);
#if GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8_RLE
priv->rlerun = 0;
priv->rlecode = 0;
@ -847,7 +846,7 @@ gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coo
}
/* Start decoding from the beginning */
img->io.fns->seek(&img->io, priv->frame0pos);
gfileSetPos(img->f, priv->frame0pos);
#if GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8_RLE
priv->rlerun = 0;
priv->rlecode = 0;

View File

@ -172,9 +172,9 @@ static gdispImageError startDecode(gdispImage *img) {
// Local palette
decode->maxpixel = priv->frame.palsize-1;
decode->palette = (color_t *)(decode+1);
img->io.fns->seek(&img->io, priv->frame.pospal);
gfileSetPos(img->f, priv->frame.pospal);
for(cnt = 0; cnt < priv->frame.palsize; cnt++) {
if (img->io.fns->read(&img->io, &decode->buf, 3) != 3)
if (gfileRead(img->f, &decode->buf, 3) != 3)
goto baddatacleanup;
decode->palette[cnt] = RGB2COLOR(decode->buf[0], decode->buf[1], decode->buf[2]);
}
@ -188,8 +188,8 @@ static gdispImageError startDecode(gdispImage *img) {
}
// Get the initial lzw code size and values
img->io.fns->seek(&img->io, priv->frame.posimg);
if (img->io.fns->read(&img->io, &decode->bitsperpixel, 1) != 1 || decode->bitsperpixel >= MAX_CODE_BITS)
gfileSetPos(img->f, priv->frame.posimg);
if (gfileRead(img->f, &decode->bitsperpixel, 1) != 1 || decode->bitsperpixel >= MAX_CODE_BITS)
goto baddatacleanup;
decode->code_clear = 1 << decode->bitsperpixel;
decode->code_eof = decode->code_clear + 1;
@ -273,8 +273,8 @@ static uint16_t getbytes(gdispImage *img) {
// Get another code - a code is made up of decode->bitspercode bits.
while (decode->shiftbits < decode->bitspercode) {
// Get a byte - we may have to start a new data block
if ((!decode->blocksz && (img->io.fns->read(&img->io, &decode->blocksz, 1) != 1 || !decode->blocksz))
|| img->io.fns->read(&img->io, &bdata, 1) != 1) {
if ((!decode->blocksz && (gfileRead(img->f, &decode->blocksz, 1) != 1 || !decode->blocksz))
|| gfileRead(img->f, &bdata, 1) != 1) {
// Pretend we got the EOF code - some encoders seem to just end the file
decode->code_last = decode->code_eof;
return cnt;
@ -302,8 +302,8 @@ static uint16_t getbytes(gdispImage *img) {
if (code == decode->code_eof) {
// Skip to the end of the data blocks
do {
img->io.fns->seek(&img->io, img->io.pos+decode->blocksz);
} while (img->io.fns->read(&img->io, &decode->blocksz, 1) == 1 && decode->blocksz);
gfileSetPos(img->f, gfileGetPos(img->f)+decode->blocksz);
} while (gfileRead(img->f, &decode->blocksz, 1) == 1 && decode->blocksz);
// Mark the end
decode->code_last = decode->code_eof;
@ -398,8 +398,8 @@ static gdispImageError initFrame(gdispImage *img) {
priv->dispose.height = priv->frame.height;
// Check for a cached version of this image
for(cache=priv->cache; cache && cache->frame.posstart <= img->io.pos; cache=cache->next) {
if (cache->frame.posstart == img->io.pos) {
for(cache=priv->cache; cache && cache->frame.posstart <= (size_t)gfileGetPos(img->f); cache=cache->next) {
if (cache->frame.posstart == (size_t)gfileGetPos(img->f)) {
priv->frame = cache->frame;
priv->curcache = cache;
return GDISP_IMAGE_ERR_OK;
@ -408,20 +408,20 @@ static gdispImageError initFrame(gdispImage *img) {
// Get ready for a new image
priv->curcache = 0;
priv->frame.posstart = img->io.pos;
priv->frame.posstart = gfileGetPos(img->f);
priv->frame.flags = 0;
priv->frame.delay = 0;
priv->frame.palsize = 0;
// Process blocks until we reach the image descriptor
while(1) {
if (img->io.fns->read(&img->io, &blocktype, 1) != 1)
if (gfileRead(img->f, &blocktype, 1) != 1)
return GDISP_IMAGE_ERR_BADDATA;
switch(blocktype) {
case 0x2C: //',' - IMAGE_DESC_RECORD_TYPE;
// Read the Image Descriptor
if (img->io.fns->read(&img->io, priv->buf, 9) != 9)
if (gfileRead(img->f, priv->buf, 9) != 9)
return GDISP_IMAGE_ERR_BADDATA;
priv->frame.x = *(uint16_t *)(((uint8_t *)priv->buf)+0);
CONVERT_FROM_WORD_LE(priv->frame.x);
@ -437,7 +437,7 @@ static gdispImageError initFrame(gdispImage *img) {
priv->frame.flags |= GIFL_INTERLACE;
// We are ready to go for the actual palette read and image decode
priv->frame.pospal = img->io.pos;
priv->frame.pospal = gfileGetPos(img->f);
priv->frame.posimg = priv->frame.pospal+priv->frame.palsize*3;
priv->frame.posend = 0;
@ -448,13 +448,13 @@ static gdispImageError initFrame(gdispImage *img) {
case 0x21: //'!' - EXTENSION_RECORD_TYPE;
// Read the extension type
if (img->io.fns->read(&img->io, &blocktype, 1) != 1)
if (gfileRead(img->f, &blocktype, 1) != 1)
return GDISP_IMAGE_ERR_BADDATA;
switch(blocktype) {
case 0xF9: // EXTENSION - Graphics Control Block
// Read the GCB
if (img->io.fns->read(&img->io, priv->buf, 6) != 6)
if (gfileRead(img->f, priv->buf, 6) != 6)
return GDISP_IMAGE_ERR_BADDATA;
// Check we have read a 4 byte data block and a data block terminator (0)
if (((uint8_t *)priv->buf)[0] != 4 || ((uint8_t *)priv->buf)[5] != 0)
@ -485,7 +485,7 @@ static gdispImageError initFrame(gdispImage *img) {
if (priv->flags & GIF_LOOP)
goto skipdatablocks;
// Read the Application header
if (img->io.fns->read(&img->io, priv->buf, 16) != 16)
if (gfileRead(img->f, priv->buf, 16) != 16)
return GDISP_IMAGE_ERR_BADDATA;
// Check we have read a 11 byte data block
if (((uint8_t *)priv->buf)[0] != 11 && ((uint8_t *)priv->buf)[12] != 3)
@ -516,11 +516,11 @@ static gdispImageError initFrame(gdispImage *img) {
// We don't understand this extension - just skip it by skipping data blocks
skipdatablocks:
while(1) {
if (img->io.fns->read(&img->io, &blocksz, 1) != 1)
if (gfileRead(img->f, &blocksz, 1) != 1)
return GDISP_IMAGE_ERR_BADDATA;
if (!blocksz)
break;
img->io.fns->seek(&img->io, img->io.pos + blocksz);
gfileSetPos(img->f, gfileGetPos(img->f) + blocksz);
}
break;
}
@ -537,7 +537,7 @@ static gdispImageError initFrame(gdispImage *img) {
}
// Seek back to frame0
img->io.fns->seek(&img->io, priv->frame0pos);
gfileSetPos(img->f, priv->frame0pos);
return GDISP_IMAGE_LOOP;
default: // UNDEFINED_RECORD_TYPE;
@ -546,13 +546,34 @@ static gdispImageError initFrame(gdispImage *img) {
}
}
void gdispImageClose_GIF(gdispImage *img) {
gdispImagePrivate * priv;
imgcache * cache;
imgcache * ncache;
priv = img->priv;
if (priv) {
// Free any stored frames
cache = priv->cache;
while(cache) {
ncache = cache->next;
gdispImageFree(img, (void *)cache, sizeof(imgcache)+cache->frame.width*cache->frame.height+cache->frame.palsize*sizeof(color_t));
cache = ncache;
}
if (priv->palette)
gdispImageFree(img, (void *)priv->palette, priv->palsize*sizeof(color_t));
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
}
gdispImageError gdispImageOpen_GIF(gdispImage *img) {
gdispImagePrivate *priv;
uint8_t hdr[6];
uint16_t aword;
/* Read the file identifier */
if (img->io.fns->read(&img->io, hdr, 6) != 6)
if (gfileRead(img->f, hdr, 6) != 6)
return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
/* Process the GIFFILEHEADER structure */
@ -580,7 +601,7 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
/* Process the Screen Descriptor structure */
// Read the screen descriptor
if (img->io.fns->read(&img->io, priv->buf, 7) != 7)
if (gfileRead(img->f, priv->buf, 7) != 7)
goto baddatacleanup;
// Get the width
img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
@ -596,7 +617,7 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
goto nomemcleanup;
// Read the global palette
for(aword = 0; aword < priv->palsize; aword++) {
if (img->io.fns->read(&img->io, &priv->buf, 3) != 3)
if (gfileRead(img->f, &priv->buf, 3) != 3)
goto baddatacleanup;
priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[0], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[2]);
}
@ -604,7 +625,7 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
priv->bgcolor = ((uint8_t *)priv->buf)[5];
// Save the fram0pos
priv->frame0pos = img->io.pos;
priv->frame0pos = gfileGetPos(img->f);
// Read the first frame descriptor
switch(initFrame(img)) {
@ -628,28 +649,6 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
}
}
void gdispImageClose_GIF(gdispImage *img) {
gdispImagePrivate * priv;
imgcache * cache;
imgcache * ncache;
priv = img->priv;
if (priv) {
// Free any stored frames
cache = priv->cache;
while(cache) {
ncache = cache->next;
gdispImageFree(img, (void *)cache, sizeof(imgcache)+cache->frame.width*cache->frame.height+cache->frame.palsize*sizeof(color_t));
cache = ncache;
}
if (priv->palette)
gdispImageFree(img, (void *)priv->palette, priv->palsize*sizeof(color_t));
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
img->io.fns->close(&img->io);
}
gdispImageError gdispImageCache_GIF(gdispImage *img) {
gdispImagePrivate * priv;
imgcache * cache;
@ -786,7 +785,7 @@ gdispImageError gdispImageCache_GIF(gdispImage *img) {
}
// We could be pedantic here but extra bytes won't hurt us
while(getbytes(img));
priv->frame.posend = cache->frame.posend = img->io.pos;
priv->frame.posend = cache->frame.posend = gfileGetPos(img->f);
// Save everything
priv->curcache = cache;
@ -1150,7 +1149,7 @@ gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coo
}
// We could be pedantic here but extra bytes won't hurt us
while (getbytes(img));
priv->frame.posend = img->io.pos;
priv->frame.posend = gfileGetPos(img->f);
stopDecode(img);
return GDISP_IMAGE_ERR_OK;
@ -1173,19 +1172,19 @@ delaytime_t gdispImageNext_GIF(gdispImage *img) {
// We need to get to the end of this frame
if (!priv->frame.posend) {
// We don't know where the end of the frame is yet - find it!
img->io.fns->seek(&img->io, priv->frame.posimg+1); // Skip the code size byte too
gfileSetPos(img->f, priv->frame.posimg+1); // Skip the code size byte too
while(1) {
if (img->io.fns->read(&img->io, &blocksz, 1) != 1)
if (gfileRead(img->f, &blocksz, 1) != 1)
return TIME_INFINITE;
if (!blocksz)
break;
img->io.fns->seek(&img->io, img->io.pos + blocksz);
gfileSetPos(img->f, gfileGetPos(img->f) + blocksz);
}
priv->frame.posend = img->io.pos;
priv->frame.posend = gfileGetPos(img->f);
}
// Seek to the end of this frame
img->io.fns->seek(&img->io, priv->frame.posend);
gfileSetPos(img->f, priv->frame.posend);
// Read the next frame descriptor
for(blocksz=0; blocksz < 2; blocksz++) { // 2 loops max to prevent cycling forever with a bad file

View File

@ -33,11 +33,20 @@ typedef struct gdispImagePrivate {
pixel_t buf[BLIT_BUFFER_SIZE];
} gdispImagePrivate;
void gdispImageClose_NATIVE(gdispImage *img) {
if (img->priv) {
if (img->priv->frame0cache)
gdispImageFree(img, (void *)img->priv->frame0cache, img->width * img->height * sizeof(pixel_t));
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
}
gdispImageError gdispImageOpen_NATIVE(gdispImage *img) {
uint8_t hdr[HEADER_SIZE];
/* Read the 8 byte header */
if (img->io.fns->read(&img->io, hdr, 8) != 8)
if (gfileRead(img->f, hdr, 8) != 8)
return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
if (hdr[0] != 'N' || hdr[1] != 'I')
@ -60,16 +69,6 @@ gdispImageError gdispImageOpen_NATIVE(gdispImage *img) {
return GDISP_IMAGE_ERR_OK;
}
void gdispImageClose_NATIVE(gdispImage *img) {
if (img->priv) {
if (img->priv->frame0cache)
gdispImageFree(img, (void *)img->priv->frame0cache, img->width * img->height * sizeof(pixel_t));
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
img->priv = 0;
}
img->io.fns->close(&img->io);
}
gdispImageError gdispImageCache_NATIVE(gdispImage *img) {
size_t len;
@ -84,8 +83,8 @@ gdispImageError gdispImageCache_NATIVE(gdispImage *img) {
return GDISP_IMAGE_ERR_NOMEMORY;
/* Read the entire bitmap into cache */
img->io.fns->seek(&img->io, FRAME0POS);
if (img->io.fns->read(&img->io, img->priv->frame0cache, len) != len)
gfileSetPos(img->f, FRAME0POS);
if (gfileRead(img->f, img->priv->frame0cache, len) != len)
return GDISP_IMAGE_ERR_BADDATA;
return GDISP_IMAGE_ERR_OK;
@ -112,12 +111,12 @@ gdispImageError gdispImageGDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x,
/* Cycle through the lines */
for(;cy;cy--, y++) {
/* Move to the start of the line */
img->io.fns->seek(&img->io, pos);
gfileSetPos(img->f, pos);
/* Draw the line in chunks using BitBlt */
for(mx = x, mcx = cx; mcx > 0; mcx -= len, mx += len) {
// Read the data
len = img->io.fns->read(&img->io,
len = gfileRead(img->f,
img->priv->buf,
mcx > BLIT_BUFFER_SIZE ? (BLIT_BUFFER_SIZE*sizeof(pixel_t)) : (mcx * sizeof(pixel_t)))
/ sizeof(pixel_t);