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@3:24fbf4dbd7e5, 2010-03-31 (annotated)
- 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?
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 | 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 |