2013-05-01 23:53:28 +00:00
|
|
|
/*
|
2013-06-15 11:37:22 +00:00
|
|
|
* This file is subject to the terms of the GFX License. If a copy of
|
2013-05-03 14:36:17 +00:00
|
|
|
* the license was not distributed with this file, you can obtain one at:
|
|
|
|
*
|
2013-07-21 20:20:37 +00:00
|
|
|
* http://ugfx.org/license.html
|
2013-05-03 14:36:17 +00:00
|
|
|
*/
|
2013-04-03 03:51:43 +00:00
|
|
|
|
2015-11-21 09:27:08 +00:00
|
|
|
#include "../../gfx.h"
|
2013-04-03 03:51:43 +00:00
|
|
|
|
|
|
|
#if GFX_USE_GDISP && GDISP_NEED_IMAGE
|
|
|
|
|
2015-11-11 09:20:10 +00:00
|
|
|
#include "gdisp_image_support.h"
|
|
|
|
|
2014-02-06 15:36:31 +00:00
|
|
|
#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);
|
2016-11-11 17:28:48 +00:00
|
|
|
extern uint16_t gdispImageGetPaletteSize_BMP(gdispImage *img);
|
|
|
|
extern color_t gdispImageGetPalette_BMP(gdispImage *img, uint16_t index);
|
|
|
|
extern bool_t gdispImageAdjustPalette_BMP(gdispImage *img, uint16_t index, color_t newColor);
|
2014-02-06 15:36:31 +00:00
|
|
|
#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
|
|
|
|
|
2013-04-03 03:51:43 +00:00
|
|
|
/* The structure defining the routines for image drawing */
|
|
|
|
typedef struct gdispImageHandlers {
|
2016-11-10 22:00:31 +00:00
|
|
|
gdispImageError (*open)(gdispImage *img); /* The open function */
|
|
|
|
void (*close)(gdispImage *img); /* The close function */
|
|
|
|
gdispImageError (*cache)(gdispImage *img); /* The cache function */
|
2013-10-24 08:34:26 +00:00
|
|
|
gdispImageError (*draw)(GDisplay *g,
|
|
|
|
gdispImage *img,
|
2013-04-03 03:51:43 +00:00
|
|
|
coord_t x, coord_t y,
|
|
|
|
coord_t cx, coord_t cy,
|
2016-11-10 22:00:31 +00:00
|
|
|
coord_t sx, coord_t sy); /* The draw function */
|
|
|
|
delaytime_t (*next)(gdispImage *img); /* The next frame function */
|
2016-11-11 17:28:48 +00:00
|
|
|
uint16_t (*getPaletteSize)(gdispImage *img); /* Retrieve the size of the palette (number of entries) */
|
|
|
|
color_t (*getPalette)(gdispImage *img, uint16_t index); /* Retrieve a specific color value of the palette */
|
|
|
|
bool_t (*adjustPalette)(gdispImage *img, uint16_t index, color_t newColor); /* Replace a color value in the palette */
|
2013-04-03 03:51:43 +00:00
|
|
|
} gdispImageHandlers;
|
|
|
|
|
|
|
|
static gdispImageHandlers ImageHandlers[] = {
|
|
|
|
#if GDISP_NEED_IMAGE_NATIVE
|
|
|
|
{ gdispImageOpen_NATIVE, gdispImageClose_NATIVE,
|
2013-10-24 08:34:26 +00:00
|
|
|
gdispImageCache_NATIVE, gdispGImageDraw_NATIVE, gdispImageNext_NATIVE,
|
2016-11-10 22:00:31 +00:00
|
|
|
0, 0, 0
|
2013-04-03 03:51:43 +00:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#if GDISP_NEED_IMAGE_GIF
|
|
|
|
{ gdispImageOpen_GIF, gdispImageClose_GIF,
|
2013-10-24 08:34:26 +00:00
|
|
|
gdispImageCache_GIF, gdispGImageDraw_GIF, gdispImageNext_GIF,
|
2016-11-10 22:00:31 +00:00
|
|
|
0, 0, 0
|
2013-04-03 03:51:43 +00:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#if GDISP_NEED_IMAGE_BMP
|
2016-11-10 22:00:31 +00:00
|
|
|
{ gdispImageOpen_BMP, gdispImageClose_BMP,
|
|
|
|
gdispImageCache_BMP, gdispGImageDraw_BMP, gdispImageNext_BMP,
|
|
|
|
gdispImageGetPaletteSize_BMP, gdispImageGetPalette_BMP, gdispImageAdjustPalette_BMP
|
2013-04-03 03:51:43 +00:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#if GDISP_NEED_IMAGE_JPG
|
|
|
|
{ gdispImageOpen_JPG, gdispImageClose_JPG,
|
2013-10-24 08:34:26 +00:00
|
|
|
gdispImageCache_JPG, gdispGImageDraw_JPG, gdispImageNext_JPG,
|
2016-11-10 22:00:31 +00:00
|
|
|
0, 0, 0
|
2013-04-03 03:51:43 +00:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
#if GDISP_NEED_IMAGE_PNG
|
|
|
|
{ gdispImageOpen_PNG, gdispImageClose_PNG,
|
2013-10-24 08:34:26 +00:00
|
|
|
gdispImageCache_PNG, gdispGImageDraw_PNG, gdispImageNext_PNG,
|
2016-11-10 22:00:31 +00:00
|
|
|
0, 0, 0
|
2013-04-03 03:51:43 +00:00
|
|
|
},
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2014-05-09 11:30:00 +00:00
|
|
|
void gdispImageInit(gdispImage *img) {
|
|
|
|
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
2014-02-07 04:06:08 +00:00
|
|
|
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f) {
|
|
|
|
gdispImageError err;
|
2013-04-03 03:51:43 +00:00
|
|
|
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img)
|
|
|
|
return GDISP_IMAGE_ERR_NULLPOINTER;
|
2014-02-07 04:06:08 +00:00
|
|
|
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);
|
2013-04-03 03:51:43 +00:00
|
|
|
}
|
2014-02-06 15:36:31 +00:00
|
|
|
|
2014-02-07 04:06:08 +00:00
|
|
|
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;
|
|
|
|
}
|
2013-04-03 03:51:43 +00:00
|
|
|
|
|
|
|
void gdispImageClose(gdispImage *img) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img)
|
|
|
|
return;
|
2013-04-03 03:51:43 +00:00
|
|
|
if (img->fns)
|
|
|
|
img->fns->close(img);
|
2014-02-07 04:06:08 +00:00
|
|
|
gfileClose(img->f);
|
2013-07-01 07:36:47 +00:00
|
|
|
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
|
|
|
|
img->flags = 0;
|
|
|
|
img->fns = 0;
|
|
|
|
img->priv = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool_t gdispImageIsOpen(gdispImage *img) {
|
2017-10-02 01:25:27 +00:00
|
|
|
return img && img->type != GDISP_IMAGE_TYPE_UNKNOWN && img->fns != 0;
|
2013-04-03 03:51:43 +00:00
|
|
|
}
|
|
|
|
|
2013-04-20 11:19:26 +00:00
|
|
|
void gdispImageSetBgColor(gdispImage *img, color_t bgcolor) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img)
|
|
|
|
return;
|
2013-04-20 11:19:26 +00:00
|
|
|
img->bgcolor = bgcolor;
|
|
|
|
}
|
|
|
|
|
2013-04-03 03:51:43 +00:00
|
|
|
gdispImageError gdispImageCache(gdispImage *img) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img) return GDISP_IMAGE_ERR_NULLPOINTER;
|
2013-04-03 03:51:43 +00:00
|
|
|
if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
|
|
|
|
return img->fns->cache(img);
|
|
|
|
}
|
|
|
|
|
2013-10-24 08:34:26 +00:00
|
|
|
gdispImageError gdispGImageDraw(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img) return GDISP_IMAGE_ERR_NULLPOINTER;
|
2013-04-03 03:51:43 +00:00
|
|
|
if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
|
2016-02-27 01:57:23 +00:00
|
|
|
|
|
|
|
// Check on window
|
|
|
|
if (cx <= 0 || cy <= 0) return GDISP_IMAGE_ERR_OK;
|
|
|
|
if (sx < 0) sx = 0;
|
|
|
|
if (sy < 0) sy = 0;
|
|
|
|
if (sx >= img->width || sy >= img->height) return GDISP_IMAGE_ERR_OK;
|
|
|
|
if (sx + cx > img->width) cx = img->width - sx;
|
|
|
|
if (sy + cy > img->height) cy = img->height - sy;
|
|
|
|
|
|
|
|
// Draw
|
2013-10-24 08:34:26 +00:00
|
|
|
return img->fns->draw(g, img, x, y, cx, cy, sx, sy);
|
2013-04-03 03:51:43 +00:00
|
|
|
}
|
|
|
|
|
2013-05-24 15:26:52 +00:00
|
|
|
delaytime_t gdispImageNext(gdispImage *img) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img) return GDISP_IMAGE_ERR_NULLPOINTER;
|
2013-04-03 03:51:43 +00:00
|
|
|
if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT;
|
|
|
|
return img->fns->next(img);
|
|
|
|
}
|
|
|
|
|
2016-11-11 17:28:48 +00:00
|
|
|
uint16_t gdispImageGetPaletteSize(gdispImage *img) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img || !img->fns) return 0;
|
2016-11-11 17:28:48 +00:00
|
|
|
if (!img->fns->getPaletteSize) return 0;
|
|
|
|
return img->fns->getPaletteSize(img);
|
|
|
|
}
|
|
|
|
|
|
|
|
color_t gdispImageGetPalette(gdispImage *img, uint16_t index) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img || !img->fns) return 0;
|
2016-11-11 17:28:48 +00:00
|
|
|
if (!img->fns->getPalette) return 0;
|
|
|
|
return img->fns->getPalette(img, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool_t gdispImageAdjustPalette(gdispImage *img, uint16_t index, color_t newColor) {
|
2017-10-01 11:21:56 +00:00
|
|
|
if (!img || !img->fns) return FALSE;
|
2016-11-11 17:28:48 +00:00
|
|
|
if (!img->fns->adjustPalette) return FALSE;
|
|
|
|
return img->fns->adjustPalette(img, index, newColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-20 11:19:26 +00:00
|
|
|
// Helper Routines
|
|
|
|
void *gdispImageAlloc(gdispImage *img, size_t sz) {
|
|
|
|
#if GDISP_NEED_IMAGE_ACCOUNTING
|
|
|
|
void *ptr;
|
|
|
|
|
2013-05-24 15:26:52 +00:00
|
|
|
ptr = gfxAlloc(sz);
|
2013-04-20 11:19:26 +00:00
|
|
|
if (ptr) {
|
|
|
|
img->memused += sz;
|
|
|
|
if (img->memused > img->maxmemused)
|
|
|
|
img->maxmemused = img->memused;
|
|
|
|
}
|
|
|
|
return ptr;
|
|
|
|
#else
|
|
|
|
(void) img;
|
2013-05-24 15:26:52 +00:00
|
|
|
return gfxAlloc(sz);
|
2013-04-20 11:19:26 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void gdispImageFree(gdispImage *img, void *ptr, size_t sz) {
|
|
|
|
#if GDISP_NEED_IMAGE_ACCOUNTING
|
2013-05-24 15:26:52 +00:00
|
|
|
gfxFree(ptr);
|
2013-04-20 11:19:26 +00:00
|
|
|
img->memused -= sz;
|
|
|
|
#else
|
|
|
|
(void) img;
|
|
|
|
(void) sz;
|
2013-05-24 15:26:52 +00:00
|
|
|
gfxFree(ptr);
|
2013-04-20 11:19:26 +00:00
|
|
|
#endif
|
|
|
|
}
|
2013-04-03 03:51:43 +00:00
|
|
|
|
2015-11-12 08:33:12 +00:00
|
|
|
#if GFX_CPU_ENDIAN != GFX_CPU_ENDIAN_LITTLE && GFX_CPU_ENDIAN != GFX_CPU_ENDIAN_BIG \
|
|
|
|
&& GFX_CPU_ENDIAN != GFX_CPU_ENDIAN_WBDWL && GFX_CPU_ENDIAN != GFX_CPU_ENDIAN_WLDWB
|
|
|
|
|
|
|
|
union wbyteorder_u {
|
|
|
|
uint8_t b[2];
|
|
|
|
uint32_t w;
|
|
|
|
};
|
|
|
|
union dwbyteorder_u {
|
|
|
|
uint8_t b[4];
|
|
|
|
uint32_t l;
|
|
|
|
};
|
|
|
|
|
|
|
|
uint16_t gdispImageH16toLE16(uint16_t w) {
|
|
|
|
union wbyteorder_u we;
|
|
|
|
|
|
|
|
we.w = w;
|
|
|
|
return (((uint16_t)we.b[0]))|(((uint16_t)we.b[1]) << 8);
|
|
|
|
}
|
2015-11-17 23:59:31 +00:00
|
|
|
uint16_t gdispImageH16toBE16(uint16_t w) {
|
2015-11-12 08:33:12 +00:00
|
|
|
union wbyteorder_u we;
|
|
|
|
|
|
|
|
we.w = w;
|
|
|
|
return (((uint16_t)we.b[0]) << 8)|(((uint16_t)we.b[1]));
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t gdispImageH32toLE32(uint32_t dw) {
|
|
|
|
union dwbyteorder_u we;
|
|
|
|
|
|
|
|
we.l = dw;
|
|
|
|
return (((uint32_t)we.b[0]))
|
|
|
|
|(((uint32_t)we.b[1]) << 8)
|
|
|
|
|(((uint32_t)we.b[2]) << 16)
|
|
|
|
|(((uint32_t)we.b[3]) << 24);
|
|
|
|
}
|
|
|
|
uint32_t gdispImageH32toBE32(uint32_t dw) {
|
|
|
|
union dwbyteorder_u we;
|
|
|
|
|
|
|
|
we.l = dw;
|
|
|
|
return (((uint32_t)we.b[0]) << 24)
|
|
|
|
|(((uint32_t)we.b[1]) << 16)
|
|
|
|
|(((uint32_t)we.b[2]) << 8)
|
|
|
|
|(((uint32_t)we.b[3]));
|
|
|
|
}
|
2015-11-11 09:20:10 +00:00
|
|
|
#endif
|
|
|
|
|
2013-04-03 03:51:43 +00:00
|
|
|
#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE */
|