aboutsummaryrefslogtreecommitdiffstats
path: root/src/gdisp/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdisp/image.c')
-rw-r--r--src/gdisp/image.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/src/gdisp/image.c b/src/gdisp/image.c
new file mode 100644
index 00000000..616aab11
--- /dev/null
+++ b/src/gdisp/image.c
@@ -0,0 +1,210 @@
+/*
+ ChibiOS/GFX - Copyright (C) 2012, 2013
+ Joel Bodenmann aka Tectu <joel@unormal.org>
+
+ This file is part of ChibiOS/GFX.
+
+ ChibiOS/GFX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS/GFX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file src/gdisp/image.c
+ * @brief GDISP generic image code.
+ */
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP && GDISP_NEED_IMAGE
+
+/* The structure defining the routines for image drawing */
+typedef struct gdispImageHandlers {
+ gdispImageError (*open)(gdispImage *img); /* The open function */
+ void (*close)(gdispImage *img); /* The close function */
+ gdispImageError (*cache)(gdispImage *img); /* The cache function */
+ gdispImageError (*draw)(gdispImage *img,
+ coord_t x, coord_t y,
+ coord_t cx, coord_t cy,
+ coord_t sx, coord_t sy); /* The draw function */
+ systime_t (*next)(gdispImage *img); /* The next frame function */
+} gdispImageHandlers;
+
+static gdispImageHandlers ImageHandlers[] = {
+ #if GDISP_NEED_IMAGE_NATIVE
+ { gdispImageOpen_NATIVE, gdispImageClose_NATIVE,
+ gdispImageCache_NATIVE, gdispImageDraw_NATIVE, gdispImageNext_NATIVE,
+ },
+ #endif
+ #if GDISP_NEED_IMAGE_GIF
+ { gdispImageOpen_GIF, gdispImageClose_GIF,
+ gdispImageCache_GIF, gdispImageDraw_GIF, gdispImageNext_GIF,
+ },
+ #endif
+ #if GDISP_NEED_IMAGE_BMP
+ { gdispImageOpen_BMP, gdispImageClose_BMP,
+ gdispImageCache_BMP, gdispImageDraw_BMP, gdispImageNext_BMP,
+ },
+ #endif
+ #if GDISP_NEED_IMAGE_JPG
+ { gdispImageOpen_JPG, gdispImageClose_JPG,
+ gdispImageCache_JPG, gdispImageDraw_JPG, gdispImageNext_JPG,
+ },
+ #endif
+ #if GDISP_NEED_IMAGE_PNG
+ { gdispImageOpen_PNG, gdispImageClose_PNG,
+ gdispImageCache_PNG, gdispImageDraw_PNG, gdispImageNext_PNG,
+ },
+ #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);
+ 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 ImageMemoryClose(struct gdispImageIO *pio) {
+ pio->fd = (void *)-1;
+ pio->pos = 0;
+}
+
+static const gdispImageIOFunctions ImageMemoryFunctions =
+ { ImageMemoryRead, ImageMemorySeek, ImageMemoryClose };
+
+bool_t gdispImageSetMemoryReader(gdispImage *img, const char *memimage) {
+ img->io.fns = &ImageMemoryFunctions;
+ img->io.pos = 0;
+ img->io.fd = (void *)memimage;
+ return TRUE;
+}
+
+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;
+ img->io.pos = 0;
+ img->io.fd = BaseFileStreamPtr;
+ return TRUE;
+}
+
+#if defined(WIN32)
+ #include <fcntl.h>
+
+ static size_t ImageSimulFileRead(struct gdispImageIO *pio, void *buf, size_t len) {
+ if (pio->fd == (void *)-1) return 0;
+ len = read((int)pio->fd, buf, len);
+ if ((int)len < 0) len = 0;
+ pio->pos += len;
+ return len;
+ }
+
+ static void ImageSimulFileSeek(struct gdispImageIO *pio, size_t pos) {
+ if (pio->fd == (void *)-1) return;
+ if (pio->pos != pos) {
+ lseek((int)pio->fd, pos, SEEK_SET);
+ pio->pos = pos;
+ }
+ }
+
+ static void ImageSimulFileClose(struct gdispImageIO *pio) {
+ if (pio->fd == (void *)-1) return;
+ close((int)pio->fd);
+ pio->fd = (void *)-1;
+ pio->pos = 0;
+ }
+
+ static const gdispImageIOFunctions ImageSimulFileFunctions =
+ { ImageSimulFileRead, ImageSimulFileSeek, ImageSimulFileClose };
+
+ bool_t gdispImageSetSimulFileReader(gdispImage *img, const char *filename) {
+ img->io.fns = &ImageSimulFileFunctions;
+ img->io.pos = 0;
+ img->io.fd = (void *)open(filename, O_RDONLY|O_BINARY);
+ return img->io.fd != (void *)-1;
+ }
+#endif
+
+gdispImageError gdispImageOpen(gdispImage *img) {
+ gdispImageError err;
+
+ 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;
+}
+
+void gdispImageClose(gdispImage *img) {
+ if (img->fns)
+ img->fns->close(img);
+ else
+ img->io.fns->close(&img->io);
+}
+
+gdispImageError gdispImageCache(gdispImage *img) {
+ if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
+ return img->fns->cache(img);
+}
+
+gdispImageError gdispImageDraw(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
+ if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
+ return img->fns->draw(img, x, y, cx, cy, sx, sy);
+}
+
+systime_t gdispImageNext(gdispImage *img) {
+ if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
+ return img->fns->next(img);
+}
+
+
+#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE */
+/** @} */