Start changing GDISP images to use a simpler API based on GFILE's.

ugfx_release_2.6
inmarket 2014-02-07 01:36:31 +10:00
parent d667fab325
commit 71aeb15d58
2 changed files with 202 additions and 241 deletions

View File

@ -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);
#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 on a BaseFileStream (eg SDCard).
*
* @return TRUE if the IO open function succeeds
*
* @param[in] img The image structure
* @param[in] BaseFileStreamPtr A pointer to the (open) BaseFileStream object.
*
*/
bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr);
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 || 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
*
* @return TRUE if the IO open function succeeds
*
* @param[in] img The image structure
* @param[in] filename The filename to open
*
*/
bool_t gdispImageSetFileReader(gdispImage *img, const char *filename);
/* Old definition */
#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_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 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

View File

@ -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,129 +130,87 @@ 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;
}
static const gdispImageIOFunctions ImageBaseFileStreamFunctions =
{ ImageBaseFileStreamRead, ImageBaseFileStreamSeek, ImageBaseFileStreamClose };
bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
img->io.fns = &ImageBaseFileStreamFunctions;
#if GFILE_NEED_MEMFS
gdispImageError gdispImageOpenMemory(gdispImage *img, const void *memimage) {
img->io.fns = &ImageGFileFunctions;
img->io.pos = 0;
img->io.fd = BaseFileStreamPtr;
return TRUE;
}
#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;
img->io.fd = gfileOpenMemory(memimage, "rb");
if (!img->io.fd)
return GDISP_IMAGE_ERR_NOSUCHFILE;
return imageOpen(img);
}
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 };
bool_t gdispImageSetFileReader(gdispImage *img, const char *filename) {
img->io.fns = &ImageFileFunctions;
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;
#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 = gfileOpenMemory(memimage, "rb");
return img->io.fd != 0;
}
#endif
gdispImageError gdispImageOpen(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))
img->fns = 0;
return err;
}
img->io.fns->seek(&img->io, 0);
}
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
img->flags = 0;
img->fns = 0;
img->priv = 0;
return GDISP_IMAGE_ERR_BADFORMAT;
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;
}
#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;
}
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
void gdispImageClose(gdispImage *img) {
if (img->fns)
img->fns->close(img);