aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2015-11-11 19:20:10 +1000
committerinmarket <andrewh@inmarket.com.au>2015-11-11 19:20:10 +1000
commitf48b492303d87349d054c80727000d9a66c9f094 (patch)
treee73a672198b7004fe9faf055471eaf6cf7a7d202 /src
parent1fa5677d449c510362a800048fbd3c4b93e86a67 (diff)
downloaduGFX-f48b492303d87349d054c80727000d9a66c9f094.tar.gz
uGFX-f48b492303d87349d054c80727000d9a66c9f094.tar.bz2
uGFX-f48b492303d87349d054c80727000d9a66c9f094.zip
Clean up endian support for images based on new system defines
Remove deprecated image functions
Diffstat (limited to 'src')
-rw-r--r--src/gdisp/gdisp_image.c39
-rw-r--r--src/gdisp/gdisp_image.h59
-rw-r--r--src/gdisp/gdisp_image_bmp.c84
-rw-r--r--src/gdisp/gdisp_image_gif.c60
-rw-r--r--src/gdisp/gdisp_image_jpg.c2
-rw-r--r--src/gdisp/gdisp_image_native.c2
-rw-r--r--src/gdisp/gdisp_image_png.c2
-rw-r--r--src/gdisp/gdisp_image_support.h109
8 files changed, 150 insertions, 207 deletions
diff --git a/src/gdisp/gdisp_image.c b/src/gdisp/gdisp_image.c
index 35020634..7da3d90e 100644
--- a/src/gdisp/gdisp_image.c
+++ b/src/gdisp/gdisp_image.c
@@ -9,6 +9,8 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE
+#include "gdisp_image_support.h"
+
#if GDISP_NEED_IMAGE_NATIVE
extern gdispImageError gdispImageOpen_NATIVE(gdispImage *img);
extern void gdispImageClose_NATIVE(gdispImage *img);
@@ -90,39 +92,6 @@ static gdispImageHandlers ImageHandlers[] = {
#endif
};
-gdispImageError
- DEPRECATED("Use gdispImageOpenGFile() instead")
- gdispImageOpen(gdispImage *img) {
- return gdispImageOpenGFile(img, img->f);
-}
-
-#if GFILE_NEED_MEMFS
- bool_t
- DEPRECATED("Use gdispImageOpenMemory() instead")
- gdispImageSetMemoryReader(gdispImage *img, const void *memimage) {
- img->f = gfileOpenMemory((void *)memimage, "rb");
- return img->f != 0;
- }
-#endif
-
-#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX
- 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")
- gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
- img->f = gfileOpenBaseFileStream(BaseFileStreamPtr, "rb");
- return img->f != 0;
- }
-#endif
-
void gdispImageInit(gdispImage *img) {
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
}
@@ -222,4 +191,8 @@ void gdispImageFree(gdispImage *img, void *ptr, size_t sz) {
#endif
}
+#if GFX_CPU_ENDIAN != GFX_CPU_ENDIAN_LITTLE && GFX_CPU_ENDIAN != GFX_CPU_ENDIAN_BIG
+ const uint8_t gdispImageEndianArray[4] = { 1, 2, 3, 4 };
+#endif
+
#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE */
diff --git a/src/gdisp/gdisp_image.h b/src/gdisp/gdisp_image.h
index 1ab320e4..4613bea7 100644
--- a/src/gdisp/gdisp_image.h
+++ b/src/gdisp/gdisp_image.h
@@ -52,52 +52,6 @@ typedef uint16_t gdispImageFlags;
#define GDISP_IMAGE_FLG_ANIMATED 0x0002 /* The image has animation */
#define GDISP_IMAGE_FLG_MULTIPAGE 0x0004 /* The image has multiple pages */
-struct gdispImageIO;
-
-/**
- * @brief An image IO close function
- *
- * @param[in] pio Pointer to the io structure
- * @param[in] desc The descriptor. A filename or an image structure pointer.
- *
- */
-typedef void (*gdispImageIOCloseFn)(struct gdispImageIO *pio);
-
-/**
- * @brief An image IO read function
- * @returns The number of bytes actually read or 0 on error
- *
- * @param[in] pio Pointer to the io structure
- * @param[in] buf Where the results should be placed
- * @param[in] len The number of bytes to read
- *
- */
-typedef size_t (*gdispImageIOReadFn)(struct gdispImageIO *pio, void *buf, size_t len);
-
-/**
- * @brief An image IO seek function
- *
- * @param[in] pio Pointer to the io structure
- * @param[in] pos Which byte to seek to relative to the start of the "file".
- *
- */
-typedef void (*gdispImageIOSeekFn)(struct gdispImageIO *pio, size_t pos);
-
-typedef struct gdispImageIOFunctions {
- gdispImageIOReadFn read; /* @< The function to read input */
- gdispImageIOSeekFn seek; /* @< The function to seek input */
- gdispImageIOCloseFn close; /* @< The function to close input */
- } gdispImageIOFunctions;
-
-/**
- * @brief The structure defining the IO routines for image handling
- */
-typedef struct gdispImageIO {
- const void * fd; /* @< The "file" descriptor */
- size_t pos; /* @< The current "file" position */
- const gdispImageIOFunctions *fns; /* @< The current "file" functions */
-} gdispImageIO;
-
/**
* @brief The structure for an image
*/
@@ -119,19 +73,6 @@ typedef struct gdispImage {
extern "C" {
#endif
- /*
- * 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") 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") gdispImageSetFileReader(gdispImage *img, const char *filename);
- #define gdispImageSetSimulFileReader(img, fname) gdispImageSetFileReader(img, fname)
- #endif
-
/**
* @brief Initialise a gdispImage object
*
diff --git a/src/gdisp/gdisp_image_bmp.c b/src/gdisp/gdisp_image_bmp.c
index 9fc0e13a..dd45081a 100644
--- a/src/gdisp/gdisp_image_bmp.c
+++ b/src/gdisp/gdisp_image_bmp.c
@@ -9,11 +9,7 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_BMP
-/**
- * Helper Routines Needed
- */
-void *gdispImageAlloc(gdispImage *img, size_t sz);
-void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
+#include "gdisp_image_support.h"
/**
* How big a pixel array to allocate for blitting (in pixels)
@@ -22,36 +18,6 @@ void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
*/
#define BLIT_BUFFER_SIZE 32
-/*
- * Determining endianness as at compile time is not guaranteed or compiler portable.
- * We use the best test we can. If we can't guarantee little endianness we do things the
- * hard way.
- */
-#define GUARANTEED_LITTLE_ENDIAN (!defined(SAFE_ENDIAN) && !defined(SAFE_ALIGNMENT) && (\
- (defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \
- || defined(__LITTLE_ENDIAN__) \
- || defined(__LITTLE_ENDIAN) \
- || defined(_LITTLE_ENDIAN) \
-/* || (1 == *(unsigned char *)&(const int){1})*/ \
- ))
-
-
-/* This is a runtime test */
-static const uint8_t dwordOrder[4] = { 1, 2, 3, 4 };
-
-#define isWordLittleEndian() (*(uint16_t *)&dwordOrder == 0x0201)
-#define isDWordLittleEndian() (*(uint32_t *)&dwordOrder == 0x04030201)
-
-#if GUARANTEED_LITTLE_ENDIAN
- /* These are fast routines for guaranteed little endian machines */
- #define CONVERT_FROM_WORD_LE(w)
- #define CONVERT_FROM_DWORD_LE(dw)
-#else
- /* These are slower routines for when little endianness cannot be guaranteed at compile time */
- #define CONVERT_FROM_WORD_LE(w) { if (!isWordLittleEndian()) w = ((((uint16_t)(w))>>8)|(((uint16_t)(w))<<8)); }
- #define CONVERT_FROM_DWORD_LE(dw) { if (!isDWordLittleEndian()) dw = (((uint32_t)(((const uint8_t *)(&dw))[0]))|(((uint32_t)(((const uint8_t *)(&dw))[1]))<<8)|(((uint32_t)(((const uint8_t *)(&dw))[2]))<<16)|(((uint32_t)(((const uint8_t *)(&dw))[3]))<<24)); }
-#endif
-
typedef struct gdispImagePrivate {
uint8_t bmpflags;
#define BMP_V2 0x01 // Version 2 (old) header format
@@ -141,14 +107,14 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
/* Get the offset to the bitmap data */
if (gfileRead(img->f, &priv->frame0pos, 4) != 4)
goto baddatacleanup;
- CONVERT_FROM_DWORD_LE(priv->frame0pos);
+ gdispImageMakeLE32(priv->frame0pos);
/* Process the BITMAPCOREHEADER structure */
/* Get the offset to the colour data */
if (gfileRead(img->f, &offsetColorTable, 4) != 4)
goto baddatacleanup;
- CONVERT_FROM_DWORD_LE(offsetColorTable);
+ gdispImageMakeLE32(offsetColorTable);
offsetColorTable += 14; // Add the size of the BITMAPFILEHEADER
// Detect our bitmap version
@@ -159,23 +125,19 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
if (gfileRead(img->f, priv->buf, 12-4) != 12-4)
goto baddatacleanup;
// Get the width
- img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
- CONVERT_FROM_WORD_LE(img->width);
+ img->width = gdispImageGetAlignedLE16(priv->buf, 0);
// Get the height
- img->height = *(uint16_t *)(((uint8_t *)priv->buf)+2);
- CONVERT_FROM_WORD_LE(img->height);
+ img->height = gdispImageGetAlignedLE16(priv->buf, 2);
if (img->height < 0) {
img->priv->bmpflags |= BMP_TOP_TO_BOTTOM;
img->height = -img->height;
}
// Get the planes
- aword = *(uint16_t *)(((uint8_t *)priv->buf)+4);
- CONVERT_FROM_WORD_LE(aword);
+ aword = gdispImageGetAlignedLE16(priv->buf, 4);
if (aword != 1)
goto unsupportedcleanup;
// Get the bits per pixel
- aword = *(uint16_t *)(((uint8_t *)priv->buf)+6);
- CONVERT_FROM_WORD_LE(aword);
+ aword = gdispImageGetAlignedLE16(priv->buf, 6);
switch(aword) {
#if GDISP_NEED_IMAGE_BMP_1
case 1:
@@ -208,14 +170,12 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
if (gfileRead(img->f, priv->buf, 40-4) != 40-4)
goto baddatacleanup;
// Get the width
- adword = *(uint32_t *)(((uint8_t *)priv->buf)+0);
- CONVERT_FROM_DWORD_LE(adword);
+ adword = gdispImageGetAlignedLE32(priv->buf, 0);
if (adword > 32768) // This also picks up negative values
goto unsupportedcleanup;
img->width = adword;
// Get the height
- adword = *(uint32_t *)(((uint8_t *)priv->buf)+4);
- CONVERT_FROM_DWORD_LE(adword);
+ adword = gdispImageGetAlignedLE32(priv->buf, 4);
if ((int32_t)adword < 0) { // Negative test
priv->bmpflags |= BMP_TOP_TO_BOTTOM;
adword = -adword;
@@ -224,13 +184,11 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
goto unsupportedcleanup;
img->height = adword;
// Get the planes
- aword = *(uint16_t *)(((uint8_t *)priv->buf)+8);
- CONVERT_FROM_WORD_LE(aword);
+ aword = gdispImageGetAlignedLE16(priv->buf, 8);
if (aword != 1)
goto unsupportedcleanup;
// Get the bits per pixel
- aword = *(uint16_t *)(((uint8_t *)priv->buf)+10);
- CONVERT_FROM_WORD_LE(aword);
+ aword = gdispImageGetAlignedLE16(priv->buf, 10);
switch(aword) {
#if GDISP_NEED_IMAGE_BMP_1
case 1:
@@ -263,8 +221,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
}
priv->bitsperpixel = aword;
// Get the compression
- adword = *(uint32_t *)(((uint8_t *)priv->buf)+12);
- CONVERT_FROM_DWORD_LE(adword);
+ adword = gdispImageGetAlignedLE32(priv->buf, 12);
switch(adword) {
case 0: // BI_RGB - uncompressed
break;
@@ -297,8 +254,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
priv->bitsperpixel = aword;
#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
// Get the actual colors used
- adword = *(uint32_t *)(((uint8_t *)priv->buf)+28);
- CONVERT_FROM_DWORD_LE(adword);
+ adword = gdispImageGetAlignedLE32(priv->buf, 28);
if (adword && adword < priv->palsize)
priv->palsize = adword;
#endif
@@ -332,14 +288,14 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
if (priv->bmpflags & BMP_COMP_MASK) {
gfileSetPos(img->f, offsetColorTable);
if (gfileRead(img->f, &priv->maskred, 4) != 4) goto baddatacleanup;
- CONVERT_FROM_DWORD_LE(priv->maskred);
+ gdispImageMakeLE32(priv->maskred);
if (gfileRead(img->f, &priv->maskgreen, 4) != 4) goto baddatacleanup;
- CONVERT_FROM_DWORD_LE(priv->maskgreen);
+ gdispImageMakeLE32(priv->maskgreen);
if (gfileRead(img->f, &priv->maskblue, 4) != 4) goto baddatacleanup;
- CONVERT_FROM_DWORD_LE(priv->maskblue);
+ gdispImageMakeLE32(priv->maskblue);
if (priv->bmpflags & BMP_V4) {
if (gfileRead(img->f, &priv->maskalpha, 4) != 4) goto baddatacleanup;
- CONVERT_FROM_DWORD_LE(priv->maskalpha);
+ gdispImageMakeLE32(priv->maskalpha);
} else
priv->maskalpha = 0;
} else if (priv->bitsperpixel == 16) {
@@ -644,8 +600,8 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
while(x < img->width && len <= BLIT_BUFFER_SIZE-2) {
if (gfileRead(img->f, &w, 4) != 4)
return 0;
- CONVERT_FROM_WORD_LE(w[0]);
- CONVERT_FROM_WORD_LE(w[1]);
+ gdispImageMakeLE16(w[0]);
+ gdispImageMakeLE16(w[1]);
if (priv->shiftred < 0)
r = (color_t)((w[0] & priv->maskred) << -priv->shiftred);
else
@@ -712,7 +668,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
while(x < img->width && len < BLIT_BUFFER_SIZE) {
if (gfileRead(img->f, &dw, 4) != 4)
return 0;
- CONVERT_FROM_DWORD_LE(dw);
+ gdispImageMakeLE32(dw);
if (priv->shiftred < 0)
r = (color_t)((dw & priv->maskred) << -priv->shiftred);
else
diff --git a/src/gdisp/gdisp_image_gif.c b/src/gdisp/gdisp_image_gif.c
index 88dac4c8..515d67e8 100644
--- a/src/gdisp/gdisp_image_gif.c
+++ b/src/gdisp/gdisp_image_gif.c
@@ -9,11 +9,7 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_GIF
-/**
- * Helper Routines Needed
- */
-void *gdispImageAlloc(gdispImage *img, size_t sz);
-void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
+#include "gdisp_image_support.h"
/**
* How big an array to allocate for blitting (in pixels)
@@ -21,36 +17,6 @@ void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
*/
#define BLIT_BUFFER_SIZE 32
-/*
- * Determining endianness as at compile time is not guaranteed or compiler portable.
- * We use the best test we can. If we can't guarantee little endianness we do things the
- * hard way.
- */
-#define GUARANTEED_LITTLE_ENDIAN (!defined(SAFE_ENDIAN) && !defined(SAFE_ALIGNMENT) && (\
- (defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) \
- || defined(__LITTLE_ENDIAN__) \
- || defined(__LITTLE_ENDIAN) \
- || defined(_LITTLE_ENDIAN) \
-/* || (1 == *(unsigned char *)&(const int){1})*/ \
- ))
-
-
-/* This is a runtime test */
-static const uint8_t dwordOrder[4] = { 1, 2, 3, 4 };
-
-#define isWordLittleEndian() (*(uint16_t *)&dwordOrder == 0x0201)
-#define isDWordLittleEndian() (*(uint32_t *)&dwordOrder == 0x04030201)
-
-#if GUARANTEED_LITTLE_ENDIAN
- /* These are fast routines for guaranteed little endian machines */
- #define CONVERT_FROM_WORD_LE(w)
- #define CONVERT_FROM_DWORD_LE(dw)
-#else
- /* These are slower routines for when little endianness cannot be guaranteed at compile time */
- #define CONVERT_FROM_WORD_LE(w) { if (!isWordLittleEndian()) w = ((((uint16_t)(w))>>8)|(((uint16_t)(w))<<8)); }
- #define CONVERT_FROM_DWORD_LE(dw) { if (!isDWordLittleEndian()) dw = (((uint32_t)(((const uint8_t *)(&dw))[0]))|(((uint32_t)(((const uint8_t *)(&dw))[1]))<<8)|(((uint32_t)(((const uint8_t *)(&dw))[2]))<<16)|(((uint32_t)(((const uint8_t *)(&dw))[3]))<<24)); }
-#endif
-
// We need a special error to indicate the end of file (which may not actually be an error)
#define GDISP_IMAGE_EOF ((gdispImageError)-1)
#define GDISP_IMAGE_LOOP ((gdispImageError)-2)
@@ -416,14 +382,10 @@ static gdispImageError initFrame(gdispImage *img) {
// Read the Image Descriptor
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);
- priv->frame.y = *(uint16_t *)(((uint8_t *)priv->buf)+2);
- CONVERT_FROM_WORD_LE(priv->frame.y);
- priv->frame.width = *(uint16_t *)(((uint8_t *)priv->buf)+4);
- CONVERT_FROM_WORD_LE(priv->frame.width);
- priv->frame.height = *(uint16_t *)(((uint8_t *)priv->buf)+6);
- CONVERT_FROM_WORD_LE(priv->frame.height);
+ priv->frame.x = gdispImageGetAlignedLE16(priv->buf, 0);
+ priv->frame.y = gdispImageGetAlignedLE16(priv->buf, 2);
+ priv->frame.width = gdispImageGetAlignedLE16(priv->buf, 4);
+ priv->frame.height = gdispImageGetAlignedLE16(priv->buf, 6);
if (((uint8_t *)priv->buf)[8] & 0x80) // Local color table?
priv->frame.palsize = 2 << (((uint8_t *)priv->buf)[8] & 0x07);
if (((uint8_t *)priv->buf)[8] & 0x40) // Interlaced?
@@ -468,8 +430,7 @@ static gdispImageError initFrame(gdispImage *img) {
else
img->flags &= ~GDISP_IMAGE_FLG_MULTIPAGE;
// Process frame delay and the transparent color (if any)
- priv->frame.delay = *(uint16_t *)(((uint8_t *)priv->buf)+2);
- CONVERT_FROM_WORD_LE(priv->frame.delay);
+ priv->frame.delay = gdispImageGetAlignedLE16(priv->buf, 2);
priv->frame.paltrans = ((uint8_t *)priv->buf)[4];
break;
@@ -489,8 +450,7 @@ static gdispImageError initFrame(gdispImage *img) {
&& ((uint8_t *)priv->buf)[7] == 'P' && ((uint8_t *)priv->buf)[8] == 'E' && ((uint8_t *)priv->buf)[9] == '2'
&& ((uint8_t *)priv->buf)[10] == '.' && ((uint8_t *)priv->buf)[11] == '0') {
if (((uint8_t *)priv->buf)[13] == 1) {
- priv->loops = *(uint16_t *)(((uint8_t *)priv->buf)+14);
- CONVERT_FROM_WORD_LE(priv->loops);
+ priv->loops = gdispImageGetAlignedLE16(priv->buf, 14);
priv->flags |= GIF_LOOP;
if (!priv->loops)
priv->flags |= GIF_LOOPFOREVER;
@@ -597,11 +557,9 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
if (gfileRead(img->f, priv->buf, 7) != 7)
goto baddatacleanup;
// Get the width
- img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
- CONVERT_FROM_WORD_LE(img->width);
+ img->width = gdispImageGetAlignedLE16(priv->buf, 0);
// Get the height
- img->height = *(uint16_t *)(((uint8_t *)priv->buf)+2);
- CONVERT_FROM_WORD_LE(img->height);
+ img->height = gdispImageGetAlignedLE16(priv->buf, 2);
if (((uint8_t *)priv->buf)[4] & 0x80) {
// Global color table
priv->palsize = 2 << (((uint8_t *)priv->buf)[4] & 0x07);
diff --git a/src/gdisp/gdisp_image_jpg.c b/src/gdisp/gdisp_image_jpg.c
index 02ec9a8f..0f856e2c 100644
--- a/src/gdisp/gdisp_image_jpg.c
+++ b/src/gdisp/gdisp_image_jpg.c
@@ -9,6 +9,8 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_JPG
+#include "gdisp_image_support.h"
+
#error "JPG support not implemented yet"
#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_JPG */
diff --git a/src/gdisp/gdisp_image_native.c b/src/gdisp/gdisp_image_native.c
index ec22f386..347738bd 100644
--- a/src/gdisp/gdisp_image_native.c
+++ b/src/gdisp/gdisp_image_native.c
@@ -9,6 +9,8 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_NATIVE
+#include "gdisp_image_support.h"
+
/**
* How big a pixel array to allocate for blitting
* Bigger is faster but uses more RAM.
diff --git a/src/gdisp/gdisp_image_png.c b/src/gdisp/gdisp_image_png.c
index 6538b2ff..b6e70d91 100644
--- a/src/gdisp/gdisp_image_png.c
+++ b/src/gdisp/gdisp_image_png.c
@@ -9,6 +9,8 @@
#if GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_PNG
+#include "gdisp_image_support.h"
+
#error "PNG support not implemented yet"
#endif /* GFX_USE_GDISP && GDISP_NEED_IMAGE && GDISP_NEED_IMAGE_PNG */
diff --git a/src/gdisp/gdisp_image_support.h b/src/gdisp/gdisp_image_support.h
new file mode 100644
index 00000000..a853f9e4
--- /dev/null
+++ b/src/gdisp/gdisp_image_support.h
@@ -0,0 +1,109 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gdisp/gdisp_image_support.h
+ * @brief GDISP image support routines header file.
+ *
+ * @defgroup Image Image
+ * @ingroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_IMAGE_SUPPORT_H
+#define _GDISP_IMAGE_SUPPORT_H
+
+/* Base endian handling routines */
+#define gdispImageGetVar(type, p, idx) (*(type *)(((uint8_t *)(p))+(idx)))
+#define gdispImageGetByte(type, p, idx, shift) (((type)gdispImageGetVar(uint8_t, p, idx))<<(shift))
+#define gdispImageSwap16(w) ((((uint16_t)(w))>>8)|(((uint16_t)(w))<<8))
+#define gdispImageSwap32(dw) ((((uint32_t)(w))>>24)|((((uint32_t)(w))&0x00FF0000)>>8)\
+ |((((uint32_t)(w))&0x0000FF00)<<8)|(((uint32_t)(w))<<24))
+
+/*
+ * Get a uint16_t/uint32_t from memory in the required endianness.
+ * There is no alignment requirement.
+ */
+#if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_LITTLE && GFX_CPU_NO_ALIGNMENT_FAULTS
+ #define gidspImageGetLE16(p, idx) gdispImageGetVar(uint16_t, (p), (idx))
+ #define gidspImageGetLE32(p, idx) gdispImageGetVar(uint32_t, (p), (idx))
+#else
+ #define gdispImageGetLE16(p, idx) ( gdispImageGetByte(uint16_t, (p), (idx) , 0) | gdispImageGetByte(uint16_t, (p), (idx)+1, 8))
+ #define gdispImageGetLE32(p, idx) ( gdispImageGetByte(uint32_t, (p), (idx) , 0) | gdispImageGetByte(uint32_t, (p), (idx)+1, 8)\
+ |gdispImageGetByte(uint32_t, (p), (idx)+2, 16) | gdispImageGetByte(uint32_t, (p), (idx)+3, 24))
+#endif
+#if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_BIG && GFX_CPU_NO_ALIGNMENT_FAULTS
+ #define gidspImageGetBE16(p, idx) gdispImageGetVar(uint16_t, (p), (idx))
+ #define gidspImageGetBE32(p, idx) gdispImageGetVar(uint32_t, (p), (idx))
+#else
+ #define gdispImageGetBE16(p, idx) ( gdispImageGetByte(uint16_t, (p), (idx) , 8) | gdispImageGetByte(uint16_t, (p), (idx)+1, 0))
+ #define gdispImageGetBE32(p, idx) ( gdispImageGetByte(uint32_t, (p), (idx) , 24) | gdispImageGetByte(uint32_t, (p), (idx)+1, 16)\
+ |gdispImageGetByte(uint32_t, (p), (idx)+2, 8) | gdispImageGetByte(uint32_t, (p), (idx)+3, 0))
+#endif
+
+/*
+ * Get a uint16_t/uint32_t from memory in the required endianness.
+ * These are optimised routines but the memory must be word/dword aligned.
+ */
+#if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_LITTLE
+ #define gdispImageGetAlignedLE16(p, idx) gdispImageGetVar(uint16_t, (p), (idx))
+ #define gdispImageGetAlignedBE16(p, idx) gidspImageGetBE16(p, (idx))
+ #define gdispImageGetAlignedLE32(p, idx) gdispImageGetVar(uint32_t, (p), (idx))
+ #define gdispImageGetAlignedBE32(p, idx) gidspImageGetBE32(p, (idx))
+#elif GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_BIG
+ #define gdispImageGetAlignedLE16(p, idx) gidspImageGetLE16(p, (idx))
+ #define gdispImageGetAlignedBE16(p, idx) gdispImageGetVar(uint16_t, (p), (idx))
+ #define gdispImageGetAlignedLE32(p, idx) gidspImageGetLE32(p, (idx))
+ #define gdispImageGetAlignedBE32(p, idx) gdispImageGetVar(uint32_t, (p), (idx))
+#else
+ #define gdispImageGetAlignedLE16(p, idx) gidspImageGetLE16(p, (idx))
+ #define gdispImageGetAlignedBE16(p, idx) gidspImageGetBE16(p, (idx))
+ #define gdispImageGetAlignedLE32(p, idx) gidspImageGetLE32(p, (idx))
+ #define gdispImageGetAlignedBE32(p, idx) gidspImageGetBE32(p, (idx))
+#endif
+
+/*
+ * Change a uint16 or uint32 already in a register to the required endianness.
+ */
+#if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_LITTLE
+ #define gdispImageMakeLE16(w)
+ #define gdispImageMakeLE32(dw)
+ #define gdispImageMakeBE16(w) { w = gdispImageSwap16(w); }
+ #define gdispImageMakeBE32(dw) { dw = gdispImageSwap32(dw); }
+#elif GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_BIG
+ #define gdispImageMakeLE16(w) { w = gdispImageSwap16(w); }
+ #define gdispImageMakeLE32(dw) { dw = gdispImageSwap32(dw); }
+ #define gdispImageMakeBE16(w)
+ #define gdispImageMakeBE32(dw)
+#else
+ #define gdispImageEndianness() (*(uint32_t *)&gdispImageEndianArray)
+
+ #define gdispImageMakeLE16(w) { if (gdispImageEndianness() != GFX_CPU_ENDIAN_LITTLE) w = gdispImageSwap16(w); }
+ #define gdispImageMakeLE32(dw) { if (gdispImageEndianness() != GFX_CPU_ENDIAN_LITTLE) dw = gdispImageSwap32(dw); }
+ #define gdispImageMakeBE16(w) { if (gdispImageEndianness() != GFX_CPU_ENDIAN_BIG) w = gdispImageSwap16(w); }
+ #define gdispImageMakeBE32(dw) { if (gdispImageEndianness() != GFX_CPU_ENDIAN_BIG) dw = gdispImageSwap32(dw); }
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void *gdispImageAlloc(gdispImage *img, size_t sz);
+ void gdispImageFree(gdispImage *img, void *ptr, size_t sz);
+
+ #if GFX_CPU_ENDIAN == GFX_CPU_ENDIAN_UNKNOWN
+ extern const uint8_t gdispImageEndianArray[4];
+ #endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GDISP_IMAGE_SUPPORT_H */
+/** @} */
+