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