aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/gdisp/image.h190
-rw-r--r--src/gdisp/image.c225
2 files changed, 188 insertions, 227 deletions
diff --git a/include/gdisp/image.h b/include/gdisp/image.h
index ff2e9d85..f8c5f6a1 100644
--- a/include/gdisp/image.h
+++ b/include/gdisp/image.h
@@ -40,6 +40,7 @@ typedef uint16_t gdispImageError;
#define GDISP_IMAGE_ERR_UNSUPPORTED (GDISP_IMAGE_ERR_UNRECOVERABLE+3)
#define GDISP_IMAGE_ERR_UNSUPPORTED_OK 3
#define GDISP_IMAGE_ERR_NOMEMORY (GDISP_IMAGE_ERR_UNRECOVERABLE+4)
+ #define GDISP_IMAGE_ERR_NOSUCHFILE (GDISP_IMAGE_ERR_UNRECOVERABLE+5)
/**
* @brief Image flags
@@ -116,59 +117,78 @@ typedef struct gdispImage {
extern "C" {
#endif
- /**
- * @brief Sets the io fields in the image structure to routines
- * that support reading from an image stored in RAM or Flash.
- *
- * @return TRUE if the IO open function succeeds
- *
- * @param[in] img The image structure
- * @param[in] memimage A pointer to the image in RAM or Flash
- *
- * @note Always returns TRUE for a Memory Reader
- */
- bool_t gdispImageSetMemoryReader(gdispImage *img, const void *memimage);
+ 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);
+ #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);
+ #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);
+ #define gdispImageSetSimulFileReader(img, fname) gdispImageSetFileReader(img, fname)
+ #endif
- #if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
+ #if GFX_USE_GFILE || defined(__DOXYGEN__)
/**
- * @brief Sets the io fields in the image structure to routines
- * that support reading from an image stored on a BaseFileStream (eg SDCard).
+ * @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.
*
- * @return TRUE if the IO open function succeeds
+ * @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] BaseFileStreamPtr A pointer to the (open) BaseFileStream object.
+ * @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.
*/
- bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr);
+ gdispImageError gdispImageOpenFile(gdispImage *img, const char *filename);
#endif
-
- #if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX || defined(__DOXYGEN__)
+
+ #if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
/**
- * @brief Sets the io fields in the image structure to routines
- * that support reading from an image stored in Win32 simulators native
- * file system.
- * @pre Only available on the Win32 simulator
+ * @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.
*
- * @return TRUE if the IO open function succeeds
+ * @pre This only makes sense on the ChibiOS operating system.
*
- * @param[in] img The image structure
- * @param[in] filename The filename to open
+ * @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.
*/
- bool_t gdispImageSetFileReader(gdispImage *img, const char *filename);
- /* Old definition */
- #define gdispImageSetSimulFileReader(img, fname) gdispImageSetFileReader(img, fname)
+ gdispImageError gdispImageOpenBaseFileStream(gdispImage *img, void *BaseFileStreamPtr);
#endif
-
+
/**
- * @brief Open an image ready for drawing
+ * @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.
*
- * @param[in] img The image structure
- *
- * @pre The io fields should be filled in before calling gdispImageOpen()
+ * @param[in] img The image structure
+ * @param[in] memimage A pointer to the image bytes in memory
*
* @note This determines which decoder to use and then initialises all other fields
* in the gdispImage structure.
@@ -179,17 +199,17 @@ 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() can be called even after a failure to open the image to ensure
- * that the IO close routine gets called.
+ * @note @p gdispImageClose() should be called even after a partial failure in order to
+ * properly close the file.
*/
- gdispImageError gdispImageOpen(gdispImage *img);
-
+ gdispImageError gdispImageOpenMemory(gdispImage *img, const void *memimage);
+
/**
* @brief Close an image and release any dynamically allocated working storage.
*
* @param[in] img The image structure
*
- * @pre gdispImageOpen() must have returned successfully.
+ * @pre gdispImageOpenFile() must have returned successfully.
*
* @note Also calls the IO close function (if it hasn't already been called).
*/
@@ -282,94 +302,6 @@ extern "C" {
*/
delaytime_t gdispImageNext(gdispImage *img);
- #if GDISP_NEED_IMAGE_NATIVE
- /**
- * @brief The image drawing routines for a NATIVE format image.
- *
- * @note Only use these functions if you absolutely know the format
- * of the image you are decoding. Generally you should use the
- * generic functions and it will auto-detect the format.
- * @note A NATIVE format image is defined as an 8 byte header described below, immediately
- * followed by the bitmap data. The bitmap data is stored in the native format for
- * the display controller. If the pixel format specified in the header does not
- * match the controller native format then the image is rejected.
- * @note The 8 byte header:
- * { 'N', 'I', width.hi, width.lo, height.hi, height.lo, format.hi, format.lo }
- * The format word = GDISP_PIXELFORMAT
- * @{
- */
- gdispImageError gdispImageOpen_NATIVE(gdispImage *img);
- void gdispImageClose_NATIVE(gdispImage *img);
- gdispImageError gdispImageCache_NATIVE(gdispImage *img);
- gdispImageError gdispGImageDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
- delaytime_t gdispImageNext_NATIVE(gdispImage *img);
- /* @} */
- #endif
-
- #if GDISP_NEED_IMAGE_GIF
- /**
- * @brief The image drawing routines for a GIF image.
- * @note Only use these functions if you absolutely know the format
- * of the image you are decoding. Generally you should use the
- * generic functions and it will auto-detect the format.
- * @{
- */
- gdispImageError gdispImageOpen_GIF(gdispImage *img);
- void gdispImageClose_GIF(gdispImage *img);
- gdispImageError gdispImageCache_GIF(gdispImage *img);
- gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
- delaytime_t gdispImageNext_GIF(gdispImage *img);
- /* @} */
- #endif
-
- #if GDISP_NEED_IMAGE_BMP
- /**
- * @brief The image drawing routines for a BMP image.
- * @note Only use these functions if you absolutely know the format
- * of the image you are decoding. Generally you should use the
- * generic functions and it will auto-detect the format.
- * @{
- */
- gdispImageError gdispImageOpen_BMP(gdispImage *img);
- void gdispImageClose_BMP(gdispImage *img);
- gdispImageError gdispImageCache_BMP(gdispImage *img);
- gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
- delaytime_t gdispImageNext_BMP(gdispImage *img);
- /* @} */
- #endif
-
- #if GDISP_NEED_IMAGE_JPG
- /**
- * @brief The image drawing routines for a JPG image.
- * @note Only use these functions if you absolutely know the format
- * of the image you are decoding. Generally you should use the
- * generic functions and it will auto-detect the format.
- * @{
- */
- gdispImageError gdispImageOpen_JPG(gdispImage *img);
- void gdispImageClose_JPG(gdispImage *img);
- gdispImageError gdispImageCache_JPG(gdispImage *img);
- gdispImageError gdispGImageDraw_JPG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
- delaytime_t gdispImageNext_JPG(gdispImage *img);
- /* @} */
- #endif
-
- #if GDISP_NEED_IMAGE_PNG
- /**
- * @brief The image drawing routines for a PNG image.
- * @note Only use these functions if you absolutely know the format
- * of the image you are decoding. Generally you should use the
- * generic functions and it will auto-detect the format.
- * @{
- */
- gdispImageError gdispImageOpen_PNG(gdispImage *img);
- void gdispImageClose_PNG(gdispImage *img);
- gdispImageError gdispImageCache_PNG(gdispImage *img);
- gdispImageError gdispGImageDraw_PNG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
- delaytime_t gdispImageNext_PNG(gdispImage *img);
- /* @} */
- #endif
-
#ifdef __cplusplus
}
#endif
diff --git a/src/gdisp/image.c b/src/gdisp/image.c
index 62af0aeb..dd219289 100644
--- a/src/gdisp/image.c
+++ b/src/gdisp/image.c
@@ -18,6 +18,77 @@
#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);
+ extern gdispImageError gdispImageCache_NATIVE(gdispImage *img);
+ extern gdispImageError gdispGImageDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
+ extern delaytime_t gdispImageNext_NATIVE(gdispImage *img);
+#endif
+
+#if GDISP_NEED_IMAGE_GIF
+ extern gdispImageError gdispImageOpen_GIF(gdispImage *img);
+ extern void gdispImageClose_GIF(gdispImage *img);
+ extern gdispImageError gdispImageCache_GIF(gdispImage *img);
+ extern gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
+ extern delaytime_t gdispImageNext_GIF(gdispImage *img);
+#endif
+
+#if GDISP_NEED_IMAGE_BMP
+ extern gdispImageError gdispImageOpen_BMP(gdispImage *img);
+ extern void gdispImageClose_BMP(gdispImage *img);
+ extern gdispImageError gdispImageCache_BMP(gdispImage *img);
+ extern gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
+ extern delaytime_t gdispImageNext_BMP(gdispImage *img);
+#endif
+
+#if GDISP_NEED_IMAGE_JPG
+ extern gdispImageError gdispImageOpen_JPG(gdispImage *img);
+ extern void gdispImageClose_JPG(gdispImage *img);
+ extern gdispImageError gdispImageCache_JPG(gdispImage *img);
+ extern gdispImageError gdispGImageDraw_JPG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
+ extern delaytime_t gdispImageNext_JPG(gdispImage *img);
+#endif
+
+#if GDISP_NEED_IMAGE_PNG
+ extern gdispImageError gdispImageOpen_PNG(gdispImage *img);
+ extern void gdispImageClose_PNG(gdispImage *img);
+ extern gdispImageError gdispImageCache_PNG(gdispImage *img);
+ extern gdispImageError gdispGImageDraw_PNG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
+ extern delaytime_t gdispImageNext_PNG(gdispImage *img);
+#endif
+
/* The structure defining the routines for image drawing */
typedef struct gdispImageHandlers {
gdispImageError (*open)(gdispImage *img); /* The open function */
@@ -59,128 +130,86 @@ static gdispImageHandlers ImageHandlers[] = {
#endif
};
-static size_t ImageMemoryRead(struct gdispImageIO *pio, void *buf, size_t len) {
- if (pio->fd == (void *)-1) return 0;
- memcpy(buf, ((const char *)pio->fd)+pio->pos, len);
+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;
}
-static void ImageMemorySeek(struct gdispImageIO *pio, size_t pos) {
- if (pio->fd == (void *)-1) return;
- pio->pos = pos;
+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 ImageMemoryClose(struct gdispImageIO *pio) {
- pio->fd = (void *)-1;
+static void ImageGFileClose(struct gdispImageIO *pio) {
+ if (!pio->fd) return;
+ gfileClose((GFILE *)pio->fd);
+ pio->fd = 0;
pio->pos = 0;
}
-static const gdispImageIOFunctions ImageMemoryFunctions =
- { ImageMemoryRead, ImageMemorySeek, ImageMemoryClose };
+static const gdispImageIOFunctions ImageGFileFunctions =
+ { ImageGFileRead, ImageGFileSeek, ImageGFileClose };
-bool_t gdispImageSetMemoryReader(gdispImage *img, const void *memimage) {
- img->io.fns = &ImageMemoryFunctions;
- img->io.pos = 0;
- img->io.fd = memimage;
- return TRUE;
-}
-
-#if GFX_USE_OS_CHIBIOS
- static size_t ImageBaseFileStreamRead(struct gdispImageIO *pio, void *buf, size_t len) {
- if (pio->fd == (void *)-1) return 0;
- len = chSequentialStreamRead(((BaseFileStream *)pio->fd), (uint8_t *)buf, len);
- pio->pos += len;
- return len;
- }
-
- static void ImageBaseFileStreamSeek(struct gdispImageIO *pio, size_t pos) {
- if (pio->fd == (void *)-1) return;
- if (pio->pos != pos) {
- chFileStreamSeek(((BaseFileStream *)pio->fd), pos);
- pio->pos = pos;
- }
- }
-
- static void ImageBaseFileStreamClose(struct gdispImageIO *pio) {
- if (pio->fd == (void *)-1) return;
- chFileStreamClose(((BaseFileStream *)pio->fd));
- pio->fd = (void *)-1;
- pio->pos = 0;
+#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);
}
- static const gdispImageIOFunctions ImageBaseFileStreamFunctions =
- { ImageBaseFileStreamRead, ImageBaseFileStreamSeek, ImageBaseFileStreamClose };
-
- bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
- img->io.fns = &ImageBaseFileStreamFunctions;
+ 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 = BaseFileStreamPtr;
- return TRUE;
+ img->io.fd = gfileOpenMemory(memimage, "rb");
+ return img->io.fd != 0;
}
#endif
-#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX
- #include <stdio.h>
-
- static size_t ImageFileRead(struct gdispImageIO *pio, void *buf, size_t len) {
- if (!pio->fd) return 0;
- len = fread(buf, 1, len, (FILE *)pio->fd);
- if ((int)len < 0) len = 0;
- pio->pos += len;
- return len;
- }
-
- static void ImageFileSeek(struct gdispImageIO *pio, size_t pos) {
- if (!pio->fd) return;
- if (pio->pos != pos) {
- fseek((FILE *)pio->fd, pos, SEEK_SET);
- pio->pos = pos;
- }
- }
-
- static void ImageFileClose(struct gdispImageIO *pio) {
- if (!pio->fd) return;
- fclose((FILE *)pio->fd);
- pio->fd = 0;
- pio->pos = 0;
- }
-
- static const gdispImageIOFunctions ImageFileFunctions =
- { ImageFileRead, ImageFileSeek, ImageFileClose };
+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);
+}
- bool_t gdispImageSetFileReader(gdispImage *img, const char *filename) {
- img->io.fns = &ImageFileFunctions;
+#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;
- #if defined(WIN32) || GFX_USE_OS_WIN32
- img->io.fd = (void *)fopen(filename, "rb");
- #else
- img->io.fd = (void *)fopen(filename, "r");
- #endif
-
+ img->io.fd = gfileOpen(filename, "rb");
return img->io.fd != 0;
}
#endif
-gdispImageError gdispImageOpen(gdispImage *img) {
- gdispImageError err;
+#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;
+ }
- 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))
- img->fns = 0;
- return err;
- }
- img->io.fns->seek(&img->io, 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);
}
- img->type = GDISP_IMAGE_TYPE_UNKNOWN;
- img->flags = 0;
- img->fns = 0;
- img->priv = 0;
- return GDISP_IMAGE_ERR_BADFORMAT;
-}
+
+#endif
void gdispImageClose(gdispImage *img) {
if (img->fns)