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.
BMPFile.cpp
00001 // ==================================================== Mar 04 2015, kayeks == 00002 // BMPFile.cpp 00003 // =========================================================================== 00004 // File library for Bitmap images (*.bmp, *.dib). 00005 00006 #include "BMPFile.h" 00007 00008 const char* BMPFile::StatusString[] = { 00009 "Success", 00010 "NullFileName", 00011 "NoSuchFile", 00012 "NotABitmapFile", 00013 "UnsupportedFormat", 00014 "UnsupportedDepth", 00015 "AllocationFailed" 00016 }; 00017 const char* BMPFile::FormatString[] = { 00018 "OS2_V1", 00019 "OS2_V2", 00020 "Windows_V3", 00021 "Windows_V4", 00022 "Windows_V5", 00023 "Unknown" 00024 }; 00025 00026 void BMPFile::readFile(FILE* fp, bool fetchData) { 00027 uint8_t buf8[2]; 00028 uint16_t buf16[2]; 00029 uint32_t buf32[3]; 00030 00031 if (!fp) { 00032 status = NoSuchFile; 00033 return; 00034 } 00035 00036 // (0 +2) Magic number ("BM") 00037 fread(buf8, 1, 2, fp); 00038 if (buf8[0] != 'B' || buf8[1] != 'M') { 00039 status = NotABitmapFile; 00040 fclose(fp); 00041 return; 00042 } 00043 00044 // (2 +4) File size 00045 // (6 +4) Reserved area 00046 // (10 +4) Image data offset (unconfirmed) 00047 fread(buf32, 4, 3, fp); 00048 fileSize = buf32[0]; 00049 00050 // (14 +4) Header size 00051 fread(buf32, 4, 1, fp); 00052 switch (buf32[0]) { 00053 case 12: // OS/2 V1 format 00054 format = OS2_V1; 00055 break; 00056 case 64: // OS/2 V2 format 00057 format = OS2_V2; 00058 break; 00059 case 40: // Windows V3 format 00060 format = Windows_V3; 00061 break; 00062 case 108: // Windows V4 format 00063 format = Windows_V4; 00064 break; 00065 case 124: // Windows V5 format 00066 format = Windows_V5; 00067 break; 00068 default: 00069 format = Unknown; 00070 } 00071 00072 switch (format) { 00073 case OS2_V1: 00074 // (18 +2) Bitmap width 00075 // (20 +2) Bitmap height 00076 fread(buf16, 4, 2, fp); 00077 width = (uint32_t) buf16[0]; 00078 height = (uint32_t) buf16[1]; 00079 00080 // (22 +2) Number of planes (unconfirmed) 00081 // (24 +2) Color depth 00082 fread(buf16, 2, 2, fp); 00083 colorDepth = buf16[1]; 00084 switch (colorDepth) { 00085 case 1: case 4: case 8: 00086 paletteSize = paletteElemSize(format) * (1ul << colorDepth); 00087 break; 00088 case 16: case 24: case 32: // No palette 00089 paletteSize = 0; 00090 break; 00091 default: 00092 paletteSize = 0; 00093 status = UnsupportedDepth; 00094 fclose(fp); 00095 return; 00096 } 00097 break; 00098 case Windows_V3: 00099 // (18 +4) Bitmap width 00100 // (22 +4) Bitmap height 00101 fread(buf32, 4, 2, fp); 00102 width = buf32[0]; 00103 height = buf32[1]; 00104 00105 // (26 +2) Number of planes (unconfirmed) 00106 // (28 +2) Color depth 00107 fread(buf16, 2, 2, fp); 00108 colorDepth = buf16[1]; 00109 switch (colorDepth) { 00110 case 1: case 4: case 8: 00111 paletteSize = paletteElemSize(format) * (1ul << colorDepth); 00112 break; 00113 case 16: case 24: case 32: // No palette 00114 paletteSize = 0; 00115 break; 00116 default: 00117 paletteSize = 0; 00118 status = UnsupportedDepth; 00119 fclose(fp); 00120 return; 00121 } 00122 00123 // (30 +4) Compression method (unconfirmed) 00124 // (34 +4) Bitmap data size (unconfirmed) 00125 // (38 +4) Horizontal resolution (unused) 00126 // (42 +4) Vertical resolution (unconfirmed) 00127 // (46 +4) Colors (unconfirmed) 00128 // (50 +4) Important colors (unconfirmed) 00129 fread(buf32, 4, 3, fp); 00130 fread(buf32, 4, 3, fp); 00131 break; 00132 case OS2_V2: 00133 case Windows_V4: 00134 case Windows_V5: 00135 case Unknown: 00136 status = UnsupportedFormat; 00137 fclose(fp); 00138 return; 00139 } 00140 00141 // Allocate palette space if needed 00142 if (paletteSize) { 00143 palette = new uint8_t[paletteSize]; 00144 00145 // Read palette data 00146 fread(palette, 1, paletteSize, fp); 00147 } 00148 00149 // Calculate stride / data length 00150 if (colorDepth == 1) { 00151 stride = ALIGN_BY_4((width + 7) / 8); 00152 } else if (colorDepth == 4) { 00153 stride = ALIGN_BY_4((width + 1) / 2); 00154 } else { 00155 // Color depth: 8, 16, 24, 32 00156 stride = ALIGN_BY_4(width * colorDepth / 8); 00157 } 00158 dataSize = stride * height; 00159 00160 // Read image data 00161 if (fetchData) { 00162 readImageData(fp); 00163 } 00164 fclose(fp); 00165 } 00166 00167 BMPFile::BMPFile(const char* filename, bool fetchData) { 00168 FILE* fp; 00169 00170 status = Success; 00171 format = Unknown; 00172 fileSize = 0; 00173 paletteSize = 0; 00174 dataSize = 0; 00175 stride = 0; 00176 width = 0; 00177 height = 0; 00178 colorDepth = 0; 00179 palette = NULL; 00180 data = NULL; 00181 00182 // Open file 00183 if (!filename) { 00184 status = NullFilename; 00185 return; 00186 } 00187 fp = fopen(filename, "rb"); 00188 00189 // Read file 00190 readFile(fp, fetchData); 00191 } 00192 00193 BMPFile::BMPFile(FILE* fp, bool fetch) { 00194 status = Success; 00195 format = Unknown; 00196 fileSize = 0; 00197 paletteSize = 0; 00198 dataSize = 0; 00199 stride = 0; 00200 width = 0; 00201 height = 0; 00202 colorDepth = 0; 00203 palette = NULL; 00204 data = NULL; 00205 00206 // Read file 00207 readFile(fp, fetch); 00208 } 00209 00210 BMPFile::~BMPFile() { 00211 if (palette) { 00212 delete[] palette; 00213 } 00214 if (data) { 00215 delete[] data; 00216 } 00217 } 00218 00219 void BMPFile::readImageData(FILE* fp) { 00220 // Allocate data space 00221 data = new uint8_t[dataSize]; 00222 00223 // Read bitmap data 00224 fread(data, 1, dataSize, fp); 00225 } 00226 00227 uint32_t BMPFile::paletteElemSize(BMPFile::Format format) { 00228 switch (format) { 00229 case OS2_V1: case OS2_V2: 00230 // BGR888 00231 return 3; 00232 case Windows_V3: case Windows_V4: case Windows_V5: 00233 // BGRX8888 00234 return 4; 00235 default: 00236 return 0; 00237 } 00238 } 00239 00240 int32_t BMPFile::paletteRed(uint8_t index) { 00241 if (!palette) { 00242 return -1; 00243 } 00244 switch (colorDepth) { 00245 case 1: case 4: case 8: 00246 if (index >= 1ul << colorDepth) { 00247 return -1; 00248 } else { 00249 return palette[paletteElemSize(format) * index + 2]; 00250 } 00251 default: 00252 return -1; 00253 } 00254 } 00255 00256 int32_t BMPFile::paletteGreen(uint8_t index) { 00257 if (!palette) { 00258 return -1; 00259 } 00260 switch (colorDepth) { 00261 case 1: case 4: case 8: 00262 if (index >= 1ul << colorDepth) { 00263 return -1; 00264 } else { 00265 return palette[paletteElemSize(format) * index + 1]; 00266 } 00267 default: 00268 return -1; 00269 } 00270 } 00271 00272 int32_t BMPFile::paletteBlue(uint8_t index) { 00273 if (!palette) { 00274 return -1; 00275 } 00276 switch (colorDepth) { 00277 case 1: case 4: case 8: 00278 if (index >= 1ul << colorDepth) { 00279 return -1; 00280 } else { 00281 return palette[paletteElemSize(format) * index]; 00282 } 00283 default: 00284 return -1; 00285 } 00286 } 00287 00288 int32_t BMPFile::red(uint32_t x, uint32_t y) { 00289 if (x >= width || y >= height) { 00290 return -1; 00291 } 00292 if (!data) { 00293 return -1; 00294 } 00295 switch (colorDepth) { 00296 case 1: // Indexed from palette 00297 return paletteRed((data[stride * y + x / 8] >> 7 - x % 8) & 0x01); 00298 case 4: // Indexed from palette 00299 return paletteRed((data[stride * y + x / 2] >> 4 * (1 - x % 2)) & 0x0f); 00300 case 8: // Indexed from palette 00301 return paletteRed(data[stride * y + x]); 00302 case 16: // BGR565 (bbbbbggg:gggrrrrr) 00303 return (data[stride * y + 2 * x + 1] & 0x1f) * 2; 00304 case 24: // BGR888 00305 return data[stride * y + 3 * x + 2]; 00306 case 32: // BGRX8888 00307 return data[stride * y + 4 * x + 2]; 00308 default: 00309 return -1; 00310 } 00311 } 00312 00313 int32_t BMPFile::green(uint32_t x, uint32_t y) { 00314 if (x >= width || y >= height) { 00315 return -1; 00316 } 00317 if (!data) { 00318 return -1; 00319 } 00320 switch (colorDepth) { 00321 case 1: // Indexed from palette 00322 return paletteGreen((data[stride * y + x / 8] >> 7 - x % 8) & 0x01); 00323 case 4: // Indexed from palette 00324 return paletteGreen((data[stride * y + x / 2] >> 4 * (1 - x % 2)) & 0x0f); 00325 case 8: // Indexed from palette 00326 return paletteGreen(data[stride * y + x]); 00327 case 16: // BGR565 (bbbbbggg:gggrrrrr) 00328 return ((data[stride * y + 2 * x] & 0x07) << 3 00329 | data[stride * y + 2 * x + 1] >> 5) * 2; 00330 case 24: // BGR888 00331 return data[stride * y + 3 * x + 1]; 00332 case 32: // BGRX8888 00333 return data[stride * y + 4 * x + 1]; 00334 default: 00335 return -1; 00336 } 00337 } 00338 00339 int32_t BMPFile::blue(uint32_t x, uint32_t y) { 00340 if (x >= width || y >= height) { 00341 return -1; 00342 } 00343 if (!data) { 00344 return -1; 00345 } 00346 switch (colorDepth) { 00347 case 1: // Indexed from palette 00348 return paletteBlue((data[stride * y + x / 8] >> 7 - x % 8) & 0x01); 00349 case 4: // Indexed from palette 00350 return paletteBlue((data[stride * y + x / 2] >> 4 * (1 - x % 2)) & 0x0f); 00351 case 8: // Indexed from palette 00352 return paletteBlue(data[stride * y + x]); 00353 case 16: // RGB565 (bbbbbggg:gggrrrrr) 00354 return (data[stride * y + 2 * x] >> 3) * 2; 00355 case 24: // BGR888 00356 return data[stride * y + 3 * x]; 00357 case 32: // BGRX8888 00358 return data[stride * y + 4 * x]; 00359 default: 00360 return -1; 00361 } 00362 }
Generated on Wed Jul 13 2022 23:09:00 by
1.7.2