Richard Parker / EALCD
Committer:
richardparker
Date:
Wed Mar 31 22:22:21 2010 +0000
Revision:
3:24fbf4dbd7e5
Parent:
1:f04bcaea1d60
Child:
6:4fe6f365cbeb

        

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