Richard Parker / EALCD

widgets/EAImage.cpp

Committer:
richardparker
Date:
2010-02-11
Revision:
0:839ecbf5cb2a
Child:
1:f04bcaea1d60

File content as of revision 0:839ecbf5cb2a:

// 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),
    _dataOffset(0)
{
}

EAImage::~EAImage()
{
}

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;
    EABMPHeader header;

    // Read the magic numbers at start.
    fread(&bufint, 1, 2, fp);   
    if (bufint != 0x4d42)
    {
        // Clean up file handle.
        fclose(fp);
    
        // 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 bits per pixel is 16 and compression type is bit fields.
    if ((header.bitsPerPixel != 16) || (header.compressionType != 3))
    {   
        // Clean up file handle.
        fclose(fp);
    
        // Header incorrect.
        return false;
    }
    
    // Set the values for later.
    _dataOffset = offset;
    setWidth(header.width);
    setHeight(header.height);
          
    // Close the file.
    fclose(fp);
    
    return true;
}

bool EAImage::load(const char* path)
{
    if (path == NULL)
    {
        // Invalid path passed in.
        return false;
    }

    if (_loadHeader(path) == false)
    {
        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::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.
    int pixelsInLine = width() + (width() % 2);
    unsigned short buffer[pixelsInLine];
    int xD = 0;
    int yD = 0;
    
    // Try and open the file, skip straight to the data.
    FILE* fp = fopen(_path, "r");
    if (fp == NULL)
    {
        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*pixelsInLine*2)+(x*2), SEEK_CUR);
           
    // Now read the data.
    while (!feof(fp))
    {    
        int sizeRead = fread(&buffer, 2, pixelsInLine, fp);
        
        for (int i = 0; i < sizeRead; i++)
        {
            lcd._writeToDisplay(buffer[i]);
            
            // Keep count of current x value.
            xD++;
            if (xD == w)
            {
                xD = 0;
                break;
            }            
        }

        // Keep count of curernt y value.
        yD++;
        if (yD == h)
        {
            break;
        }            
    }
    
    // Close the file and release handle.
    fclose(fp);
    
}