Richard Parker / EALCD
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);
-    }
-}
-
-