Shows how to use a display and the onboard SD Card. Requires a display module with an adapter

Dependencies:   DmTftLibrary SDFileSystem mbed

Committer:
displaymodule
Date:
Mon Jul 07 11:43:35 2014 +0000
Revision:
3:030be860c83d
Parent:
0:ee27d4c12433
Child:
5:ed6a302e0917
Added basic clipping of BMP files.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
displaymodule 0:ee27d4c12433 1 /**********************************************************************************************
displaymodule 0:ee27d4c12433 2 Copyright (c) 2014 DisplayModule. All rights reserved.
displaymodule 0:ee27d4c12433 3
displaymodule 0:ee27d4c12433 4 Redistribution and use of this source code, part of this source code or any compiled binary
displaymodule 0:ee27d4c12433 5 based on this source code is permitted as long as the above copyright notice and following
displaymodule 0:ee27d4c12433 6 disclaimer is retained.
displaymodule 0:ee27d4c12433 7
displaymodule 0:ee27d4c12433 8 DISCLAIMER:
displaymodule 0:ee27d4c12433 9 THIS SOFTWARE IS SUPPLIED "AS IS" WITHOUT ANY WARRANTIES AND SUPPORT. DISPLAYMODULE ASSUMES
displaymodule 0:ee27d4c12433 10 NO RESPONSIBILITY OR LIABILITY FOR THE USE OF THE SOFTWARE.
displaymodule 0:ee27d4c12433 11 ********************************************************************************************/
displaymodule 0:ee27d4c12433 12
displaymodule 0:ee27d4c12433 13 #include "DmDrawBmpBase.h"
displaymodule 0:ee27d4c12433 14
displaymodule 0:ee27d4c12433 15 bool DmDrawBmpBase::drawBitmap(DmTftBase& tft, uint16_t x, uint16_t y, readFunc func, uint32_t userData) {
displaymodule 0:ee27d4c12433 16 _readFunc = func;
displaymodule 0:ee27d4c12433 17 _userData = userData;
displaymodule 0:ee27d4c12433 18 _readPos = 0;
displaymodule 0:ee27d4c12433 19
displaymodule 0:ee27d4c12433 20 if (readBmpHeader()) {
displaymodule 0:ee27d4c12433 21 if (IsValid565Bitmap()) {
displaymodule 0:ee27d4c12433 22 return draw565Bitmap(tft, x, y);
displaymodule 0:ee27d4c12433 23 }
displaymodule 0:ee27d4c12433 24 if (IsValid888Bitmap()) {
displaymodule 0:ee27d4c12433 25 return draw888Bitmap(tft, x, y);
displaymodule 0:ee27d4c12433 26 }
displaymodule 0:ee27d4c12433 27 }
displaymodule 0:ee27d4c12433 28 return false;
displaymodule 0:ee27d4c12433 29 }
displaymodule 0:ee27d4c12433 30
displaymodule 0:ee27d4c12433 31 bool DmDrawBmpBase::draw888Bitmap(DmTftBase& tft, uint16_t x, uint16_t y) {
displaymodule 0:ee27d4c12433 32 const uint8_t bytesPerPixel = 3;
displaymodule 3:030be860c83d 33 uint32_t _bitmapOffset;
displaymodule 0:ee27d4c12433 34 uint8_t red, green, blue;
displaymodule 0:ee27d4c12433 35 uint16_t row, column;
displaymodule 0:ee27d4c12433 36 uint16_t bytesPerRow = (bytesPerPixel*_width + 3) & ~3;
displaymodule 0:ee27d4c12433 37 uint8_t buff[20*bytesPerPixel];
displaymodule 0:ee27d4c12433 38 uint8_t buffPos = sizeof(buff);
displaymodule 3:030be860c83d 39 uint16_t clipX = _width;
displaymodule 3:030be860c83d 40 uint16_t clipY = _height;
displaymodule 3:030be860c83d 41
displaymodule 3:030be860c83d 42 //make sure image fits
displaymodule 3:030be860c83d 43 if ((x + clipX) > tft.width()) {
displaymodule 3:030be860c83d 44 clipX = tft.width() - x;
displaymodule 3:030be860c83d 45 }
displaymodule 3:030be860c83d 46 if ((y + clipY) > tft.height()) {
displaymodule 3:030be860c83d 47 clipY = tft.height() - y;
displaymodule 3:030be860c83d 48 }
displaymodule 3:030be860c83d 49
displaymodule 0:ee27d4c12433 50 tft.select();
displaymodule 3:030be860c83d 51 tft.setAddress(x, y, x+clipX-1, y+clipY-1);
displaymodule 0:ee27d4c12433 52 tft.unSelect();
displaymodule 0:ee27d4c12433 53
displaymodule 0:ee27d4c12433 54 for(row=0; row<_height; row++) {
displaymodule 3:030be860c83d 55 _readPos = _bitmapOffset + (_height - 1 -row ) * bytesPerRow;
displaymodule 0:ee27d4c12433 56 buffPos = sizeof(buff);
displaymodule 0:ee27d4c12433 57
displaymodule 0:ee27d4c12433 58 for(column=0; column<_width; column++) {
displaymodule 0:ee27d4c12433 59 if (buffPos >= sizeof(buff)) {
displaymodule 0:ee27d4c12433 60 tft.unSelect();
displaymodule 0:ee27d4c12433 61 _readFunc(_userData, buff, _readPos, sizeof(buff));
displaymodule 0:ee27d4c12433 62 _readPos += sizeof(buff);
displaymodule 0:ee27d4c12433 63 tft.select();
displaymodule 0:ee27d4c12433 64 buffPos = 0;
displaymodule 0:ee27d4c12433 65 }
displaymodule 0:ee27d4c12433 66
displaymodule 0:ee27d4c12433 67 blue = buff[buffPos++];
displaymodule 0:ee27d4c12433 68 green = buff[buffPos++];
displaymodule 0:ee27d4c12433 69 red = buff[buffPos++];
displaymodule 0:ee27d4c12433 70
displaymodule 3:030be860c83d 71 if (row < clipY && column < clipX) {
displaymodule 3:030be860c83d 72 tft.sendData(Convert888to565(red, green, blue));
displaymodule 3:030be860c83d 73 }
displaymodule 0:ee27d4c12433 74 }
displaymodule 0:ee27d4c12433 75 }
displaymodule 0:ee27d4c12433 76 tft.unSelect();
displaymodule 0:ee27d4c12433 77 return true;
displaymodule 0:ee27d4c12433 78 }
displaymodule 0:ee27d4c12433 79
displaymodule 0:ee27d4c12433 80 bool DmDrawBmpBase::draw565Bitmap(DmTftBase& tft, uint16_t x, uint16_t y) {
displaymodule 0:ee27d4c12433 81 const uint8_t bytesPerPixel = 2;
displaymodule 0:ee27d4c12433 82 uint8_t buff[30*bytesPerPixel]; // Should be dividable by bytesPerPixel
displaymodule 0:ee27d4c12433 83 uint8_t buffPos = sizeof(buff);
displaymodule 0:ee27d4c12433 84 uint16_t bytesPerRow = (bytesPerPixel * _width + 3) & ~3; // bytes Per Row including padding to 4 bytes boundary
displaymodule 0:ee27d4c12433 85 uint16_t paddingSize = bytesPerRow - (bytesPerPixel * _width); // paddingSize for each row
displaymodule 0:ee27d4c12433 86 uint16_t height = -_height; // Change if load bottom-top
displaymodule 0:ee27d4c12433 87 uint16_t pixel;
displaymodule 0:ee27d4c12433 88 uint16_t row, column;
displaymodule 3:030be860c83d 89 uint16_t clipX = _width;
displaymodule 3:030be860c83d 90 uint16_t clipY = height;
displaymodule 0:ee27d4c12433 91 _readPos = _bitmapOffset;
displaymodule 0:ee27d4c12433 92
displaymodule 0:ee27d4c12433 93 //_imageFile.seek(_bitmapOffset);
displaymodule 0:ee27d4c12433 94
displaymodule 3:030be860c83d 95 //make sure image fits
displaymodule 3:030be860c83d 96 if ((x + clipX) > tft.width()) {
displaymodule 3:030be860c83d 97 clipX = tft.width() - x;
displaymodule 3:030be860c83d 98 }
displaymodule 3:030be860c83d 99 if ((y + clipY) > tft.height()) {
displaymodule 3:030be860c83d 100 clipY = tft.height() - y;
displaymodule 3:030be860c83d 101 }
displaymodule 3:030be860c83d 102
displaymodule 0:ee27d4c12433 103 tft.select();
displaymodule 3:030be860c83d 104 tft.setAddress(x, y, x+clipX-1, y+clipY-1);
displaymodule 0:ee27d4c12433 105 tft.unSelect();
displaymodule 0:ee27d4c12433 106
displaymodule 0:ee27d4c12433 107 for(row=0; row<height; row++) {
displaymodule 0:ee27d4c12433 108 for(column=0; column<_width; column++) {
displaymodule 0:ee27d4c12433 109 if (buffPos >= sizeof(buff)) {
displaymodule 0:ee27d4c12433 110 tft.unSelect();
displaymodule 0:ee27d4c12433 111 _readFunc(_userData, buff, _readPos, sizeof(buff));
displaymodule 0:ee27d4c12433 112 _readPos += sizeof(buff);
displaymodule 0:ee27d4c12433 113 //_imageFile.read(buff, sizeof(buff));
displaymodule 0:ee27d4c12433 114 tft.select();
displaymodule 0:ee27d4c12433 115 buffPos = 0;
displaymodule 0:ee27d4c12433 116 }
displaymodule 0:ee27d4c12433 117 pixel = buff[buffPos++] & 0xFF;
displaymodule 0:ee27d4c12433 118 pixel |= buff[buffPos++] << 8;
displaymodule 3:030be860c83d 119 if (row < clipY && column < clipX) {
displaymodule 3:030be860c83d 120 tft.sendData(pixel);
displaymodule 3:030be860c83d 121 }
displaymodule 0:ee27d4c12433 122 }
displaymodule 0:ee27d4c12433 123
displaymodule 0:ee27d4c12433 124 if ( paddingSize > 0 ) { // Check if there is padding in the file
displaymodule 0:ee27d4c12433 125 if ((sizeof(buff) - buffPos) >= paddingSize) { // Most common case, the padding is in the buffer
displaymodule 0:ee27d4c12433 126 buffPos += paddingSize;
displaymodule 0:ee27d4c12433 127 }
displaymodule 0:ee27d4c12433 128 else { // Padding is not in the buffer, we have to load the buffer from file
displaymodule 0:ee27d4c12433 129 tft.unSelect();
displaymodule 0:ee27d4c12433 130 _readFunc(_userData, buff, _readPos, sizeof(buff));
displaymodule 0:ee27d4c12433 131 _readPos += sizeof(buff);
displaymodule 0:ee27d4c12433 132 // _imageFile.read(buff, sizeof(buff));
displaymodule 0:ee27d4c12433 133 tft.select();
displaymodule 0:ee27d4c12433 134 buffPos = paddingSize-(sizeof(buff) - buffPos); // paddingSize (0-3) spaceLeftInBuffer (0-3) where spaceLeftInBuffer < paddingSize
displaymodule 0:ee27d4c12433 135 }
displaymodule 0:ee27d4c12433 136 }
displaymodule 0:ee27d4c12433 137 }
displaymodule 0:ee27d4c12433 138 tft.unSelect();
displaymodule 0:ee27d4c12433 139
displaymodule 0:ee27d4c12433 140 return true;
displaymodule 0:ee27d4c12433 141 }
displaymodule 0:ee27d4c12433 142
displaymodule 0:ee27d4c12433 143 void DmDrawBmpBase::printBmpHeaderInfo() {
displaymodule 0:ee27d4c12433 144 printf("Image size: %d\n", _fileSize);
displaymodule 0:ee27d4c12433 145 printf("Image offset: %d\n", _bitmapOffset);
displaymodule 0:ee27d4c12433 146 printf("Image size: %d, %d\n", _width, _height);
displaymodule 0:ee27d4c12433 147 printf("BitsPerPixel: %d\n",_bitsPerPixel);
displaymodule 0:ee27d4c12433 148 printf("Compression: %d\n",_compression);
displaymodule 0:ee27d4c12433 149 printf("Is 24-bit bmp: %d\n", IsValid888Bitmap());
displaymodule 0:ee27d4c12433 150 printf("Is 16-bit 565 bmp: %d\n", IsValid565Bitmap());
displaymodule 0:ee27d4c12433 151 printf("Has 565 color mask: %d\n", Is565ColorMask());
displaymodule 0:ee27d4c12433 152 }
displaymodule 0:ee27d4c12433 153
displaymodule 0:ee27d4c12433 154 bool DmDrawBmpBase::readBmpHeader() {
displaymodule 0:ee27d4c12433 155 if (read16() !=0x4D42){ // read magic byte
displaymodule 0:ee27d4c12433 156 return false;
displaymodule 0:ee27d4c12433 157 }
displaymodule 0:ee27d4c12433 158
displaymodule 0:ee27d4c12433 159 _fileSize = read32();
displaymodule 0:ee27d4c12433 160 read32(); // Value depends on application which created the image
displaymodule 0:ee27d4c12433 161 _bitmapOffset = read32();
displaymodule 0:ee27d4c12433 162
displaymodule 0:ee27d4c12433 163 // read DIB header
displaymodule 0:ee27d4c12433 164 _headerSize = read32();
displaymodule 0:ee27d4c12433 165 _width = readInt32();
displaymodule 0:ee27d4c12433 166 _height = readInt32();
displaymodule 0:ee27d4c12433 167
displaymodule 0:ee27d4c12433 168 if (read16() != 1) { // number of color planes must be 1
displaymodule 0:ee27d4c12433 169 return false;
displaymodule 0:ee27d4c12433 170 }
displaymodule 0:ee27d4c12433 171
displaymodule 0:ee27d4c12433 172 _bitsPerPixel = read16();
displaymodule 0:ee27d4c12433 173 _compression = read32();
displaymodule 0:ee27d4c12433 174
displaymodule 0:ee27d4c12433 175 if (_bitmapOffset == 66 || _bitmapOffset == 70) { // V3 or v2 format
displaymodule 0:ee27d4c12433 176 //setPosition(54);
displaymodule 0:ee27d4c12433 177 _readPos = 54;
displaymodule 0:ee27d4c12433 178 _redMask = read32();
displaymodule 0:ee27d4c12433 179 _greenMask = read32();
displaymodule 0:ee27d4c12433 180 _blueMask = read32();
displaymodule 0:ee27d4c12433 181 }
displaymodule 0:ee27d4c12433 182 else {
displaymodule 0:ee27d4c12433 183 _redMask = 0x00;
displaymodule 0:ee27d4c12433 184 _greenMask = 0x00;
displaymodule 0:ee27d4c12433 185 _blueMask = 0x00;
displaymodule 0:ee27d4c12433 186 }
displaymodule 0:ee27d4c12433 187
displaymodule 0:ee27d4c12433 188 if (!IsValid888Bitmap() && !IsValid565Bitmap())
displaymodule 0:ee27d4c12433 189 {
displaymodule 0:ee27d4c12433 190 return false;
displaymodule 0:ee27d4c12433 191 }
displaymodule 0:ee27d4c12433 192
displaymodule 0:ee27d4c12433 193 return true;
displaymodule 0:ee27d4c12433 194 }
displaymodule 0:ee27d4c12433 195
displaymodule 0:ee27d4c12433 196 // In this context a valid bitmap
displaymodule 0:ee27d4c12433 197 // - Stored bottom to top
displaymodule 0:ee27d4c12433 198 // - 24-bit file
displaymodule 0:ee27d4c12433 199 // - No compression
displaymodule 0:ee27d4c12433 200 bool DmDrawBmpBase::IsValid888Bitmap() {
displaymodule 0:ee27d4c12433 201 if (_height > 0 && _bitsPerPixel == 24 && _compression == 0)
displaymodule 0:ee27d4c12433 202 {
displaymodule 0:ee27d4c12433 203 return true;
displaymodule 0:ee27d4c12433 204 }
displaymodule 0:ee27d4c12433 205 return false;
displaymodule 0:ee27d4c12433 206 }
displaymodule 0:ee27d4c12433 207
displaymodule 0:ee27d4c12433 208 // In this context a valid bitmap
displaymodule 0:ee27d4c12433 209 // - Stored top to bottom
displaymodule 0:ee27d4c12433 210 // - 16-bit file
displaymodule 0:ee27d4c12433 211 // - Compression 3 (BI_BITFIELDS)
displaymodule 0:ee27d4c12433 212 // - Have a 565 Colormask
displaymodule 0:ee27d4c12433 213 bool DmDrawBmpBase::IsValid565Bitmap() {
displaymodule 0:ee27d4c12433 214 if (_height < 0 && _bitsPerPixel == 16 && _compression == 3 && Is565ColorMask())
displaymodule 0:ee27d4c12433 215 {
displaymodule 0:ee27d4c12433 216 return true;
displaymodule 0:ee27d4c12433 217 }
displaymodule 0:ee27d4c12433 218 return false;
displaymodule 0:ee27d4c12433 219 }
displaymodule 0:ee27d4c12433 220
displaymodule 0:ee27d4c12433 221 bool DmDrawBmpBase::Is565ColorMask() {
displaymodule 0:ee27d4c12433 222 if (_redMask == 0xF800 && _greenMask == 0x7E0 && _blueMask == 0x1F)
displaymodule 0:ee27d4c12433 223 {
displaymodule 0:ee27d4c12433 224 return true;
displaymodule 0:ee27d4c12433 225 }
displaymodule 0:ee27d4c12433 226 return false;
displaymodule 0:ee27d4c12433 227 }
displaymodule 0:ee27d4c12433 228
displaymodule 0:ee27d4c12433 229 int32_t DmDrawBmpBase::readInt32() {
displaymodule 0:ee27d4c12433 230 int32_t d;
displaymodule 0:ee27d4c12433 231 uint16_t b;
displaymodule 0:ee27d4c12433 232
displaymodule 0:ee27d4c12433 233 b = read16();
displaymodule 0:ee27d4c12433 234 d = read16();
displaymodule 0:ee27d4c12433 235 d <<= 16;
displaymodule 0:ee27d4c12433 236 d |= b;
displaymodule 0:ee27d4c12433 237 return d;
displaymodule 0:ee27d4c12433 238 }
displaymodule 0:ee27d4c12433 239
displaymodule 0:ee27d4c12433 240 uint32_t DmDrawBmpBase::read32() {
displaymodule 0:ee27d4c12433 241 uint32_t d;
displaymodule 0:ee27d4c12433 242 uint16_t b;
displaymodule 0:ee27d4c12433 243
displaymodule 0:ee27d4c12433 244 b = read16();
displaymodule 0:ee27d4c12433 245 d = read16();
displaymodule 0:ee27d4c12433 246 d <<= 16;
displaymodule 0:ee27d4c12433 247 d |= b;
displaymodule 0:ee27d4c12433 248 return d;
displaymodule 0:ee27d4c12433 249 }
displaymodule 0:ee27d4c12433 250
displaymodule 0:ee27d4c12433 251 uint16_t DmDrawBmpBase::read16() {
displaymodule 0:ee27d4c12433 252 //uint16_t d;
displaymodule 0:ee27d4c12433 253 //uint8_t b;
displaymodule 0:ee27d4c12433 254 uint8_t buff[2];
displaymodule 0:ee27d4c12433 255 //b = _imageFile.read();
displaymodule 0:ee27d4c12433 256 //d = _imageFile.read();
displaymodule 0:ee27d4c12433 257 _readFunc(_userData, buff, _readPos, 2);
displaymodule 0:ee27d4c12433 258 _readPos+=2;
displaymodule 0:ee27d4c12433 259 //d <<= 8;
displaymodule 0:ee27d4c12433 260 //d |= b;
displaymodule 0:ee27d4c12433 261 //return d;
displaymodule 0:ee27d4c12433 262 return (buff[1] << 8) | buff[0];
displaymodule 0:ee27d4c12433 263 }
displaymodule 0:ee27d4c12433 264
displaymodule 0:ee27d4c12433 265 // http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
displaymodule 0:ee27d4c12433 266 uint16_t DmDrawBmpBase::Convert888to565(uint8_t red, uint8_t green, uint8_t blue){
displaymodule 0:ee27d4c12433 267 return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
displaymodule 0:ee27d4c12433 268 }
displaymodule 0:ee27d4c12433 269