Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: widgets/EAImage.cpp
- Revision:
- 7:6cf21b018420
- Parent:
- 6:4fe6f365cbeb
--- a/widgets/EAImage.cpp Thu May 06 23:32:14 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,647 +0,0 @@
-// Copyright 2010 Richard Parker
-
-#include "mbed.h"
-
-#include "EAImage.h"
-
-#include "../graphics/EAPen.h"
-#include "../graphics/EAColor.h"
-#include "../screen/EALCD.h"
-
-EAImage::EAImage()
-: _path(NULL),
- _palette(NULL),
- _dataOffset(0),
- _mask(false),
- _cached(false),
- _cache(NULL),
- _size(0L),
- _pos(0L)
-{
- // Start from known state.
- unload();
-}
-
-EAImage::~EAImage()
-{
- unload();
-}
-
-int EAImage::_feof(FILE* stream)
-{
- if (isCached() == true)
- {
- return (_pos < _size) ? 0 : 1;
- } else {
- return feof(stream);
- }
-}
-
-
-int EAImage::_fseek(FILE* stream, long int offset, int origin)
-{
- if (isCached() == true)
- {
- switch (origin)
- {
- default:
- case SEEK_SET:
- _pos = offset;
- break;
- case SEEK_CUR:
- _pos = _pos + offset;
- break;
- case SEEK_END:
- _pos = (_size-1) + offset;
- break;
- }
-
- // Make sure position within range.
- if (_pos < 0)
- {
- _pos = 0;
- return 0;
- }
-
- if (_pos > (_size-1))
- {
- _pos = (_size-1);
- return 0;
- }
-
- // Error.
- return 1;
- } else {
- return fseek(stream, offset, origin);
- }
-}
-
-size_t EAImage::_fread(void* ptr, size_t size, size_t count, FILE* stream)
-{
- if (isCached() == true)
- {
- // Truncate size to fit array if needed.
- if (_pos + (count*size) > _size)
- {
- count = (_size - _pos)/size;
- }
-
- if (count <= 0)
- {
- return 0;
- }
-
- // Now copy out of cache to array.
- memcpy(ptr, &_cache[_pos], count*size);
-
- // Update the file position.
- _pos = _pos + (count*size);
-
- // Return the number of bytes read.
- return count;
- } else {
- return fread(ptr, size, count, stream);
- }
-}
-
-bool EAImage::_loadCache(FILE* fp)
-{
- // Can't do anything with a null pointer.
- if (fp == NULL)
- {
- return false;
- }
-
- // Clear any previously loaded cache.
- if (_cache != NULL)
- {
- delete[] _cache;
- _cache = NULL;
- }
- _size = 0L;
- _pos = 0L;
-
- if (isCached() == false)
- {
- return true;
- }
-
- // Get the size of the file.
- fseek(fp, 0, SEEK_END);
- long int size = ftell(fp);
-
- if (size == -1)
- {
- // Something went wronmg with the command.
- return false;
- }
-
- // Now create a cache large enough to hold all of the image data.
- _cache = new char[size];
-
- if (_cache == NULL)
- {
- // Unable to allocate enough space for the font.
- return false;
- }
-
- // Now rewind file pointer back to the beginning.
- rewind(fp);
-
- const unsigned int CHUNK_SIZE = 100;
- long int sizeRead = 0;
- long int totalSizeRead = 0;
-
- // Load in small chunks at a time.
- while (!feof(fp))
- {
- // Read into the buffer.
- sizeRead = fread(&_cache[totalSizeRead], 1, CHUNK_SIZE, fp);
-
- // Update total count of amount of data loaded.
- totalSizeRead += sizeRead;
- }
-
- // Check that the whole file loaded.
- if (totalSizeRead != size)
- {
- // Clear cache.
- delete[] _cache;
- _cache = NULL;
-
- // Return error.
- return false;
- }
-
- // Record size and position.
- _size = size;
- _pos = 0L;
-
- return true;
-}
-
-bool EAImage::_loadPalette(FILE* fp)
-{
- // Can't do anything with a null pointer unless cached.
- if ((fp == NULL) && (isCached() == false))
- {
- return false;
- }
-
- // Clear any previously loaded palette.
- if (_palette != NULL)
- {
- delete[] _palette;
- _palette = NULL;
- }
-
- // If the number of bits is not less than 16 then return after having cleared the
- // palette. There is no palette required.
- if (info().bitsPerPixel >= 16)
- {
- return true;
- }
-
- // First create a palette of the required size.
- unsigned int noColors = info().noColors;
-
- // When 0 the number of colors is equal to 2^n where n is the bits per pixel.
- if (noColors == 0)
- {
- noColors = pow((double)2, info().bitsPerPixel);
- }
-
- // Create the palette and assign the memory.
- _palette = new EAColor[noColors];
-
- // Now parse the palette. First seek to the start of the palette. This must be the
- // start of the bitmap data minus the number of colour entries multiplied by 4 (the
- // colours are stored as 4 byte long entries, the last byte can be ignored).
- unsigned int offset = _dataOffset - (noColors*4);
-
- // Seek to the start of the table.
- _fseek(fp, offset, SEEK_SET);
- unsigned char buffer[4];
-
- // Iterate through the table filling the palette as needed.
- for (int i = 0; i < noColors; i++)
- {
- int sizeRead = _fread(&buffer, 4, 1, fp);
-
- if (sizeRead == 1)
- {
- _palette[i].setRgb(buffer[2], buffer[1], buffer[0]);
- }
- }
-
- return true;
-}
-
-bool EAImage::_loadHeader(const char* path)
-{
- if (path == NULL)
- {
- // Invalid path passed in.
- return false;
- }
-
- // Try and open the file, check type and load width and height.
- FILE* fp = fopen(path, "r");
- if (fp == NULL)
- {
- return false;
- }
-
- unsigned int bufint = 0;
- unsigned int offset = 0;
-
- // Read the magic numbers at start.
- fread(&bufint, 1, 2, fp);
- if (bufint != 0x4d42)
- {
- // Clean up file handle.
- fclose(fp);
- unload();
-
- // Header incorrect.
- return false;
- }
-
- // Now read the bmp file size.
- fread(&bufint, 1, 4, fp);
-
- // Now read the two creator values and throw away.
- fread(&bufint, 1, 2, fp);
- fread(&bufint, 1, 2, fp);
-
- // Now read the offset for the bitmap data.
- fread(&bufint, 1, 4, fp);
- offset = bufint;
-
- // Retrieve the header.
- fread(&_header, sizeof(EABMPHeader), 1, fp);
-
- // Make sure the compression type is a value that can be dealt with.
- if ((info().compressionType != 3) && (info().compressionType != 0))
- {
- // Clean up file handle.
- fclose(fp);
- unload();
-
- // Header incorrect.
- return false;
- }
-
- // Set the values for later.
- _dataOffset = offset;
- setWidth(info().width);
- setHeight(info().height);
-
- // If the image is to be cached then load the cache.
- if (_loadCache(fp) == false)
- {
- // Clean up file handle.
- fclose(fp);
- unload();
-
- // Header incorrect.
- return false;
- }
-
- // Close the file.
- fclose(fp);
-
- return true;
-}
-
-int EAImage::_wordsInRow()
-{
- // If there were no padding to 32 bit boundaries this would be the number of bits per row
- // in the file.
- int bitsPerWidth = width() * info().bitsPerPixel;
-
- // This is the row size with padding on the end.
- int remainder = (bitsPerWidth % 32);
- int bitsPerRow = (remainder == 0) ? bitsPerWidth : bitsPerWidth + (32 - remainder);
-
- // Return the size in number of words.
- return (bitsPerRow / 32);
-}
-
-int EAImage::_wordForX(unsigned int x)
-{
- int bitForX = x * info().bitsPerPixel;
-
- return (bitForX / 32);
-}
-
-int EAImage::_xWordOffset(unsigned int x)
-{
- int bitForX = x * info().bitsPerPixel;
-
- return (bitForX % 32);
-}
-
-unsigned short EAImage::_getColourAtOffset(unsigned int word, int offset)
-{
- // Sort bytes for endianness.
- unsigned char* cptr;
- unsigned short result = 0x0000;
-
- // Now need to decide how to cast the value to a colour.
- switch (info().bitsPerPixel)
- {
- // Swap the bytes around.
- case 32:
- case 4:
- case 8:
- case 1:
- unsigned char tmp;
- cptr = (unsigned char*)&word;
- tmp = cptr[0];
- cptr[0] = cptr[3];
- cptr[3] = tmp;
- tmp = cptr[1];
- cptr[1] = cptr[2];
- cptr[2] = tmp;
- break;
-
- default:
- // Swap the 16bits around.
- case 16:
- unsigned char tmpa;
- unsigned char tmpb;
- cptr = (unsigned char*)&word;
- tmpa = cptr[1];
- tmpb = cptr[0];
- cptr[1] = cptr[3];
- cptr[0] = cptr[2];
- cptr[3] = tmpa;
- cptr[2] = tmpb;
- break;
- }
-
- // First shift off the pixels above.
- word = word << offset;
-
- // Now shift down so that pixel is in lsb.
- word = word >> (32 - info().bitsPerPixel);
-
- EAColor c;
-
- // Now need to decide how to cast the value to a colour.
- switch (info().bitsPerPixel)
- {
- case 8:
- case 4:
- case 1:
- if (_palette != NULL)
- {
- result = _palette[word].rawValue();
- } else {
- result = 0x0000;
- }
- break;
-
- // By default just cast to unsigned short and return.
- default:
- case 16:
- result = (unsigned short)(word);
- break;
-
- case 24:
- case 32:
- unsigned char b = ((word << 0) >> 24);
- unsigned char g = ((word << 8) >> 24);
- unsigned char r = ((word << 16) >> 24);
-
- c.setRgb(r, g, b);
- result = c.rawValue();
- break;
- }
-
- return result;
-}
-
-bool EAImage::load(const char* path)
-{
- if (path == NULL)
- {
- // Reset all of the state.
- unload();
-
- // Invalid path passed in.
- return false;
- }
-
- if (_loadHeader(path) == false)
- {
- // Reset all of the state.
- unload();
-
- return false;
- }
-
- int pathLen = strlen(path);
-
- // If already loaded an image then clear to load the new one.
- if (_path != NULL)
- {
- delete[] _path;
- _path = NULL;
- }
-
- // Now allocate enough space to hold path. Note +1 for null character.
- _path = new char[pathLen+1];
-
- // Now copy over passed in path to path variable.
- strcpy(_path, path);
-
- // Image loaded successfully.
- return true;
-}
-
-void EAImage::unload()
-{
- // Empty the header struct.
- _header.headerSize = 0;
- _header.width = 0;
- _header.height = 0;
- _header.noColorPlanes = 0;
- _header.bitsPerPixel = 0;
- _header.compressionType = 0;
- _header.bmpSize = 0;
- _header.horizontalRes = 0;
- _header.verticalRes = 0;
- _header.noColors = 0;
- _header.noImportantColors = 0;
-
- // Clear the path.
- if (_path != NULL)
- {
- delete[] _path;
- _path = NULL;
- }
-
- // Clear the palette.
- if (_palette != NULL)
- {
- delete[] _palette;
- _palette = NULL;
- }
-
- // Clear the data offset.
- _dataOffset = 0;
-
- // Set the size to 0.
- setWidth(0);
- setHeight(0);
-
- // Empty the cache.
- if (_cache != NULL)
- {
- delete[] _cache;
- _cache = NULL;
- }
- _size = 0L;
- _pos = 0L;
-}
-
-void EAImage::paint(EALCD& lcd)
-{
- paint(lcd, 0, 0, width(), height());
-}
-
-void EAImage::paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
-{
- if (isValid() == false)
- {
- return;
- }
-
- // Don't allow draw out of range.
- if (x + w > width())
- {
- return;
- }
-
- if (y + h > height())
- {
- return;
- }
-
- // Buffer to hold load one line at a time this must be large enough to hold all of the data used
- // for a line in the file. Note that the line in the file is padded so that it always ends on a
- // 32 bit boundary.
- int wordsInRow = _wordsInRow();
- unsigned int buffer[wordsInRow];
- int xD = 0;
- int yD = 0;
- int wordOffset = 0;
- int bitsPerPixel = info().bitsPerPixel;
- unsigned short data = 0;
-
- // Try and open the file, skip straight to the data.
- FILE* fp = NULL;
- if (isCached() == false)
- {
- fp = fopen(_path, "r");
- if (fp == NULL)
- {
- return;
- }
- }
-
- // If the bits per pixel are less than 16 then the bitmap is using a colour
- // palette which should be loaded first.
- if (_loadPalette(fp) == false)
- {
- if (isCached() == false)
- {
- fclose(fp);
- }
-
- return;
- }
-
- // Skip the header and size.
- _fseek(fp, _dataOffset, SEEK_SET);
-
- // Prepare the lcd for drawing.
- lcd._window(this->x(), this->y(), w, h);
- lcd._moveTo(this->x(), this->y());
-
- // Move in the file to the first pixel in the window.
- _fseek(fp, (y*wordsInRow*4)+(_wordForX(x)*4), SEEK_CUR);
-
- // Now read the data.
- while (!_feof(fp))
- {
- wordOffset = _xWordOffset(x);
-
- int sizeRead = _fread(&buffer, 4, wordsInRow, fp);
-
- for (int i = 0; i < sizeRead; i++)
- {
- while (wordOffset < 32)
- {
- // Convert the colour to a 16 bit colour value that can be written directly to the screen.
- data = _getColourAtOffset(buffer[i], wordOffset);
-
- if (isMask() == true)
- {
- // When a mask the 0x0000 value is transparent anything else is drawn with the pen color.
- if (data == 0x0000)
- {
- lcd.noop();
- } else {
- lcd._writeToDisplay(lcd.pen().color().rawValue());
- }
- } else {
- // Not a mask so just use colour that have loaded.
- lcd._writeToDisplay(data);
- }
-
- // Got to next pixel in the word.
- wordOffset += bitsPerPixel;
-
- // Keep count of current x value.
- xD++;
- if (xD == w)
- {
- break;
- }
- }
- wordOffset = 0;
-
- // When written all required pixels exit.
- if (xD == w)
- {
- xD = 0;
- break;
- }
- }
-
- // Keep count of curernt y value.
- yD++;
- if (yD == h)
- {
- break;
- }
- }
-
- // Clear the palette.
- if (_palette != NULL)
- {
- delete[] _palette;
- _palette = NULL;
- }
-
- if (isCached() == false)
- {
- // Close the file and release handle.
- fclose(fp);
- }
-}
-
-