From 695bcbee5b84cd2e152baca91c58bdc2e971b0d1 Mon Sep 17 00:00:00 2001 From: inmarket Date: Fri, 7 Feb 2014 14:06:08 +1000 Subject: [PATCH] Update GDISP image code to fully use new GFILE's --- include/gdisp/image.h | 131 ++++++++++++++++---------------- src/gdisp/image.c | 157 ++++++++++++++------------------------- src/gdisp/image_bmp.c | 93 ++++++++++++----------- src/gdisp/image_gif.c | 105 +++++++++++++------------- src/gdisp/image_native.c | 29 ++++---- 5 files changed, 229 insertions(+), 286 deletions(-) diff --git a/include/gdisp/image.h b/include/gdisp/image.h index f8c5f6a1..bcf9c497 100644 --- a/include/gdisp/image.h +++ b/include/gdisp/image.h @@ -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. diff --git a/src/gdisp/image.c b/src/gdisp/image.c index dd219289..2b8395b0 100644 --- a/src/gdisp/image.c +++ b/src/gdisp/image.c @@ -16,39 +16,6 @@ #if GFX_USE_GDISP && GDISP_NEED_IMAGE -#include - -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) { diff --git a/src/gdisp/image_bmp.c b/src/gdisp/image_bmp.c index 158d6edc..8ff40ca0 100644 --- a/src/gdisp/image_bmp.c +++ b/src/gdisp/image_bmp.c @@ -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; diff --git a/src/gdisp/image_gif.c b/src/gdisp/image_gif.c index 1ff72ff0..06f4ef6a 100644 --- a/src/gdisp/image_gif.c +++ b/src/gdisp/image_gif.c @@ -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 diff --git a/src/gdisp/image_native.c b/src/gdisp/image_native.c index 7f249ae8..c458531e 100644 --- a/src/gdisp/image_native.c +++ b/src/gdisp/image_native.c @@ -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);