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.
images/EAImage.cpp@7:6cf21b018420, 2010-11-01 (annotated)
- Committer:
- richardparker
- Date:
- Mon Nov 01 13:07:40 2010 +0000
- Revision:
- 7:6cf21b018420
Embedded Artists LCD panel:- Version 0.7
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| richardparker | 7:6cf21b018420 | 1 | // Copyright 2010 Richard Parker | 
| richardparker | 7:6cf21b018420 | 2 | |
| richardparker | 7:6cf21b018420 | 3 | #include "mbed.h" | 
| richardparker | 7:6cf21b018420 | 4 | |
| richardparker | 7:6cf21b018420 | 5 | #include "EAImage.h" | 
| richardparker | 7:6cf21b018420 | 6 | |
| richardparker | 7:6cf21b018420 | 7 | #include "../graphics/EAPen.h" | 
| richardparker | 7:6cf21b018420 | 8 | #include "../graphics/EAColor.h" | 
| richardparker | 7:6cf21b018420 | 9 | #include "../screen/EALCD.h" | 
| richardparker | 7:6cf21b018420 | 10 | |
| richardparker | 7:6cf21b018420 | 11 | EAImage::EAImage() | 
| richardparker | 7:6cf21b018420 | 12 | : _path(NULL), | 
| richardparker | 7:6cf21b018420 | 13 | _palette(NULL), | 
| richardparker | 7:6cf21b018420 | 14 | _dataOffset(0), | 
| richardparker | 7:6cf21b018420 | 15 | _mask(false) | 
| richardparker | 7:6cf21b018420 | 16 | { | 
| richardparker | 7:6cf21b018420 | 17 | // Start from known state. | 
| richardparker | 7:6cf21b018420 | 18 | unload(); | 
| richardparker | 7:6cf21b018420 | 19 | } | 
| richardparker | 7:6cf21b018420 | 20 | |
| richardparker | 7:6cf21b018420 | 21 | EAImage::~EAImage() | 
| richardparker | 7:6cf21b018420 | 22 | { | 
| richardparker | 7:6cf21b018420 | 23 | unload(); | 
| richardparker | 7:6cf21b018420 | 24 | } | 
| richardparker | 7:6cf21b018420 | 25 | |
| richardparker | 7:6cf21b018420 | 26 | int EAImage::_feof(FILE* stream) | 
| richardparker | 7:6cf21b018420 | 27 | { | 
| richardparker | 7:6cf21b018420 | 28 | return feof(stream); | 
| richardparker | 7:6cf21b018420 | 29 | } | 
| richardparker | 7:6cf21b018420 | 30 | |
| richardparker | 7:6cf21b018420 | 31 | |
| richardparker | 7:6cf21b018420 | 32 | int EAImage::_fseek(FILE* stream, long int offset, int origin) | 
| richardparker | 7:6cf21b018420 | 33 | { | 
| richardparker | 7:6cf21b018420 | 34 | return fseek(stream, offset, origin); | 
| richardparker | 7:6cf21b018420 | 35 | } | 
| richardparker | 7:6cf21b018420 | 36 | |
| richardparker | 7:6cf21b018420 | 37 | size_t EAImage::_fread(void* ptr, size_t size, size_t count, FILE* stream) | 
| richardparker | 7:6cf21b018420 | 38 | { | 
| richardparker | 7:6cf21b018420 | 39 | return fread(ptr, size, count, stream); | 
| richardparker | 7:6cf21b018420 | 40 | } | 
| richardparker | 7:6cf21b018420 | 41 | |
| richardparker | 7:6cf21b018420 | 42 | bool EAImage::_loadPalette(FILE* fp) | 
| richardparker | 7:6cf21b018420 | 43 | { | 
| richardparker | 7:6cf21b018420 | 44 | // Can't do anything with a null pointer unless cached. | 
| richardparker | 7:6cf21b018420 | 45 | if (fp == NULL) | 
| richardparker | 7:6cf21b018420 | 46 | { | 
| richardparker | 7:6cf21b018420 | 47 | return false; | 
| richardparker | 7:6cf21b018420 | 48 | } | 
| richardparker | 7:6cf21b018420 | 49 | |
| richardparker | 7:6cf21b018420 | 50 | // Clear any previously loaded palette. | 
| richardparker | 7:6cf21b018420 | 51 | if (_palette != NULL) | 
| richardparker | 7:6cf21b018420 | 52 | { | 
| richardparker | 7:6cf21b018420 | 53 | delete[] _palette; | 
| richardparker | 7:6cf21b018420 | 54 | _palette = NULL; | 
| richardparker | 7:6cf21b018420 | 55 | } | 
| richardparker | 7:6cf21b018420 | 56 | |
| richardparker | 7:6cf21b018420 | 57 | // If the number of bits is not less than 16 then return after having cleared the | 
| richardparker | 7:6cf21b018420 | 58 | // palette. There is no palette required. | 
| richardparker | 7:6cf21b018420 | 59 | if (info().bitsPerPixel >= 16) | 
| richardparker | 7:6cf21b018420 | 60 | { | 
| richardparker | 7:6cf21b018420 | 61 | return true; | 
| richardparker | 7:6cf21b018420 | 62 | } | 
| richardparker | 7:6cf21b018420 | 63 | |
| richardparker | 7:6cf21b018420 | 64 | // First create a palette of the required size. | 
| richardparker | 7:6cf21b018420 | 65 | unsigned int noColors = info().noColors; | 
| richardparker | 7:6cf21b018420 | 66 | |
| richardparker | 7:6cf21b018420 | 67 | // When 0 the number of colors is equal to 2^n where n is the bits per pixel. | 
| richardparker | 7:6cf21b018420 | 68 | if (noColors == 0) | 
| richardparker | 7:6cf21b018420 | 69 | { | 
| richardparker | 7:6cf21b018420 | 70 | noColors = pow((double)2, info().bitsPerPixel); | 
| richardparker | 7:6cf21b018420 | 71 | } | 
| richardparker | 7:6cf21b018420 | 72 | |
| richardparker | 7:6cf21b018420 | 73 | // Create the palette and assign the memory. | 
| richardparker | 7:6cf21b018420 | 74 | _palette = new EAColor[noColors]; | 
| richardparker | 7:6cf21b018420 | 75 | |
| richardparker | 7:6cf21b018420 | 76 | // Now parse the palette. First seek to the start of the palette. This must be the | 
| richardparker | 7:6cf21b018420 | 77 | // start of the bitmap data minus the number of colour entries multiplied by 4 (the | 
| richardparker | 7:6cf21b018420 | 78 | // colours are stored as 4 byte long entries, the last byte can be ignored). | 
| richardparker | 7:6cf21b018420 | 79 | unsigned int offset = _dataOffset - (noColors*4); | 
| richardparker | 7:6cf21b018420 | 80 | |
| richardparker | 7:6cf21b018420 | 81 | // Seek to the start of the table. | 
| richardparker | 7:6cf21b018420 | 82 | _fseek(fp, offset, SEEK_SET); | 
| richardparker | 7:6cf21b018420 | 83 | unsigned char buffer[4]; | 
| richardparker | 7:6cf21b018420 | 84 | |
| richardparker | 7:6cf21b018420 | 85 | // Iterate through the table filling the palette as needed. | 
| richardparker | 7:6cf21b018420 | 86 | for (int i = 0; i < noColors; i++) | 
| richardparker | 7:6cf21b018420 | 87 | { | 
| richardparker | 7:6cf21b018420 | 88 | int sizeRead = _fread(&buffer, 4, 1, fp); | 
| richardparker | 7:6cf21b018420 | 89 | |
| richardparker | 7:6cf21b018420 | 90 | if (sizeRead == 1) | 
| richardparker | 7:6cf21b018420 | 91 | { | 
| richardparker | 7:6cf21b018420 | 92 | _palette[i].setRgb(buffer[2], buffer[1], buffer[0]); | 
| richardparker | 7:6cf21b018420 | 93 | } | 
| richardparker | 7:6cf21b018420 | 94 | } | 
| richardparker | 7:6cf21b018420 | 95 | |
| richardparker | 7:6cf21b018420 | 96 | return true; | 
| richardparker | 7:6cf21b018420 | 97 | } | 
| richardparker | 7:6cf21b018420 | 98 | |
| richardparker | 7:6cf21b018420 | 99 | bool EAImage::_loadHeader(const std::string& path) | 
| richardparker | 7:6cf21b018420 | 100 | { | 
| richardparker | 7:6cf21b018420 | 101 | if (path.empty() == true) | 
| richardparker | 7:6cf21b018420 | 102 | { | 
| richardparker | 7:6cf21b018420 | 103 | // Invalid path passed in. | 
| richardparker | 7:6cf21b018420 | 104 | return false; | 
| richardparker | 7:6cf21b018420 | 105 | } | 
| richardparker | 7:6cf21b018420 | 106 | |
| richardparker | 7:6cf21b018420 | 107 | // Try and open the file, check type and load width and height. | 
| richardparker | 7:6cf21b018420 | 108 | FILE* fp = fopen(path.c_str(), "r"); | 
| richardparker | 7:6cf21b018420 | 109 | if (fp == NULL) | 
| richardparker | 7:6cf21b018420 | 110 | { | 
| richardparker | 7:6cf21b018420 | 111 | return false; | 
| richardparker | 7:6cf21b018420 | 112 | } | 
| richardparker | 7:6cf21b018420 | 113 | |
| richardparker | 7:6cf21b018420 | 114 | unsigned int bufint = 0; | 
| richardparker | 7:6cf21b018420 | 115 | unsigned int offset = 0; | 
| richardparker | 7:6cf21b018420 | 116 | |
| richardparker | 7:6cf21b018420 | 117 | // Read the magic numbers at start. | 
| richardparker | 7:6cf21b018420 | 118 | fread(&bufint, 1, 2, fp); | 
| richardparker | 7:6cf21b018420 | 119 | if (bufint != 0x4d42) | 
| richardparker | 7:6cf21b018420 | 120 | { | 
| richardparker | 7:6cf21b018420 | 121 | // Clean up file handle. | 
| richardparker | 7:6cf21b018420 | 122 | fclose(fp); | 
| richardparker | 7:6cf21b018420 | 123 | unload(); | 
| richardparker | 7:6cf21b018420 | 124 | |
| richardparker | 7:6cf21b018420 | 125 | // Header incorrect. | 
| richardparker | 7:6cf21b018420 | 126 | return false; | 
| richardparker | 7:6cf21b018420 | 127 | } | 
| richardparker | 7:6cf21b018420 | 128 | |
| richardparker | 7:6cf21b018420 | 129 | // Now read the bmp file size. | 
| richardparker | 7:6cf21b018420 | 130 | fread(&bufint, 1, 4, fp); | 
| richardparker | 7:6cf21b018420 | 131 | |
| richardparker | 7:6cf21b018420 | 132 | // Now read the two creator values and throw away. | 
| richardparker | 7:6cf21b018420 | 133 | fread(&bufint, 1, 2, fp); | 
| richardparker | 7:6cf21b018420 | 134 | fread(&bufint, 1, 2, fp); | 
| richardparker | 7:6cf21b018420 | 135 | |
| richardparker | 7:6cf21b018420 | 136 | // Now read the offset for the bitmap data. | 
| richardparker | 7:6cf21b018420 | 137 | fread(&bufint, 1, 4, fp); | 
| richardparker | 7:6cf21b018420 | 138 | offset = bufint; | 
| richardparker | 7:6cf21b018420 | 139 | |
| richardparker | 7:6cf21b018420 | 140 | // Retrieve the header. | 
| richardparker | 7:6cf21b018420 | 141 | fread(&_header, sizeof(EABMPHeader), 1, fp); | 
| richardparker | 7:6cf21b018420 | 142 | |
| richardparker | 7:6cf21b018420 | 143 | // Make sure the compression type is a value that can be dealt with. | 
| richardparker | 7:6cf21b018420 | 144 | if ((info().compressionType != 3) && (info().compressionType != 0)) | 
| richardparker | 7:6cf21b018420 | 145 | { | 
| richardparker | 7:6cf21b018420 | 146 | // Clean up file handle. | 
| richardparker | 7:6cf21b018420 | 147 | fclose(fp); | 
| richardparker | 7:6cf21b018420 | 148 | unload(); | 
| richardparker | 7:6cf21b018420 | 149 | |
| richardparker | 7:6cf21b018420 | 150 | // Header incorrect. | 
| richardparker | 7:6cf21b018420 | 151 | return false; | 
| richardparker | 7:6cf21b018420 | 152 | } | 
| richardparker | 7:6cf21b018420 | 153 | |
| richardparker | 7:6cf21b018420 | 154 | // Set the values for later. | 
| richardparker | 7:6cf21b018420 | 155 | _dataOffset = offset; | 
| richardparker | 7:6cf21b018420 | 156 | setWidth(info().width); | 
| richardparker | 7:6cf21b018420 | 157 | setHeight(info().height); | 
| richardparker | 7:6cf21b018420 | 158 | |
| richardparker | 7:6cf21b018420 | 159 | // If the bits per pixel are less than 16 then the bitmap is using a colour | 
| richardparker | 7:6cf21b018420 | 160 | // palette which should be loaded first. | 
| richardparker | 7:6cf21b018420 | 161 | if (_loadPalette(fp) == false) | 
| richardparker | 7:6cf21b018420 | 162 | { | 
| richardparker | 7:6cf21b018420 | 163 | fclose(fp); | 
| richardparker | 7:6cf21b018420 | 164 | |
| richardparker | 7:6cf21b018420 | 165 | return false; | 
| richardparker | 7:6cf21b018420 | 166 | } | 
| richardparker | 7:6cf21b018420 | 167 | |
| richardparker | 7:6cf21b018420 | 168 | // Close the file. | 
| richardparker | 7:6cf21b018420 | 169 | fclose(fp); | 
| richardparker | 7:6cf21b018420 | 170 | |
| richardparker | 7:6cf21b018420 | 171 | return true; | 
| richardparker | 7:6cf21b018420 | 172 | } | 
| richardparker | 7:6cf21b018420 | 173 | |
| richardparker | 7:6cf21b018420 | 174 | int EAImage::_wordsInRow() | 
| richardparker | 7:6cf21b018420 | 175 | { | 
| richardparker | 7:6cf21b018420 | 176 | // If there were no padding to 32 bit boundaries this would be the number of bits per row | 
| richardparker | 7:6cf21b018420 | 177 | // in the file. | 
| richardparker | 7:6cf21b018420 | 178 | int bitsPerWidth = width() * info().bitsPerPixel; | 
| richardparker | 7:6cf21b018420 | 179 | |
| richardparker | 7:6cf21b018420 | 180 | // This is the row size with padding on the end. | 
| richardparker | 7:6cf21b018420 | 181 | int remainder = (bitsPerWidth % 32); | 
| richardparker | 7:6cf21b018420 | 182 | int bitsPerRow = (remainder == 0) ? bitsPerWidth : bitsPerWidth + (32 - remainder); | 
| richardparker | 7:6cf21b018420 | 183 | |
| richardparker | 7:6cf21b018420 | 184 | // Return the size in number of words. | 
| richardparker | 7:6cf21b018420 | 185 | return (bitsPerRow / 32); | 
| richardparker | 7:6cf21b018420 | 186 | } | 
| richardparker | 7:6cf21b018420 | 187 | |
| richardparker | 7:6cf21b018420 | 188 | int EAImage::_wordForX(unsigned int x) | 
| richardparker | 7:6cf21b018420 | 189 | { | 
| richardparker | 7:6cf21b018420 | 190 | int bitForX = x * info().bitsPerPixel; | 
| richardparker | 7:6cf21b018420 | 191 | |
| richardparker | 7:6cf21b018420 | 192 | return (bitForX / 32); | 
| richardparker | 7:6cf21b018420 | 193 | } | 
| richardparker | 7:6cf21b018420 | 194 | |
| richardparker | 7:6cf21b018420 | 195 | int EAImage::_xWordOffset(unsigned int x) | 
| richardparker | 7:6cf21b018420 | 196 | { | 
| richardparker | 7:6cf21b018420 | 197 | int bitForX = x * info().bitsPerPixel; | 
| richardparker | 7:6cf21b018420 | 198 | |
| richardparker | 7:6cf21b018420 | 199 | return (bitForX % 32); | 
| richardparker | 7:6cf21b018420 | 200 | } | 
| richardparker | 7:6cf21b018420 | 201 | |
| richardparker | 7:6cf21b018420 | 202 | unsigned short EAImage::_getColourAtOffset(unsigned int word, int offset) | 
| richardparker | 7:6cf21b018420 | 203 | { | 
| richardparker | 7:6cf21b018420 | 204 | // Sort bytes for endianness. | 
| richardparker | 7:6cf21b018420 | 205 | unsigned char* cptr; | 
| richardparker | 7:6cf21b018420 | 206 | unsigned short result = 0x0000; | 
| richardparker | 7:6cf21b018420 | 207 | |
| richardparker | 7:6cf21b018420 | 208 | // Now need to decide how to cast the value to a colour. | 
| richardparker | 7:6cf21b018420 | 209 | switch (info().bitsPerPixel) | 
| richardparker | 7:6cf21b018420 | 210 | { | 
| richardparker | 7:6cf21b018420 | 211 | // Swap the bytes around. | 
| richardparker | 7:6cf21b018420 | 212 | case 32: | 
| richardparker | 7:6cf21b018420 | 213 | case 4: | 
| richardparker | 7:6cf21b018420 | 214 | case 8: | 
| richardparker | 7:6cf21b018420 | 215 | case 1: | 
| richardparker | 7:6cf21b018420 | 216 | unsigned char tmp; | 
| richardparker | 7:6cf21b018420 | 217 | cptr = (unsigned char*)&word; | 
| richardparker | 7:6cf21b018420 | 218 | tmp = cptr[0]; | 
| richardparker | 7:6cf21b018420 | 219 | cptr[0] = cptr[3]; | 
| richardparker | 7:6cf21b018420 | 220 | cptr[3] = tmp; | 
| richardparker | 7:6cf21b018420 | 221 | tmp = cptr[1]; | 
| richardparker | 7:6cf21b018420 | 222 | cptr[1] = cptr[2]; | 
| richardparker | 7:6cf21b018420 | 223 | cptr[2] = tmp; | 
| richardparker | 7:6cf21b018420 | 224 | break; | 
| richardparker | 7:6cf21b018420 | 225 | |
| richardparker | 7:6cf21b018420 | 226 | default: | 
| richardparker | 7:6cf21b018420 | 227 | // Swap the 16bits around. | 
| richardparker | 7:6cf21b018420 | 228 | case 16: | 
| richardparker | 7:6cf21b018420 | 229 | unsigned char tmpa; | 
| richardparker | 7:6cf21b018420 | 230 | unsigned char tmpb; | 
| richardparker | 7:6cf21b018420 | 231 | cptr = (unsigned char*)&word; | 
| richardparker | 7:6cf21b018420 | 232 | tmpa = cptr[1]; | 
| richardparker | 7:6cf21b018420 | 233 | tmpb = cptr[0]; | 
| richardparker | 7:6cf21b018420 | 234 | cptr[1] = cptr[3]; | 
| richardparker | 7:6cf21b018420 | 235 | cptr[0] = cptr[2]; | 
| richardparker | 7:6cf21b018420 | 236 | cptr[3] = tmpa; | 
| richardparker | 7:6cf21b018420 | 237 | cptr[2] = tmpb; | 
| richardparker | 7:6cf21b018420 | 238 | break; | 
| richardparker | 7:6cf21b018420 | 239 | } | 
| richardparker | 7:6cf21b018420 | 240 | |
| richardparker | 7:6cf21b018420 | 241 | // First shift off the pixels above. | 
| richardparker | 7:6cf21b018420 | 242 | word = word << offset; | 
| richardparker | 7:6cf21b018420 | 243 | |
| richardparker | 7:6cf21b018420 | 244 | // Now shift down so that pixel is in lsb. | 
| richardparker | 7:6cf21b018420 | 245 | word = word >> (32 - info().bitsPerPixel); | 
| richardparker | 7:6cf21b018420 | 246 | |
| richardparker | 7:6cf21b018420 | 247 | EAColor c; | 
| richardparker | 7:6cf21b018420 | 248 | |
| richardparker | 7:6cf21b018420 | 249 | // Now need to decide how to cast the value to a colour. | 
| richardparker | 7:6cf21b018420 | 250 | switch (info().bitsPerPixel) | 
| richardparker | 7:6cf21b018420 | 251 | { | 
| richardparker | 7:6cf21b018420 | 252 | case 8: | 
| richardparker | 7:6cf21b018420 | 253 | case 4: | 
| richardparker | 7:6cf21b018420 | 254 | case 1: | 
| richardparker | 7:6cf21b018420 | 255 | if (_palette != NULL) | 
| richardparker | 7:6cf21b018420 | 256 | { | 
| richardparker | 7:6cf21b018420 | 257 | result = _palette[word].rawValue(); | 
| richardparker | 7:6cf21b018420 | 258 | } else { | 
| richardparker | 7:6cf21b018420 | 259 | result = 0x0000; | 
| richardparker | 7:6cf21b018420 | 260 | } | 
| richardparker | 7:6cf21b018420 | 261 | break; | 
| richardparker | 7:6cf21b018420 | 262 | |
| richardparker | 7:6cf21b018420 | 263 | // By default just cast to unsigned short and return. | 
| richardparker | 7:6cf21b018420 | 264 | default: | 
| richardparker | 7:6cf21b018420 | 265 | case 16: | 
| richardparker | 7:6cf21b018420 | 266 | result = (unsigned short)(word); | 
| richardparker | 7:6cf21b018420 | 267 | break; | 
| richardparker | 7:6cf21b018420 | 268 | |
| richardparker | 7:6cf21b018420 | 269 | case 24: | 
| richardparker | 7:6cf21b018420 | 270 | case 32: | 
| richardparker | 7:6cf21b018420 | 271 | unsigned char b = ((word << 0) >> 24); | 
| richardparker | 7:6cf21b018420 | 272 | unsigned char g = ((word << 8) >> 24); | 
| richardparker | 7:6cf21b018420 | 273 | unsigned char r = ((word << 16) >> 24); | 
| richardparker | 7:6cf21b018420 | 274 | |
| richardparker | 7:6cf21b018420 | 275 | c.setRgb(r, g, b); | 
| richardparker | 7:6cf21b018420 | 276 | result = c.rawValue(); | 
| richardparker | 7:6cf21b018420 | 277 | break; | 
| richardparker | 7:6cf21b018420 | 278 | } | 
| richardparker | 7:6cf21b018420 | 279 | |
| richardparker | 7:6cf21b018420 | 280 | return result; | 
| richardparker | 7:6cf21b018420 | 281 | } | 
| richardparker | 7:6cf21b018420 | 282 | |
| richardparker | 7:6cf21b018420 | 283 | bool EAImage::load(const std::string& path) | 
| richardparker | 7:6cf21b018420 | 284 | { | 
| richardparker | 7:6cf21b018420 | 285 | if (path.empty() == true) | 
| richardparker | 7:6cf21b018420 | 286 | { | 
| richardparker | 7:6cf21b018420 | 287 | // Reset all of the state. | 
| richardparker | 7:6cf21b018420 | 288 | unload(); | 
| richardparker | 7:6cf21b018420 | 289 | |
| richardparker | 7:6cf21b018420 | 290 | // Invalid path passed in. | 
| richardparker | 7:6cf21b018420 | 291 | return false; | 
| richardparker | 7:6cf21b018420 | 292 | } | 
| richardparker | 7:6cf21b018420 | 293 | |
| richardparker | 7:6cf21b018420 | 294 | if (_loadHeader(path) == false) | 
| richardparker | 7:6cf21b018420 | 295 | { | 
| richardparker | 7:6cf21b018420 | 296 | // Reset all of the state. | 
| richardparker | 7:6cf21b018420 | 297 | unload(); | 
| richardparker | 7:6cf21b018420 | 298 | |
| richardparker | 7:6cf21b018420 | 299 | return false; | 
| richardparker | 7:6cf21b018420 | 300 | } | 
| richardparker | 7:6cf21b018420 | 301 | |
| richardparker | 7:6cf21b018420 | 302 | _path = path; | 
| richardparker | 7:6cf21b018420 | 303 | |
| richardparker | 7:6cf21b018420 | 304 | // Image loaded successfully. | 
| richardparker | 7:6cf21b018420 | 305 | return true; | 
| richardparker | 7:6cf21b018420 | 306 | } | 
| richardparker | 7:6cf21b018420 | 307 | |
| richardparker | 7:6cf21b018420 | 308 | void EAImage::unload() | 
| richardparker | 7:6cf21b018420 | 309 | { | 
| richardparker | 7:6cf21b018420 | 310 | // Empty the header struct. | 
| richardparker | 7:6cf21b018420 | 311 | _header.headerSize = 0; | 
| richardparker | 7:6cf21b018420 | 312 | _header.width = 0; | 
| richardparker | 7:6cf21b018420 | 313 | _header.height = 0; | 
| richardparker | 7:6cf21b018420 | 314 | _header.noColorPlanes = 0; | 
| richardparker | 7:6cf21b018420 | 315 | _header.bitsPerPixel = 0; | 
| richardparker | 7:6cf21b018420 | 316 | _header.compressionType = 0; | 
| richardparker | 7:6cf21b018420 | 317 | _header.bmpSize = 0; | 
| richardparker | 7:6cf21b018420 | 318 | _header.horizontalRes = 0; | 
| richardparker | 7:6cf21b018420 | 319 | _header.verticalRes = 0; | 
| richardparker | 7:6cf21b018420 | 320 | _header.noColors = 0; | 
| richardparker | 7:6cf21b018420 | 321 | _header.noImportantColors = 0; | 
| richardparker | 7:6cf21b018420 | 322 | |
| richardparker | 7:6cf21b018420 | 323 | // Clear the palette. | 
| richardparker | 7:6cf21b018420 | 324 | if (_palette != NULL) | 
| richardparker | 7:6cf21b018420 | 325 | { | 
| richardparker | 7:6cf21b018420 | 326 | //delete[] _palette; | 
| richardparker | 7:6cf21b018420 | 327 | _palette = NULL; | 
| richardparker | 7:6cf21b018420 | 328 | } | 
| richardparker | 7:6cf21b018420 | 329 | |
| richardparker | 7:6cf21b018420 | 330 | // Clear the path. | 
| richardparker | 7:6cf21b018420 | 331 | _path.clear(); | 
| richardparker | 7:6cf21b018420 | 332 | |
| richardparker | 7:6cf21b018420 | 333 | // Clear the data offset. | 
| richardparker | 7:6cf21b018420 | 334 | _dataOffset = 0; | 
| richardparker | 7:6cf21b018420 | 335 | |
| richardparker | 7:6cf21b018420 | 336 | // Set the size to 0. | 
| richardparker | 7:6cf21b018420 | 337 | setWidth(0); | 
| richardparker | 7:6cf21b018420 | 338 | setHeight(0); | 
| richardparker | 7:6cf21b018420 | 339 | } | 
| richardparker | 7:6cf21b018420 | 340 | |
| richardparker | 7:6cf21b018420 | 341 | void EAImage::paint(EALCD& lcd) | 
| richardparker | 7:6cf21b018420 | 342 | { | 
| richardparker | 7:6cf21b018420 | 343 | paint(lcd, 0, 0, width(), height()); | 
| richardparker | 7:6cf21b018420 | 344 | } | 
| richardparker | 7:6cf21b018420 | 345 | |
| richardparker | 7:6cf21b018420 | 346 | void EAImage::paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h) | 
| richardparker | 7:6cf21b018420 | 347 | { | 
| richardparker | 7:6cf21b018420 | 348 | if (isValid() == false) | 
| richardparker | 7:6cf21b018420 | 349 | { | 
| richardparker | 7:6cf21b018420 | 350 | return; | 
| richardparker | 7:6cf21b018420 | 351 | } | 
| richardparker | 7:6cf21b018420 | 352 | |
| richardparker | 7:6cf21b018420 | 353 | // Don't allow draw out of range. | 
| richardparker | 7:6cf21b018420 | 354 | if (x + w > width()) | 
| richardparker | 7:6cf21b018420 | 355 | { | 
| richardparker | 7:6cf21b018420 | 356 | return; | 
| richardparker | 7:6cf21b018420 | 357 | } | 
| richardparker | 7:6cf21b018420 | 358 | |
| richardparker | 7:6cf21b018420 | 359 | if (y + h > height()) | 
| richardparker | 7:6cf21b018420 | 360 | { | 
| richardparker | 7:6cf21b018420 | 361 | return; | 
| richardparker | 7:6cf21b018420 | 362 | } | 
| richardparker | 7:6cf21b018420 | 363 | |
| richardparker | 7:6cf21b018420 | 364 | // Buffer to hold load one line at a time this must be large enough to hold all of the data used | 
| richardparker | 7:6cf21b018420 | 365 | // for a line in the file. Note that the line in the file is padded so that it always ends on a | 
| richardparker | 7:6cf21b018420 | 366 | // 32 bit boundary. | 
| richardparker | 7:6cf21b018420 | 367 | int wordsInRow = _wordsInRow(); | 
| richardparker | 7:6cf21b018420 | 368 | unsigned int buffer[wordsInRow]; | 
| richardparker | 7:6cf21b018420 | 369 | int xD = 0; | 
| richardparker | 7:6cf21b018420 | 370 | int yD = 0; | 
| richardparker | 7:6cf21b018420 | 371 | int wordOffset = 0; | 
| richardparker | 7:6cf21b018420 | 372 | int bitsPerPixel = info().bitsPerPixel; | 
| richardparker | 7:6cf21b018420 | 373 | unsigned short data = 0; | 
| richardparker | 7:6cf21b018420 | 374 | |
| richardparker | 7:6cf21b018420 | 375 | // Try and open the file, skip straight to the data. | 
| richardparker | 7:6cf21b018420 | 376 | FILE* fp = NULL; | 
| richardparker | 7:6cf21b018420 | 377 | fp = fopen(_path.c_str(), "r"); | 
| richardparker | 7:6cf21b018420 | 378 | if (fp == NULL) | 
| richardparker | 7:6cf21b018420 | 379 | { | 
| richardparker | 7:6cf21b018420 | 380 | return; | 
| richardparker | 7:6cf21b018420 | 381 | } | 
| richardparker | 7:6cf21b018420 | 382 | |
| richardparker | 7:6cf21b018420 | 383 | // Skip the header and size. | 
| richardparker | 7:6cf21b018420 | 384 | _fseek(fp, _dataOffset, SEEK_SET); | 
| richardparker | 7:6cf21b018420 | 385 | |
| richardparker | 7:6cf21b018420 | 386 | // Prepare the lcd for drawing. | 
| richardparker | 7:6cf21b018420 | 387 | lcd._window(this->x(), this->y(), w, h); | 
| richardparker | 7:6cf21b018420 | 388 | lcd._moveTo(this->x(), this->y()); | 
| richardparker | 7:6cf21b018420 | 389 | |
| richardparker | 7:6cf21b018420 | 390 | // Move in the file to the first pixel in the window. | 
| richardparker | 7:6cf21b018420 | 391 | _fseek(fp, (y*wordsInRow*4)+(_wordForX(x)*4), SEEK_CUR); | 
| richardparker | 7:6cf21b018420 | 392 | |
| richardparker | 7:6cf21b018420 | 393 | // Now read the data. | 
| richardparker | 7:6cf21b018420 | 394 | while (!_feof(fp)) | 
| richardparker | 7:6cf21b018420 | 395 | { | 
| richardparker | 7:6cf21b018420 | 396 | wordOffset = _xWordOffset(x); | 
| richardparker | 7:6cf21b018420 | 397 | |
| richardparker | 7:6cf21b018420 | 398 | int sizeRead = _fread(&buffer, 4, wordsInRow, fp); | 
| richardparker | 7:6cf21b018420 | 399 | |
| richardparker | 7:6cf21b018420 | 400 | for (int i = 0; i < sizeRead; i++) | 
| richardparker | 7:6cf21b018420 | 401 | { | 
| richardparker | 7:6cf21b018420 | 402 | while (wordOffset < 32) | 
| richardparker | 7:6cf21b018420 | 403 | { | 
| richardparker | 7:6cf21b018420 | 404 | // Convert the colour to a 16 bit colour value that can be written directly to the screen. | 
| richardparker | 7:6cf21b018420 | 405 | data = _getColourAtOffset(buffer[i], wordOffset); | 
| richardparker | 7:6cf21b018420 | 406 | |
| richardparker | 7:6cf21b018420 | 407 | if (isMask() == true) | 
| richardparker | 7:6cf21b018420 | 408 | { | 
| richardparker | 7:6cf21b018420 | 409 | // When a mask the 0x0000 value is transparent anything else is drawn with the pen color. | 
| richardparker | 7:6cf21b018420 | 410 | if (data == 0x0000) | 
| richardparker | 7:6cf21b018420 | 411 | { | 
| richardparker | 7:6cf21b018420 | 412 | lcd.noop(); | 
| richardparker | 7:6cf21b018420 | 413 | } else { | 
| richardparker | 7:6cf21b018420 | 414 | lcd._writeToDisplay(lcd.pen().color().rawValue()); | 
| richardparker | 7:6cf21b018420 | 415 | } | 
| richardparker | 7:6cf21b018420 | 416 | } else { | 
| richardparker | 7:6cf21b018420 | 417 | // Not a mask so just use colour that have loaded. | 
| richardparker | 7:6cf21b018420 | 418 | lcd._writeToDisplay(data); | 
| richardparker | 7:6cf21b018420 | 419 | } | 
| richardparker | 7:6cf21b018420 | 420 | |
| richardparker | 7:6cf21b018420 | 421 | // Got to next pixel in the word. | 
| richardparker | 7:6cf21b018420 | 422 | wordOffset += bitsPerPixel; | 
| richardparker | 7:6cf21b018420 | 423 | |
| richardparker | 7:6cf21b018420 | 424 | // Keep count of current x value. | 
| richardparker | 7:6cf21b018420 | 425 | xD++; | 
| richardparker | 7:6cf21b018420 | 426 | if (xD == w) | 
| richardparker | 7:6cf21b018420 | 427 | { | 
| richardparker | 7:6cf21b018420 | 428 | break; | 
| richardparker | 7:6cf21b018420 | 429 | } | 
| richardparker | 7:6cf21b018420 | 430 | } | 
| richardparker | 7:6cf21b018420 | 431 | wordOffset = 0; | 
| richardparker | 7:6cf21b018420 | 432 | |
| richardparker | 7:6cf21b018420 | 433 | // When written all required pixels exit. | 
| richardparker | 7:6cf21b018420 | 434 | if (xD == w) | 
| richardparker | 7:6cf21b018420 | 435 | { | 
| richardparker | 7:6cf21b018420 | 436 | xD = 0; | 
| richardparker | 7:6cf21b018420 | 437 | break; | 
| richardparker | 7:6cf21b018420 | 438 | } | 
| richardparker | 7:6cf21b018420 | 439 | } | 
| richardparker | 7:6cf21b018420 | 440 | |
| richardparker | 7:6cf21b018420 | 441 | // Keep count of curernt y value. | 
| richardparker | 7:6cf21b018420 | 442 | yD++; | 
| richardparker | 7:6cf21b018420 | 443 | if (yD == h) | 
| richardparker | 7:6cf21b018420 | 444 | { | 
| richardparker | 7:6cf21b018420 | 445 | break; | 
| richardparker | 7:6cf21b018420 | 446 | } | 
| richardparker | 7:6cf21b018420 | 447 | } | 
| richardparker | 7:6cf21b018420 | 448 | |
| richardparker | 7:6cf21b018420 | 449 | // Close the file and release handle. | 
| richardparker | 7:6cf21b018420 | 450 | fclose(fp); | 
| richardparker | 7:6cf21b018420 | 451 | } | 
| richardparker | 7:6cf21b018420 | 452 | |
| richardparker | 7:6cf21b018420 | 453 |