Richard Parker / EALCD
Committer:
richardparker
Date:
Thu May 06 23:32:14 2010 +0000
Revision:
6:4fe6f365cbeb
Parent:
3:24fbf4dbd7e5
Added caching for the fonts which seems to give ~20x improvement in rendering at the sacrifice of RAM.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
richardparker 0:839ecbf5cb2a 1 // Copyright 2010 Richard Parker
richardparker 0:839ecbf5cb2a 2
richardparker 0:839ecbf5cb2a 3 #include "mbed.h"
richardparker 0:839ecbf5cb2a 4
richardparker 0:839ecbf5cb2a 5 #include "EAImage.h"
richardparker 0:839ecbf5cb2a 6
richardparker 0:839ecbf5cb2a 7 #include "../graphics/EAPen.h"
richardparker 0:839ecbf5cb2a 8 #include "../graphics/EAColor.h"
richardparker 0:839ecbf5cb2a 9 #include "../screen/EALCD.h"
richardparker 0:839ecbf5cb2a 10
richardparker 0:839ecbf5cb2a 11 EAImage::EAImage()
richardparker 0:839ecbf5cb2a 12 : _path(NULL),
richardparker 1:f04bcaea1d60 13 _palette(NULL),
richardparker 1:f04bcaea1d60 14 _dataOffset(0),
richardparker 6:4fe6f365cbeb 15 _mask(false),
richardparker 6:4fe6f365cbeb 16 _cached(false),
richardparker 6:4fe6f365cbeb 17 _cache(NULL),
richardparker 6:4fe6f365cbeb 18 _size(0L),
richardparker 6:4fe6f365cbeb 19 _pos(0L)
richardparker 0:839ecbf5cb2a 20 {
richardparker 1:f04bcaea1d60 21 // Start from known state.
richardparker 1:f04bcaea1d60 22 unload();
richardparker 0:839ecbf5cb2a 23 }
richardparker 0:839ecbf5cb2a 24
richardparker 0:839ecbf5cb2a 25 EAImage::~EAImage()
richardparker 0:839ecbf5cb2a 26 {
richardparker 6:4fe6f365cbeb 27 unload();
richardparker 6:4fe6f365cbeb 28 }
richardparker 6:4fe6f365cbeb 29
richardparker 6:4fe6f365cbeb 30 int EAImage::_feof(FILE* stream)
richardparker 6:4fe6f365cbeb 31 {
richardparker 6:4fe6f365cbeb 32 if (isCached() == true)
richardparker 3:24fbf4dbd7e5 33 {
richardparker 6:4fe6f365cbeb 34 return (_pos < _size) ? 0 : 1;
richardparker 6:4fe6f365cbeb 35 } else {
richardparker 6:4fe6f365cbeb 36 return feof(stream);
richardparker 6:4fe6f365cbeb 37 }
richardparker 6:4fe6f365cbeb 38 }
richardparker 6:4fe6f365cbeb 39
richardparker 6:4fe6f365cbeb 40
richardparker 6:4fe6f365cbeb 41 int EAImage::_fseek(FILE* stream, long int offset, int origin)
richardparker 6:4fe6f365cbeb 42 {
richardparker 6:4fe6f365cbeb 43 if (isCached() == true)
richardparker 6:4fe6f365cbeb 44 {
richardparker 6:4fe6f365cbeb 45 switch (origin)
richardparker 6:4fe6f365cbeb 46 {
richardparker 6:4fe6f365cbeb 47 default:
richardparker 6:4fe6f365cbeb 48 case SEEK_SET:
richardparker 6:4fe6f365cbeb 49 _pos = offset;
richardparker 6:4fe6f365cbeb 50 break;
richardparker 6:4fe6f365cbeb 51 case SEEK_CUR:
richardparker 6:4fe6f365cbeb 52 _pos = _pos + offset;
richardparker 6:4fe6f365cbeb 53 break;
richardparker 6:4fe6f365cbeb 54 case SEEK_END:
richardparker 6:4fe6f365cbeb 55 _pos = (_size-1) + offset;
richardparker 6:4fe6f365cbeb 56 break;
richardparker 6:4fe6f365cbeb 57 }
richardparker 6:4fe6f365cbeb 58
richardparker 6:4fe6f365cbeb 59 // Make sure position within range.
richardparker 6:4fe6f365cbeb 60 if (_pos < 0)
richardparker 6:4fe6f365cbeb 61 {
richardparker 6:4fe6f365cbeb 62 _pos = 0;
richardparker 6:4fe6f365cbeb 63 return 0;
richardparker 6:4fe6f365cbeb 64 }
richardparker 6:4fe6f365cbeb 65
richardparker 6:4fe6f365cbeb 66 if (_pos > (_size-1))
richardparker 6:4fe6f365cbeb 67 {
richardparker 6:4fe6f365cbeb 68 _pos = (_size-1);
richardparker 6:4fe6f365cbeb 69 return 0;
richardparker 6:4fe6f365cbeb 70 }
richardparker 6:4fe6f365cbeb 71
richardparker 6:4fe6f365cbeb 72 // Error.
richardparker 6:4fe6f365cbeb 73 return 1;
richardparker 6:4fe6f365cbeb 74 } else {
richardparker 6:4fe6f365cbeb 75 return fseek(stream, offset, origin);
richardparker 6:4fe6f365cbeb 76 }
richardparker 6:4fe6f365cbeb 77 }
richardparker 6:4fe6f365cbeb 78
richardparker 6:4fe6f365cbeb 79 size_t EAImage::_fread(void* ptr, size_t size, size_t count, FILE* stream)
richardparker 6:4fe6f365cbeb 80 {
richardparker 6:4fe6f365cbeb 81 if (isCached() == true)
richardparker 6:4fe6f365cbeb 82 {
richardparker 6:4fe6f365cbeb 83 // Truncate size to fit array if needed.
richardparker 6:4fe6f365cbeb 84 if (_pos + (count*size) > _size)
richardparker 6:4fe6f365cbeb 85 {
richardparker 6:4fe6f365cbeb 86 count = (_size - _pos)/size;
richardparker 6:4fe6f365cbeb 87 }
richardparker 6:4fe6f365cbeb 88
richardparker 6:4fe6f365cbeb 89 if (count <= 0)
richardparker 6:4fe6f365cbeb 90 {
richardparker 6:4fe6f365cbeb 91 return 0;
richardparker 6:4fe6f365cbeb 92 }
richardparker 6:4fe6f365cbeb 93
richardparker 6:4fe6f365cbeb 94 // Now copy out of cache to array.
richardparker 6:4fe6f365cbeb 95 memcpy(ptr, &_cache[_pos], count*size);
richardparker 6:4fe6f365cbeb 96
richardparker 6:4fe6f365cbeb 97 // Update the file position.
richardparker 6:4fe6f365cbeb 98 _pos = _pos + (count*size);
richardparker 6:4fe6f365cbeb 99
richardparker 6:4fe6f365cbeb 100 // Return the number of bytes read.
richardparker 6:4fe6f365cbeb 101 return count;
richardparker 6:4fe6f365cbeb 102 } else {
richardparker 6:4fe6f365cbeb 103 return fread(ptr, size, count, stream);
richardparker 6:4fe6f365cbeb 104 }
richardparker 6:4fe6f365cbeb 105 }
richardparker 6:4fe6f365cbeb 106
richardparker 6:4fe6f365cbeb 107 bool EAImage::_loadCache(FILE* fp)
richardparker 6:4fe6f365cbeb 108 {
richardparker 6:4fe6f365cbeb 109 // Can't do anything with a null pointer.
richardparker 6:4fe6f365cbeb 110 if (fp == NULL)
richardparker 6:4fe6f365cbeb 111 {
richardparker 6:4fe6f365cbeb 112 return false;
richardparker 3:24fbf4dbd7e5 113 }
richardparker 3:24fbf4dbd7e5 114
richardparker 6:4fe6f365cbeb 115 // Clear any previously loaded cache.
richardparker 6:4fe6f365cbeb 116 if (_cache != NULL)
richardparker 6:4fe6f365cbeb 117 {
richardparker 6:4fe6f365cbeb 118 delete[] _cache;
richardparker 6:4fe6f365cbeb 119 _cache = NULL;
richardparker 6:4fe6f365cbeb 120 }
richardparker 6:4fe6f365cbeb 121 _size = 0L;
richardparker 6:4fe6f365cbeb 122 _pos = 0L;
richardparker 6:4fe6f365cbeb 123
richardparker 6:4fe6f365cbeb 124 if (isCached() == false)
richardparker 6:4fe6f365cbeb 125 {
richardparker 6:4fe6f365cbeb 126 return true;
richardparker 6:4fe6f365cbeb 127 }
richardparker 6:4fe6f365cbeb 128
richardparker 6:4fe6f365cbeb 129 // Get the size of the file.
richardparker 6:4fe6f365cbeb 130 fseek(fp, 0, SEEK_END);
richardparker 6:4fe6f365cbeb 131 long int size = ftell(fp);
richardparker 6:4fe6f365cbeb 132
richardparker 6:4fe6f365cbeb 133 if (size == -1)
richardparker 6:4fe6f365cbeb 134 {
richardparker 6:4fe6f365cbeb 135 // Something went wronmg with the command.
richardparker 6:4fe6f365cbeb 136 return false;
richardparker 6:4fe6f365cbeb 137 }
richardparker 6:4fe6f365cbeb 138
richardparker 6:4fe6f365cbeb 139 // Now create a cache large enough to hold all of the image data.
richardparker 6:4fe6f365cbeb 140 _cache = new char[size];
richardparker 6:4fe6f365cbeb 141
richardparker 6:4fe6f365cbeb 142 if (_cache == NULL)
richardparker 3:24fbf4dbd7e5 143 {
richardparker 6:4fe6f365cbeb 144 // Unable to allocate enough space for the font.
richardparker 6:4fe6f365cbeb 145 return false;
richardparker 3:24fbf4dbd7e5 146 }
richardparker 6:4fe6f365cbeb 147
richardparker 6:4fe6f365cbeb 148 // Now rewind file pointer back to the beginning.
richardparker 6:4fe6f365cbeb 149 rewind(fp);
richardparker 6:4fe6f365cbeb 150
richardparker 6:4fe6f365cbeb 151 const unsigned int CHUNK_SIZE = 100;
richardparker 6:4fe6f365cbeb 152 long int sizeRead = 0;
richardparker 6:4fe6f365cbeb 153 long int totalSizeRead = 0;
richardparker 6:4fe6f365cbeb 154
richardparker 6:4fe6f365cbeb 155 // Load in small chunks at a time.
richardparker 6:4fe6f365cbeb 156 while (!feof(fp))
richardparker 6:4fe6f365cbeb 157 {
richardparker 6:4fe6f365cbeb 158 // Read into the buffer.
richardparker 6:4fe6f365cbeb 159 sizeRead = fread(&_cache[totalSizeRead], 1, CHUNK_SIZE, fp);
richardparker 6:4fe6f365cbeb 160
richardparker 6:4fe6f365cbeb 161 // Update total count of amount of data loaded.
richardparker 6:4fe6f365cbeb 162 totalSizeRead += sizeRead;
richardparker 6:4fe6f365cbeb 163 }
richardparker 6:4fe6f365cbeb 164
richardparker 6:4fe6f365cbeb 165 // Check that the whole file loaded.
richardparker 6:4fe6f365cbeb 166 if (totalSizeRead != size)
richardparker 6:4fe6f365cbeb 167 {
richardparker 6:4fe6f365cbeb 168 // Clear cache.
richardparker 6:4fe6f365cbeb 169 delete[] _cache;
richardparker 6:4fe6f365cbeb 170 _cache = NULL;
richardparker 6:4fe6f365cbeb 171
richardparker 6:4fe6f365cbeb 172 // Return error.
richardparker 6:4fe6f365cbeb 173 return false;
richardparker 6:4fe6f365cbeb 174 }
richardparker 6:4fe6f365cbeb 175
richardparker 6:4fe6f365cbeb 176 // Record size and position.
richardparker 6:4fe6f365cbeb 177 _size = size;
richardparker 6:4fe6f365cbeb 178 _pos = 0L;
richardparker 6:4fe6f365cbeb 179
richardparker 6:4fe6f365cbeb 180 return true;
richardparker 0:839ecbf5cb2a 181 }
richardparker 0:839ecbf5cb2a 182
richardparker 1:f04bcaea1d60 183 bool EAImage::_loadPalette(FILE* fp)
richardparker 1:f04bcaea1d60 184 {
richardparker 6:4fe6f365cbeb 185 // Can't do anything with a null pointer unless cached.
richardparker 6:4fe6f365cbeb 186 if ((fp == NULL) && (isCached() == false))
richardparker 1:f04bcaea1d60 187 {
richardparker 1:f04bcaea1d60 188 return false;
richardparker 1:f04bcaea1d60 189 }
richardparker 1:f04bcaea1d60 190
richardparker 1:f04bcaea1d60 191 // Clear any previously loaded palette.
richardparker 1:f04bcaea1d60 192 if (_palette != NULL)
richardparker 1:f04bcaea1d60 193 {
richardparker 1:f04bcaea1d60 194 delete[] _palette;
richardparker 1:f04bcaea1d60 195 _palette = NULL;
richardparker 1:f04bcaea1d60 196 }
richardparker 1:f04bcaea1d60 197
richardparker 1:f04bcaea1d60 198 // If the number of bits is not less than 16 then return after having cleared the
richardparker 1:f04bcaea1d60 199 // palette. There is no palette required.
richardparker 1:f04bcaea1d60 200 if (info().bitsPerPixel >= 16)
richardparker 1:f04bcaea1d60 201 {
richardparker 1:f04bcaea1d60 202 return true;
richardparker 1:f04bcaea1d60 203 }
richardparker 1:f04bcaea1d60 204
richardparker 1:f04bcaea1d60 205 // First create a palette of the required size.
richardparker 1:f04bcaea1d60 206 unsigned int noColors = info().noColors;
richardparker 1:f04bcaea1d60 207
richardparker 1:f04bcaea1d60 208 // When 0 the number of colors is equal to 2^n where n is the bits per pixel.
richardparker 1:f04bcaea1d60 209 if (noColors == 0)
richardparker 1:f04bcaea1d60 210 {
richardparker 1:f04bcaea1d60 211 noColors = pow((double)2, info().bitsPerPixel);
richardparker 1:f04bcaea1d60 212 }
richardparker 1:f04bcaea1d60 213
richardparker 1:f04bcaea1d60 214 // Create the palette and assign the memory.
richardparker 1:f04bcaea1d60 215 _palette = new EAColor[noColors];
richardparker 1:f04bcaea1d60 216
richardparker 1:f04bcaea1d60 217 // Now parse the palette. First seek to the start of the palette. This must be the
richardparker 1:f04bcaea1d60 218 // start of the bitmap data minus the number of colour entries multiplied by 4 (the
richardparker 1:f04bcaea1d60 219 // colours are stored as 4 byte long entries, the last byte can be ignored).
richardparker 1:f04bcaea1d60 220 unsigned int offset = _dataOffset - (noColors*4);
richardparker 1:f04bcaea1d60 221
richardparker 1:f04bcaea1d60 222 // Seek to the start of the table.
richardparker 6:4fe6f365cbeb 223 _fseek(fp, offset, SEEK_SET);
richardparker 1:f04bcaea1d60 224 unsigned char buffer[4];
richardparker 1:f04bcaea1d60 225
richardparker 1:f04bcaea1d60 226 // Iterate through the table filling the palette as needed.
richardparker 1:f04bcaea1d60 227 for (int i = 0; i < noColors; i++)
richardparker 1:f04bcaea1d60 228 {
richardparker 6:4fe6f365cbeb 229 int sizeRead = _fread(&buffer, 4, 1, fp);
richardparker 1:f04bcaea1d60 230
richardparker 1:f04bcaea1d60 231 if (sizeRead == 1)
richardparker 1:f04bcaea1d60 232 {
richardparker 1:f04bcaea1d60 233 _palette[i].setRgb(buffer[2], buffer[1], buffer[0]);
richardparker 1:f04bcaea1d60 234 }
richardparker 1:f04bcaea1d60 235 }
richardparker 1:f04bcaea1d60 236
richardparker 1:f04bcaea1d60 237 return true;
richardparker 1:f04bcaea1d60 238 }
richardparker 1:f04bcaea1d60 239
richardparker 0:839ecbf5cb2a 240 bool EAImage::_loadHeader(const char* path)
richardparker 0:839ecbf5cb2a 241 {
richardparker 0:839ecbf5cb2a 242 if (path == NULL)
richardparker 0:839ecbf5cb2a 243 {
richardparker 0:839ecbf5cb2a 244 // Invalid path passed in.
richardparker 0:839ecbf5cb2a 245 return false;
richardparker 0:839ecbf5cb2a 246 }
richardparker 0:839ecbf5cb2a 247
richardparker 0:839ecbf5cb2a 248 // Try and open the file, check type and load width and height.
richardparker 0:839ecbf5cb2a 249 FILE* fp = fopen(path, "r");
richardparker 0:839ecbf5cb2a 250 if (fp == NULL)
richardparker 0:839ecbf5cb2a 251 {
richardparker 0:839ecbf5cb2a 252 return false;
richardparker 0:839ecbf5cb2a 253 }
richardparker 0:839ecbf5cb2a 254
richardparker 0:839ecbf5cb2a 255 unsigned int bufint = 0;
richardparker 0:839ecbf5cb2a 256 unsigned int offset = 0;
richardparker 0:839ecbf5cb2a 257
richardparker 0:839ecbf5cb2a 258 // Read the magic numbers at start.
richardparker 0:839ecbf5cb2a 259 fread(&bufint, 1, 2, fp);
richardparker 0:839ecbf5cb2a 260 if (bufint != 0x4d42)
richardparker 0:839ecbf5cb2a 261 {
richardparker 0:839ecbf5cb2a 262 // Clean up file handle.
richardparker 0:839ecbf5cb2a 263 fclose(fp);
richardparker 6:4fe6f365cbeb 264 unload();
richardparker 0:839ecbf5cb2a 265
richardparker 0:839ecbf5cb2a 266 // Header incorrect.
richardparker 0:839ecbf5cb2a 267 return false;
richardparker 0:839ecbf5cb2a 268 }
richardparker 0:839ecbf5cb2a 269
richardparker 0:839ecbf5cb2a 270 // Now read the bmp file size.
richardparker 0:839ecbf5cb2a 271 fread(&bufint, 1, 4, fp);
richardparker 0:839ecbf5cb2a 272
richardparker 0:839ecbf5cb2a 273 // Now read the two creator values and throw away.
richardparker 0:839ecbf5cb2a 274 fread(&bufint, 1, 2, fp);
richardparker 0:839ecbf5cb2a 275 fread(&bufint, 1, 2, fp);
richardparker 0:839ecbf5cb2a 276
richardparker 0:839ecbf5cb2a 277 // Now read the offset for the bitmap data.
richardparker 0:839ecbf5cb2a 278 fread(&bufint, 1, 4, fp);
richardparker 0:839ecbf5cb2a 279 offset = bufint;
richardparker 0:839ecbf5cb2a 280
richardparker 0:839ecbf5cb2a 281 // Retrieve the header.
richardparker 1:f04bcaea1d60 282 fread(&_header, sizeof(EABMPHeader), 1, fp);
richardparker 0:839ecbf5cb2a 283
richardparker 1:f04bcaea1d60 284 // Make sure the compression type is a value that can be dealt with.
richardparker 1:f04bcaea1d60 285 if ((info().compressionType != 3) && (info().compressionType != 0))
richardparker 1:f04bcaea1d60 286 {
richardparker 0:839ecbf5cb2a 287 // Clean up file handle.
richardparker 6:4fe6f365cbeb 288 fclose(fp);
richardparker 6:4fe6f365cbeb 289 unload();
richardparker 0:839ecbf5cb2a 290
richardparker 0:839ecbf5cb2a 291 // Header incorrect.
richardparker 0:839ecbf5cb2a 292 return false;
richardparker 0:839ecbf5cb2a 293 }
richardparker 0:839ecbf5cb2a 294
richardparker 0:839ecbf5cb2a 295 // Set the values for later.
richardparker 0:839ecbf5cb2a 296 _dataOffset = offset;
richardparker 1:f04bcaea1d60 297 setWidth(info().width);
richardparker 1:f04bcaea1d60 298 setHeight(info().height);
richardparker 6:4fe6f365cbeb 299
richardparker 6:4fe6f365cbeb 300 // If the image is to be cached then load the cache.
richardparker 6:4fe6f365cbeb 301 if (_loadCache(fp) == false)
richardparker 6:4fe6f365cbeb 302 {
richardparker 6:4fe6f365cbeb 303 // Clean up file handle.
richardparker 6:4fe6f365cbeb 304 fclose(fp);
richardparker 6:4fe6f365cbeb 305 unload();
richardparker 6:4fe6f365cbeb 306
richardparker 6:4fe6f365cbeb 307 // Header incorrect.
richardparker 6:4fe6f365cbeb 308 return false;
richardparker 6:4fe6f365cbeb 309 }
richardparker 1:f04bcaea1d60 310
richardparker 0:839ecbf5cb2a 311 // Close the file.
richardparker 0:839ecbf5cb2a 312 fclose(fp);
richardparker 0:839ecbf5cb2a 313
richardparker 0:839ecbf5cb2a 314 return true;
richardparker 0:839ecbf5cb2a 315 }
richardparker 0:839ecbf5cb2a 316
richardparker 1:f04bcaea1d60 317 int EAImage::_wordsInRow()
richardparker 1:f04bcaea1d60 318 {
richardparker 1:f04bcaea1d60 319 // If there were no padding to 32 bit boundaries this would be the number of bits per row
richardparker 1:f04bcaea1d60 320 // in the file.
richardparker 1:f04bcaea1d60 321 int bitsPerWidth = width() * info().bitsPerPixel;
richardparker 1:f04bcaea1d60 322
richardparker 1:f04bcaea1d60 323 // This is the row size with padding on the end.
richardparker 1:f04bcaea1d60 324 int remainder = (bitsPerWidth % 32);
richardparker 1:f04bcaea1d60 325 int bitsPerRow = (remainder == 0) ? bitsPerWidth : bitsPerWidth + (32 - remainder);
richardparker 1:f04bcaea1d60 326
richardparker 1:f04bcaea1d60 327 // Return the size in number of words.
richardparker 1:f04bcaea1d60 328 return (bitsPerRow / 32);
richardparker 1:f04bcaea1d60 329 }
richardparker 1:f04bcaea1d60 330
richardparker 1:f04bcaea1d60 331 int EAImage::_wordForX(unsigned int x)
richardparker 1:f04bcaea1d60 332 {
richardparker 1:f04bcaea1d60 333 int bitForX = x * info().bitsPerPixel;
richardparker 1:f04bcaea1d60 334
richardparker 1:f04bcaea1d60 335 return (bitForX / 32);
richardparker 1:f04bcaea1d60 336 }
richardparker 1:f04bcaea1d60 337
richardparker 1:f04bcaea1d60 338 int EAImage::_xWordOffset(unsigned int x)
richardparker 1:f04bcaea1d60 339 {
richardparker 1:f04bcaea1d60 340 int bitForX = x * info().bitsPerPixel;
richardparker 1:f04bcaea1d60 341
richardparker 1:f04bcaea1d60 342 return (bitForX % 32);
richardparker 1:f04bcaea1d60 343 }
richardparker 1:f04bcaea1d60 344
richardparker 1:f04bcaea1d60 345 unsigned short EAImage::_getColourAtOffset(unsigned int word, int offset)
richardparker 1:f04bcaea1d60 346 {
richardparker 1:f04bcaea1d60 347 // Sort bytes for endianness.
richardparker 1:f04bcaea1d60 348 unsigned char* cptr;
richardparker 1:f04bcaea1d60 349 unsigned short result = 0x0000;
richardparker 1:f04bcaea1d60 350
richardparker 1:f04bcaea1d60 351 // Now need to decide how to cast the value to a colour.
richardparker 1:f04bcaea1d60 352 switch (info().bitsPerPixel)
richardparker 1:f04bcaea1d60 353 {
richardparker 1:f04bcaea1d60 354 // Swap the bytes around.
richardparker 1:f04bcaea1d60 355 case 32:
richardparker 1:f04bcaea1d60 356 case 4:
richardparker 1:f04bcaea1d60 357 case 8:
richardparker 1:f04bcaea1d60 358 case 1:
richardparker 1:f04bcaea1d60 359 unsigned char tmp;
richardparker 1:f04bcaea1d60 360 cptr = (unsigned char*)&word;
richardparker 1:f04bcaea1d60 361 tmp = cptr[0];
richardparker 1:f04bcaea1d60 362 cptr[0] = cptr[3];
richardparker 1:f04bcaea1d60 363 cptr[3] = tmp;
richardparker 1:f04bcaea1d60 364 tmp = cptr[1];
richardparker 1:f04bcaea1d60 365 cptr[1] = cptr[2];
richardparker 1:f04bcaea1d60 366 cptr[2] = tmp;
richardparker 1:f04bcaea1d60 367 break;
richardparker 1:f04bcaea1d60 368
richardparker 1:f04bcaea1d60 369 default:
richardparker 1:f04bcaea1d60 370 // Swap the 16bits around.
richardparker 1:f04bcaea1d60 371 case 16:
richardparker 1:f04bcaea1d60 372 unsigned char tmpa;
richardparker 1:f04bcaea1d60 373 unsigned char tmpb;
richardparker 1:f04bcaea1d60 374 cptr = (unsigned char*)&word;
richardparker 1:f04bcaea1d60 375 tmpa = cptr[1];
richardparker 1:f04bcaea1d60 376 tmpb = cptr[0];
richardparker 1:f04bcaea1d60 377 cptr[1] = cptr[3];
richardparker 1:f04bcaea1d60 378 cptr[0] = cptr[2];
richardparker 1:f04bcaea1d60 379 cptr[3] = tmpa;
richardparker 1:f04bcaea1d60 380 cptr[2] = tmpb;
richardparker 1:f04bcaea1d60 381 break;
richardparker 1:f04bcaea1d60 382 }
richardparker 1:f04bcaea1d60 383
richardparker 1:f04bcaea1d60 384 // First shift off the pixels above.
richardparker 1:f04bcaea1d60 385 word = word << offset;
richardparker 1:f04bcaea1d60 386
richardparker 1:f04bcaea1d60 387 // Now shift down so that pixel is in lsb.
richardparker 1:f04bcaea1d60 388 word = word >> (32 - info().bitsPerPixel);
richardparker 1:f04bcaea1d60 389
richardparker 1:f04bcaea1d60 390 EAColor c;
richardparker 1:f04bcaea1d60 391
richardparker 1:f04bcaea1d60 392 // Now need to decide how to cast the value to a colour.
richardparker 1:f04bcaea1d60 393 switch (info().bitsPerPixel)
richardparker 1:f04bcaea1d60 394 {
richardparker 1:f04bcaea1d60 395 case 8:
richardparker 1:f04bcaea1d60 396 case 4:
richardparker 1:f04bcaea1d60 397 case 1:
richardparker 1:f04bcaea1d60 398 if (_palette != NULL)
richardparker 1:f04bcaea1d60 399 {
richardparker 1:f04bcaea1d60 400 result = _palette[word].rawValue();
richardparker 1:f04bcaea1d60 401 } else {
richardparker 1:f04bcaea1d60 402 result = 0x0000;
richardparker 1:f04bcaea1d60 403 }
richardparker 1:f04bcaea1d60 404 break;
richardparker 1:f04bcaea1d60 405
richardparker 1:f04bcaea1d60 406 // By default just cast to unsigned short and return.
richardparker 1:f04bcaea1d60 407 default:
richardparker 1:f04bcaea1d60 408 case 16:
richardparker 1:f04bcaea1d60 409 result = (unsigned short)(word);
richardparker 1:f04bcaea1d60 410 break;
richardparker 1:f04bcaea1d60 411
richardparker 1:f04bcaea1d60 412 case 24:
richardparker 1:f04bcaea1d60 413 case 32:
richardparker 1:f04bcaea1d60 414 unsigned char b = ((word << 0) >> 24);
richardparker 1:f04bcaea1d60 415 unsigned char g = ((word << 8) >> 24);
richardparker 1:f04bcaea1d60 416 unsigned char r = ((word << 16) >> 24);
richardparker 1:f04bcaea1d60 417
richardparker 1:f04bcaea1d60 418 c.setRgb(r, g, b);
richardparker 1:f04bcaea1d60 419 result = c.rawValue();
richardparker 1:f04bcaea1d60 420 break;
richardparker 1:f04bcaea1d60 421 }
richardparker 1:f04bcaea1d60 422
richardparker 1:f04bcaea1d60 423 return result;
richardparker 1:f04bcaea1d60 424 }
richardparker 1:f04bcaea1d60 425
richardparker 0:839ecbf5cb2a 426 bool EAImage::load(const char* path)
richardparker 0:839ecbf5cb2a 427 {
richardparker 0:839ecbf5cb2a 428 if (path == NULL)
richardparker 0:839ecbf5cb2a 429 {
richardparker 1:f04bcaea1d60 430 // Reset all of the state.
richardparker 1:f04bcaea1d60 431 unload();
richardparker 1:f04bcaea1d60 432
richardparker 0:839ecbf5cb2a 433 // Invalid path passed in.
richardparker 0:839ecbf5cb2a 434 return false;
richardparker 0:839ecbf5cb2a 435 }
richardparker 0:839ecbf5cb2a 436
richardparker 0:839ecbf5cb2a 437 if (_loadHeader(path) == false)
richardparker 0:839ecbf5cb2a 438 {
richardparker 1:f04bcaea1d60 439 // Reset all of the state.
richardparker 1:f04bcaea1d60 440 unload();
richardparker 1:f04bcaea1d60 441
richardparker 0:839ecbf5cb2a 442 return false;
richardparker 0:839ecbf5cb2a 443 }
richardparker 0:839ecbf5cb2a 444
richardparker 0:839ecbf5cb2a 445 int pathLen = strlen(path);
richardparker 0:839ecbf5cb2a 446
richardparker 0:839ecbf5cb2a 447 // If already loaded an image then clear to load the new one.
richardparker 0:839ecbf5cb2a 448 if (_path != NULL)
richardparker 0:839ecbf5cb2a 449 {
richardparker 0:839ecbf5cb2a 450 delete[] _path;
richardparker 0:839ecbf5cb2a 451 _path = NULL;
richardparker 0:839ecbf5cb2a 452 }
richardparker 0:839ecbf5cb2a 453
richardparker 0:839ecbf5cb2a 454 // Now allocate enough space to hold path. Note +1 for null character.
richardparker 0:839ecbf5cb2a 455 _path = new char[pathLen+1];
richardparker 0:839ecbf5cb2a 456
richardparker 0:839ecbf5cb2a 457 // Now copy over passed in path to path variable.
richardparker 0:839ecbf5cb2a 458 strcpy(_path, path);
richardparker 0:839ecbf5cb2a 459
richardparker 0:839ecbf5cb2a 460 // Image loaded successfully.
richardparker 0:839ecbf5cb2a 461 return true;
richardparker 0:839ecbf5cb2a 462 }
richardparker 0:839ecbf5cb2a 463
richardparker 1:f04bcaea1d60 464 void EAImage::unload()
richardparker 1:f04bcaea1d60 465 {
richardparker 1:f04bcaea1d60 466 // Empty the header struct.
richardparker 1:f04bcaea1d60 467 _header.headerSize = 0;
richardparker 1:f04bcaea1d60 468 _header.width = 0;
richardparker 1:f04bcaea1d60 469 _header.height = 0;
richardparker 1:f04bcaea1d60 470 _header.noColorPlanes = 0;
richardparker 1:f04bcaea1d60 471 _header.bitsPerPixel = 0;
richardparker 1:f04bcaea1d60 472 _header.compressionType = 0;
richardparker 1:f04bcaea1d60 473 _header.bmpSize = 0;
richardparker 1:f04bcaea1d60 474 _header.horizontalRes = 0;
richardparker 1:f04bcaea1d60 475 _header.verticalRes = 0;
richardparker 1:f04bcaea1d60 476 _header.noColors = 0;
richardparker 1:f04bcaea1d60 477 _header.noImportantColors = 0;
richardparker 1:f04bcaea1d60 478
richardparker 1:f04bcaea1d60 479 // Clear the path.
richardparker 1:f04bcaea1d60 480 if (_path != NULL)
richardparker 1:f04bcaea1d60 481 {
richardparker 1:f04bcaea1d60 482 delete[] _path;
richardparker 1:f04bcaea1d60 483 _path = NULL;
richardparker 1:f04bcaea1d60 484 }
richardparker 1:f04bcaea1d60 485
richardparker 1:f04bcaea1d60 486 // Clear the palette.
richardparker 1:f04bcaea1d60 487 if (_palette != NULL)
richardparker 1:f04bcaea1d60 488 {
richardparker 1:f04bcaea1d60 489 delete[] _palette;
richardparker 1:f04bcaea1d60 490 _palette = NULL;
richardparker 1:f04bcaea1d60 491 }
richardparker 1:f04bcaea1d60 492
richardparker 1:f04bcaea1d60 493 // Clear the data offset.
richardparker 1:f04bcaea1d60 494 _dataOffset = 0;
richardparker 1:f04bcaea1d60 495
richardparker 1:f04bcaea1d60 496 // Set the size to 0.
richardparker 1:f04bcaea1d60 497 setWidth(0);
richardparker 1:f04bcaea1d60 498 setHeight(0);
richardparker 1:f04bcaea1d60 499
richardparker 6:4fe6f365cbeb 500 // Empty the cache.
richardparker 6:4fe6f365cbeb 501 if (_cache != NULL)
richardparker 6:4fe6f365cbeb 502 {
richardparker 6:4fe6f365cbeb 503 delete[] _cache;
richardparker 6:4fe6f365cbeb 504 _cache = NULL;
richardparker 6:4fe6f365cbeb 505 }
richardparker 6:4fe6f365cbeb 506 _size = 0L;
richardparker 6:4fe6f365cbeb 507 _pos = 0L;
richardparker 1:f04bcaea1d60 508 }
richardparker 1:f04bcaea1d60 509
richardparker 0:839ecbf5cb2a 510 void EAImage::paint(EALCD& lcd)
richardparker 0:839ecbf5cb2a 511 {
richardparker 0:839ecbf5cb2a 512 paint(lcd, 0, 0, width(), height());
richardparker 0:839ecbf5cb2a 513 }
richardparker 0:839ecbf5cb2a 514
richardparker 0:839ecbf5cb2a 515 void EAImage::paint(EALCD& lcd, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
richardparker 0:839ecbf5cb2a 516 {
richardparker 0:839ecbf5cb2a 517 if (isValid() == false)
richardparker 0:839ecbf5cb2a 518 {
richardparker 0:839ecbf5cb2a 519 return;
richardparker 0:839ecbf5cb2a 520 }
richardparker 0:839ecbf5cb2a 521
richardparker 0:839ecbf5cb2a 522 // Don't allow draw out of range.
richardparker 0:839ecbf5cb2a 523 if (x + w > width())
richardparker 0:839ecbf5cb2a 524 {
richardparker 0:839ecbf5cb2a 525 return;
richardparker 0:839ecbf5cb2a 526 }
richardparker 0:839ecbf5cb2a 527
richardparker 0:839ecbf5cb2a 528 if (y + h > height())
richardparker 0:839ecbf5cb2a 529 {
richardparker 0:839ecbf5cb2a 530 return;
richardparker 0:839ecbf5cb2a 531 }
richardparker 0:839ecbf5cb2a 532
richardparker 1:f04bcaea1d60 533 // Buffer to hold load one line at a time this must be large enough to hold all of the data used
richardparker 1:f04bcaea1d60 534 // for a line in the file. Note that the line in the file is padded so that it always ends on a
richardparker 1:f04bcaea1d60 535 // 32 bit boundary.
richardparker 1:f04bcaea1d60 536 int wordsInRow = _wordsInRow();
richardparker 1:f04bcaea1d60 537 unsigned int buffer[wordsInRow];
richardparker 0:839ecbf5cb2a 538 int xD = 0;
richardparker 0:839ecbf5cb2a 539 int yD = 0;
richardparker 1:f04bcaea1d60 540 int wordOffset = 0;
richardparker 1:f04bcaea1d60 541 int bitsPerPixel = info().bitsPerPixel;
richardparker 1:f04bcaea1d60 542 unsigned short data = 0;
richardparker 0:839ecbf5cb2a 543
richardparker 0:839ecbf5cb2a 544 // Try and open the file, skip straight to the data.
richardparker 6:4fe6f365cbeb 545 FILE* fp = NULL;
richardparker 6:4fe6f365cbeb 546 if (isCached() == false)
richardparker 0:839ecbf5cb2a 547 {
richardparker 6:4fe6f365cbeb 548 fp = fopen(_path, "r");
richardparker 6:4fe6f365cbeb 549 if (fp == NULL)
richardparker 6:4fe6f365cbeb 550 {
richardparker 6:4fe6f365cbeb 551 return;
richardparker 6:4fe6f365cbeb 552 }
richardparker 6:4fe6f365cbeb 553 }
richardparker 6:4fe6f365cbeb 554
richardparker 6:4fe6f365cbeb 555 // If the bits per pixel are less than 16 then the bitmap is using a colour
richardparker 6:4fe6f365cbeb 556 // palette which should be loaded first.
richardparker 6:4fe6f365cbeb 557 if (_loadPalette(fp) == false)
richardparker 6:4fe6f365cbeb 558 {
richardparker 6:4fe6f365cbeb 559 if (isCached() == false)
richardparker 6:4fe6f365cbeb 560 {
richardparker 6:4fe6f365cbeb 561 fclose(fp);
richardparker 6:4fe6f365cbeb 562 }
richardparker 6:4fe6f365cbeb 563
richardparker 0:839ecbf5cb2a 564 return;
richardparker 0:839ecbf5cb2a 565 }
richardparker 0:839ecbf5cb2a 566
richardparker 0:839ecbf5cb2a 567 // Skip the header and size.
richardparker 6:4fe6f365cbeb 568 _fseek(fp, _dataOffset, SEEK_SET);
richardparker 0:839ecbf5cb2a 569
richardparker 0:839ecbf5cb2a 570 // Prepare the lcd for drawing.
richardparker 0:839ecbf5cb2a 571 lcd._window(this->x(), this->y(), w, h);
richardparker 0:839ecbf5cb2a 572 lcd._moveTo(this->x(), this->y());
richardparker 0:839ecbf5cb2a 573
richardparker 0:839ecbf5cb2a 574 // Move in the file to the first pixel in the window.
richardparker 6:4fe6f365cbeb 575 _fseek(fp, (y*wordsInRow*4)+(_wordForX(x)*4), SEEK_CUR);
richardparker 1:f04bcaea1d60 576
richardparker 0:839ecbf5cb2a 577 // Now read the data.
richardparker 6:4fe6f365cbeb 578 while (!_feof(fp))
richardparker 0:839ecbf5cb2a 579 {
richardparker 1:f04bcaea1d60 580 wordOffset = _xWordOffset(x);
richardparker 1:f04bcaea1d60 581
richardparker 6:4fe6f365cbeb 582 int sizeRead = _fread(&buffer, 4, wordsInRow, fp);
richardparker 0:839ecbf5cb2a 583
richardparker 0:839ecbf5cb2a 584 for (int i = 0; i < sizeRead; i++)
richardparker 1:f04bcaea1d60 585 {
richardparker 1:f04bcaea1d60 586 while (wordOffset < 32)
richardparker 1:f04bcaea1d60 587 {
richardparker 1:f04bcaea1d60 588 // Convert the colour to a 16 bit colour value that can be written directly to the screen.
richardparker 1:f04bcaea1d60 589 data = _getColourAtOffset(buffer[i], wordOffset);
richardparker 6:4fe6f365cbeb 590
richardparker 1:f04bcaea1d60 591 if (isMask() == true)
richardparker 1:f04bcaea1d60 592 {
richardparker 1:f04bcaea1d60 593 // When a mask the 0x0000 value is transparent anything else is drawn with the pen color.
richardparker 1:f04bcaea1d60 594 if (data == 0x0000)
richardparker 1:f04bcaea1d60 595 {
richardparker 1:f04bcaea1d60 596 lcd.noop();
richardparker 1:f04bcaea1d60 597 } else {
richardparker 1:f04bcaea1d60 598 lcd._writeToDisplay(lcd.pen().color().rawValue());
richardparker 1:f04bcaea1d60 599 }
richardparker 6:4fe6f365cbeb 600 } else {
richardparker 1:f04bcaea1d60 601 // Not a mask so just use colour that have loaded.
richardparker 1:f04bcaea1d60 602 lcd._writeToDisplay(data);
richardparker 1:f04bcaea1d60 603 }
richardparker 1:f04bcaea1d60 604
richardparker 1:f04bcaea1d60 605 // Got to next pixel in the word.
richardparker 1:f04bcaea1d60 606 wordOffset += bitsPerPixel;
richardparker 1:f04bcaea1d60 607
richardparker 1:f04bcaea1d60 608 // Keep count of current x value.
richardparker 1:f04bcaea1d60 609 xD++;
richardparker 1:f04bcaea1d60 610 if (xD == w)
richardparker 1:f04bcaea1d60 611 {
richardparker 1:f04bcaea1d60 612 break;
richardparker 1:f04bcaea1d60 613 }
richardparker 1:f04bcaea1d60 614 }
richardparker 1:f04bcaea1d60 615 wordOffset = 0;
richardparker 0:839ecbf5cb2a 616
richardparker 1:f04bcaea1d60 617 // When written all required pixels exit.
richardparker 0:839ecbf5cb2a 618 if (xD == w)
richardparker 0:839ecbf5cb2a 619 {
richardparker 0:839ecbf5cb2a 620 xD = 0;
richardparker 0:839ecbf5cb2a 621 break;
richardparker 0:839ecbf5cb2a 622 }
richardparker 0:839ecbf5cb2a 623 }
richardparker 0:839ecbf5cb2a 624
richardparker 0:839ecbf5cb2a 625 // Keep count of curernt y value.
richardparker 0:839ecbf5cb2a 626 yD++;
richardparker 0:839ecbf5cb2a 627 if (yD == h)
richardparker 0:839ecbf5cb2a 628 {
richardparker 0:839ecbf5cb2a 629 break;
richardparker 0:839ecbf5cb2a 630 }
richardparker 0:839ecbf5cb2a 631 }
richardparker 0:839ecbf5cb2a 632
richardparker 1:f04bcaea1d60 633 // Clear the palette.
richardparker 1:f04bcaea1d60 634 if (_palette != NULL)
richardparker 1:f04bcaea1d60 635 {
richardparker 1:f04bcaea1d60 636 delete[] _palette;
richardparker 1:f04bcaea1d60 637 _palette = NULL;
richardparker 1:f04bcaea1d60 638 }
richardparker 1:f04bcaea1d60 639
richardparker 6:4fe6f365cbeb 640 if (isCached() == false)
richardparker 6:4fe6f365cbeb 641 {
richardparker 6:4fe6f365cbeb 642 // Close the file and release handle.
richardparker 6:4fe6f365cbeb 643 fclose(fp);
richardparker 6:4fe6f365cbeb 644 }
richardparker 0:839ecbf5cb2a 645 }
richardparker 0:839ecbf5cb2a 646
richardparker 0:839ecbf5cb2a 647