Fork of David Smart's RA8875 library
Fork of RA8875 by
Revision 42:7cbdfd2bbfc5, committed 2014-02-23
- Comitter:
- WiredHome
- Date:
- Sun Feb 23 17:58:39 2014 +0000
- Parent:
- 41:2956a0a221e5
- Child:
- 43:3becae133285
- Commit message:
- Added initial support for .ico file format (does not yet account for them being 2 x height for the mask), but this permitted generalizing the API for loading an image from the file system.
Changed in this revision
--- a/Bitmap.h Sat Feb 08 17:35:45 2014 +0000 +++ b/Bitmap.h Sun Feb 23 17:58:39 2014 +0000 @@ -23,7 +23,7 @@ #pragma push #pragma pack(2) -typedef struct /**** BMP file header structure ****/ +typedef struct /**** BMP file header structure ****/ { uint16_t bfType; /* Magic number for file */ uint32_t bfSize; /* Size of file */ @@ -73,4 +73,30 @@ // RGBQUAD bmiColors[256]; /* Image colormap */ // } BITMAPINFO; + +#pragma push +#pragma pack(2) + +typedef struct /**** ICO file header structure ****/ + { + uint16_t Reserved_zero; // Always zero + uint16_t icType; // 1 for .ico, 2 for .cur + uint16_t icImageCount; // number of images in the file + } ICOFILEHEADER; + +typedef struct /**** ICO file Directory Entry structure (1 or more) ****/ + { + uint8_t biWidth; /* Width of image */ + uint8_t biHeight; /* Height of image */ + uint8_t biClrUsed; /* Number of colors used */ + uint8_t Reserved_zero; + uint16_t biPlanes; /* Number of color planes (ICO should be 0 or 1, CUR horz hotspot */ + uint16_t biBitCount; /* Number of bits per pixel (ICO bits per pixel, CUR vert hotspot */ + uint32_t biSizeImage; /* Size of image data */ + uint32_t bfOffBits; /* Offset into file for the bitmap data */ + } ICODIRENTRY; +#pragma pop + +#define IC_TYPE 0x0001 /* 1 = ICO (icon), 2 = CUR (cursor) */ + #endif // _BITMAP_H_
--- a/DisplayDefs.h Sat Feb 08 17:35:45 2014 +0000 +++ b/DisplayDefs.h Sun Feb 23 17:58:39 2014 +0000 @@ -11,7 +11,8 @@ noerror, ///< no errors, command completed successfully bad_parameter, ///< one or more parameters are invalid file_not_found, ///< specified file could not be found - not_bmp_format, ///< file is a not bmp file + not_bmp_format, ///< file is not a .bmp file + not_ico_format, ///< file is not a .ico file not_supported_format, ///< file format is not yet supported image_too_big, ///< image is too large for the screen not_enough_ram, ///< could not allocate ram for scanline
--- a/GraphicsDisplay.cpp Sat Feb 08 17:35:45 2014 +0000 +++ b/GraphicsDisplay.cpp Sun Feb 23 17:58:39 2014 +0000 @@ -7,8 +7,9 @@ #include "GraphicsDisplay.h" #include "Bitmap.h" +#include "string.h" -#define DEBUG "GD" +//#define DEBUG "GD" // ... // INFO("Stuff to show %d", var); // new-line is automatically appended // @@ -145,6 +146,40 @@ }; #endif // LOCALFONT +char mytolower(char a) { + if (a >= 'A' && a <= 'Z') + return (a - 'A' + 'a'); + else + return a; +} +/// mystrnicmp exists because not all compiler libraries have this function. +/// +/// Some have strnicmp, others _strnicmp, and others have C++ methods, which +/// is outside the scope of this C-portable set of functions. +/// +/// @param l is a pointer to the string on the left +/// @param r is a pointer to the string on the right +/// @param n is the number of characters to compare +/// @returns -1 if l < r +/// @returns 0 if l == r +/// @returns +1 if l > r +/// +int mystrnicmp(const char *l, const char *r, size_t n) { + int result = 0; + + if (n != 0) { + do { + result = mytolower(*l++) - mytolower(*r++); + } while ((result == 0) && (*l != '\0') && (--n > 0)); + } + if (result < -1) + result = -1; + else if (result > 1) + result = 1; + return result; +} + + GraphicsDisplay::GraphicsDisplay(const char *name) : TextDisplay(name) { @@ -412,40 +447,19 @@ } } - -RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP) +RetCode_t GraphicsDisplay::_RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image) { - #define OffsetPixelWidth 18 - #define OffsetPixelHeight 22 - #define OffsetFileSize 34 - #define OffsetPixData 10 - #define OffsetBPP 28 - - BITMAPFILEHEADER BMP_Header; BITMAPINFOHEADER BMP_Info; RGBQUAD * colorPalette = NULL; int colorCount; uint8_t * lineBuffer = NULL; uint16_t BPP_t; uint32_t PixelWidth, PixelHeight; - uint32_t start_data; + //uint32_t start_data; unsigned int i, offset; int padd,j; - INFO("Opening {%s}", Name_BMP); - FILE *Image = fopen(Name_BMP, "rb"); - if (!Image) { - return(file_not_found); - } - - fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header - INFO("bfType %04X", BMP_Header.bfType); - //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); - if (BMP_Header.bfType != BF_TYPE) { - fclose(Image); - return(not_bmp_format); - } - + // Now, Read the bitmap info header fread(&BMP_Info, 1, sizeof(BMP_Info), Image); //HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info)); BPP_t = BMP_Info.biBitCount; @@ -513,11 +527,11 @@ SetGraphicsCursor(x, y); _StartGraphicsStream(); - start_data = BMP_Header.bfOffBits; - HexDump("Raw Data", (uint8_t *)&start_data, 32); + //start_data = BMP_Header.bfOffBits; + //HexDump("Raw Data", (uint8_t *)&start_data, 32); //INFO("(%d,%d) (%d,%d), [%d,%d]", x,y, PixelWidth,PixelHeight, lineBufSize, padd); for (j = PixelHeight - 1; j >= 0; j--) { //Lines bottom up - offset = start_data + j * (lineBufSize + padd); // start of line + offset = fileOffset + j * (lineBufSize + padd); // start of line fseek(Image, offset, SEEK_SET); fread(lineBuffer, 1, lineBufSize, Image); // read a line - slow ! //INFO("offset: %6X", offset); @@ -544,14 +558,89 @@ } pixelStream(pixelBuffer, PixelWidth, x, y++); } + _EndGraphicsStream(); + WindowMax(); free(lineBuffer); free(colorPalette); - fclose(Image); - _EndGraphicsStream(); - WindowMax(); return (noerror); } + +RetCode_t GraphicsDisplay::RenderImageFile(loc_t x, loc_t y, const char *FileName) +{ + if (mystrnicmp(FileName + strlen(FileName) - 4, ".bmp", 4) == 0) { + return RenderBitmapFile(x,y,FileName); + } else if (mystrnicmp(FileName + strlen(FileName) - 4, ".ico", 4) == 0) { + return RenderIconFile(x,y,FileName); + } else { + return not_supported_format; + } +} + +RetCode_t GraphicsDisplay::RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP) +{ + BITMAPFILEHEADER BMP_Header; + + INFO("Opening {%s}", Name_BMP); + FILE *Image = fopen(Name_BMP, "rb"); + if (!Image) { + return(file_not_found); + } + + fread(&BMP_Header, 1, sizeof(BMP_Header), Image); // get the BMP Header + INFO("bfType %04X", BMP_Header.bfType); + //HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header)); + if (BMP_Header.bfType != BF_TYPE) { + fclose(Image); + return(not_bmp_format); + } + RetCode_t rt = _RenderBitmap(x, y, BMP_Header.bfOffBits, Image); + if (rt != noerror) { + return rt; + } else { + fclose(Image); + return (noerror); + } +} + +RetCode_t GraphicsDisplay::RenderIconFile(loc_t x, loc_t y, const char *Name_ICO) +{ + ICOFILEHEADER ICO_Header; + ICODIRENTRY ICO_DirEntry; + + INFO("Opening {%s}", Name_ICO); + FILE *Image = fopen(Name_ICO, "rb"); + if (!Image) { + return(file_not_found); + } + + fread(&ICO_Header, 1, sizeof(ICO_Header), Image); // get the BMP Header + HexDump("ICO_Header", (uint8_t *)&ICO_Header, sizeof(ICO_Header)); + if (ICO_Header.Reserved_zero != 0 + || ICO_Header.icType != IC_TYPE + || ICO_Header.icImageCount == 0) { + fclose(Image); + return(not_ico_format); + } + + // Read ONLY the first of n possible directory entries. + fread(&ICO_DirEntry, 1, sizeof(ICO_DirEntry), Image); + HexDump("ICO_DirEntry", (uint8_t *)&ICO_DirEntry, sizeof(ICO_DirEntry)); + INFO("biBitCount %04X", ICO_DirEntry.biBitCount); + if (ICO_DirEntry.biBitCount != 0) { // Expecting this to be zero for ico + fclose(Image); + return(not_supported_format); + } + + RetCode_t rt = _RenderBitmap(x, y, ICO_DirEntry.bfOffBits, Image); + if (rt == noerror) { + fclose(Image); + return (noerror); + } else { + return rt; + } +} + int GraphicsDisplay::columns() { return width() / 8;
--- a/GraphicsDisplay.h Sat Feb 08 17:35:45 2014 +0000 +++ b/GraphicsDisplay.h Sun Feb 23 17:58:39 2014 +0000 @@ -218,6 +218,28 @@ /// RGBQUAD RGB16ToRGBQuad(color_t c); + /// This method attempts to render a specified graphics image file at + /// the specified screen location. + /// + /// This supports several variants of the following file types: + /// \li Bitmap file format, + /// \li Icon file format. + /// + /// @note The specified image width and height, when adjusted for the + /// x and y origin, must fit on the screen, or the image will not + /// be shown (it does not clip the image). + /// + /// @note The file extension is tested, and if it ends in a supported + /// format, the appropriate handler is called to render that image. + /// + /// @param x is the horizontal pixel coordinate + /// @param y is the vertical pixel coordinate + /// @param FileName refers to the fully qualified path and file on + /// a mounted file system. + /// @returns success or error code. + /// + RetCode_t RenderImageFile(loc_t x, loc_t y, const char *FileName); + /// This method reads a disk file that is in bitmap format and /// puts it on the screen. /// @@ -252,11 +274,29 @@ /// /// @param x is the horizontal pixel coordinate /// @param y is the vertical pixel coordinate - /// @param Name_BMP is the filename on the local file system. + /// @param Name_BMP is the filename on the mounted file system. /// @returns success or error code. /// RetCode_t RenderBitmapFile(loc_t x, loc_t y, const char *Name_BMP); + + /// This method reads a disk file that is in ico format and + /// puts it on the screen. + /// + /// Reading the disk is slow, but a typical icon file is small + /// so it should be ok. + /// + /// @note An Icon file can have more than one icon in it. This + /// implementation only processes the first image in the file. + /// + /// @param x is the horizontal pixel coordinate + /// @param y is the vertical pixel coordinate + /// @param Name_ICO is the filename on the mounted file system. + /// @returns success or error code. + /// + RetCode_t RenderIconFile(loc_t x, loc_t y, const char *Name_ICO); + + /// This method captures the specified area as a 24-bit bitmap file. /// /// Even though this is a 16-bit display, the stored image is in @@ -348,6 +388,19 @@ /// virtual RetCode_t _EndGraphicsStream(void) = 0; + /// Protected method to render an image given a file handle and + /// coordinates. + /// + /// @param x is the horizontal pixel coordinate + /// @param y is the vertical pixel coordinate + /// @param w is the image width restriction, or zero to permit full image width. + /// @param h is the image height restriction, or zero to permit full image height. + /// @param fileOffset is the offset into the file where the image data starts + /// @param Image is the filename stream already opened for the data. + /// @returns success or error code. + /// + RetCode_t _RenderBitmap(loc_t x, loc_t y, uint32_t fileOffset, FILE * Image); + #ifdef LOCALFONT virtual int blitbit(int x, int y, int w, int h, const char * color); #endif