File library for Bitmap images (*.bmp, *.dib). Currently supports only Windows V3 format with 24-bit-per-pixel color depth.
BMPFile.cpp@0:4617bf407fe5, 2015-03-04 (annotated)
- Committer:
- kayekss
- Date:
- Wed Mar 04 00:29:12 2015 +0000
- Revision:
- 0:4617bf407fe5
- Child:
- 1:8cf4beca9695
Initial release.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kayekss | 0:4617bf407fe5 | 1 | // ==================================================== Mar 04 2015, kayeks == |
kayekss | 0:4617bf407fe5 | 2 | // BMPFile.cpp |
kayekss | 0:4617bf407fe5 | 3 | // =========================================================================== |
kayekss | 0:4617bf407fe5 | 4 | // File library for Bitmap images (*.bmp, *.dib). |
kayekss | 0:4617bf407fe5 | 5 | |
kayekss | 0:4617bf407fe5 | 6 | #include "BMPFile.h" |
kayekss | 0:4617bf407fe5 | 7 | |
kayekss | 0:4617bf407fe5 | 8 | const char* BMPFile::StatusString[] = { |
kayekss | 0:4617bf407fe5 | 9 | "Success", |
kayekss | 0:4617bf407fe5 | 10 | "NullFileName", |
kayekss | 0:4617bf407fe5 | 11 | "NoSuchFile", |
kayekss | 0:4617bf407fe5 | 12 | "NotABitmapFile", |
kayekss | 0:4617bf407fe5 | 13 | "UnsupportedFormat", |
kayekss | 0:4617bf407fe5 | 14 | "UnsupportedDepth", |
kayekss | 0:4617bf407fe5 | 15 | "AllocationFailed" |
kayekss | 0:4617bf407fe5 | 16 | }; |
kayekss | 0:4617bf407fe5 | 17 | const char* BMPFile::FormatString[] = { |
kayekss | 0:4617bf407fe5 | 18 | "Windows_V3", |
kayekss | 0:4617bf407fe5 | 19 | "Windows_V4", |
kayekss | 0:4617bf407fe5 | 20 | "Windows_V5", |
kayekss | 0:4617bf407fe5 | 21 | "OS2_V1", |
kayekss | 0:4617bf407fe5 | 22 | "OS2_V2", |
kayekss | 0:4617bf407fe5 | 23 | "Unknown" |
kayekss | 0:4617bf407fe5 | 24 | }; |
kayekss | 0:4617bf407fe5 | 25 | |
kayekss | 0:4617bf407fe5 | 26 | BMPFile::BMPFile(const char* filename) { |
kayekss | 0:4617bf407fe5 | 27 | FILE* fp; |
kayekss | 0:4617bf407fe5 | 28 | uint8_t buf8[2]; |
kayekss | 0:4617bf407fe5 | 29 | uint16_t buf16[2]; |
kayekss | 0:4617bf407fe5 | 30 | uint32_t buf32[3]; |
kayekss | 0:4617bf407fe5 | 31 | uint32_t offset; |
kayekss | 0:4617bf407fe5 | 32 | |
kayekss | 0:4617bf407fe5 | 33 | status = Success; |
kayekss | 0:4617bf407fe5 | 34 | format = Unknown; |
kayekss | 0:4617bf407fe5 | 35 | fileSize = 0; |
kayekss | 0:4617bf407fe5 | 36 | dataSize = 0; |
kayekss | 0:4617bf407fe5 | 37 | width = 0; |
kayekss | 0:4617bf407fe5 | 38 | height = 0; |
kayekss | 0:4617bf407fe5 | 39 | colorDepth = 0; |
kayekss | 0:4617bf407fe5 | 40 | data = NULL; |
kayekss | 0:4617bf407fe5 | 41 | |
kayekss | 0:4617bf407fe5 | 42 | // Open file |
kayekss | 0:4617bf407fe5 | 43 | if (!filename) { |
kayekss | 0:4617bf407fe5 | 44 | status = NullFilename; |
kayekss | 0:4617bf407fe5 | 45 | return; |
kayekss | 0:4617bf407fe5 | 46 | } |
kayekss | 0:4617bf407fe5 | 47 | fp = fopen(filename, "rb"); |
kayekss | 0:4617bf407fe5 | 48 | if (!fp) { |
kayekss | 0:4617bf407fe5 | 49 | status = NoSuchFile; |
kayekss | 0:4617bf407fe5 | 50 | return; |
kayekss | 0:4617bf407fe5 | 51 | } |
kayekss | 0:4617bf407fe5 | 52 | |
kayekss | 0:4617bf407fe5 | 53 | // (0 +2) Magic number ("BM") |
kayekss | 0:4617bf407fe5 | 54 | fread(buf8, 1, 2, fp); |
kayekss | 0:4617bf407fe5 | 55 | if (buf8[0] != 'B' || buf8[1] != 'M') { |
kayekss | 0:4617bf407fe5 | 56 | status = NotABitmapFile; |
kayekss | 0:4617bf407fe5 | 57 | fclose(fp); |
kayekss | 0:4617bf407fe5 | 58 | return; |
kayekss | 0:4617bf407fe5 | 59 | } |
kayekss | 0:4617bf407fe5 | 60 | |
kayekss | 0:4617bf407fe5 | 61 | // (2 +4) File size |
kayekss | 0:4617bf407fe5 | 62 | // (6 +4) Reserved area |
kayekss | 0:4617bf407fe5 | 63 | // (10 +4) Image data offset (unconfirmed) |
kayekss | 0:4617bf407fe5 | 64 | fread(buf32, 4, 3, fp); |
kayekss | 0:4617bf407fe5 | 65 | fileSize = buf32[0]; |
kayekss | 0:4617bf407fe5 | 66 | offset = buf32[2]; |
kayekss | 0:4617bf407fe5 | 67 | |
kayekss | 0:4617bf407fe5 | 68 | // (14 +4) Header size |
kayekss | 0:4617bf407fe5 | 69 | fread(buf32, 4, 1, fp); |
kayekss | 0:4617bf407fe5 | 70 | switch (buf32[0]) { |
kayekss | 0:4617bf407fe5 | 71 | case 40: // Windows V3 format |
kayekss | 0:4617bf407fe5 | 72 | format = Windows_V3; |
kayekss | 0:4617bf407fe5 | 73 | break; |
kayekss | 0:4617bf407fe5 | 74 | case 108: // Windows V4 format |
kayekss | 0:4617bf407fe5 | 75 | format = Windows_V4; |
kayekss | 0:4617bf407fe5 | 76 | break; |
kayekss | 0:4617bf407fe5 | 77 | case 124: // Windows V5 format |
kayekss | 0:4617bf407fe5 | 78 | format = Windows_V5; |
kayekss | 0:4617bf407fe5 | 79 | break; |
kayekss | 0:4617bf407fe5 | 80 | case 12: // OS/2 V1 format |
kayekss | 0:4617bf407fe5 | 81 | format = OS2_V1; |
kayekss | 0:4617bf407fe5 | 82 | break; |
kayekss | 0:4617bf407fe5 | 83 | case 64: // OS/2 V2 format |
kayekss | 0:4617bf407fe5 | 84 | format = OS2_V2; |
kayekss | 0:4617bf407fe5 | 85 | break; |
kayekss | 0:4617bf407fe5 | 86 | default: |
kayekss | 0:4617bf407fe5 | 87 | format = Unknown; |
kayekss | 0:4617bf407fe5 | 88 | } |
kayekss | 0:4617bf407fe5 | 89 | |
kayekss | 0:4617bf407fe5 | 90 | switch (format) { |
kayekss | 0:4617bf407fe5 | 91 | case Windows_V3: |
kayekss | 0:4617bf407fe5 | 92 | // (18 +4) Bitmap width |
kayekss | 0:4617bf407fe5 | 93 | // (22 +4) Bitmap height |
kayekss | 0:4617bf407fe5 | 94 | fread(buf32, 4, 2, fp); |
kayekss | 0:4617bf407fe5 | 95 | width = buf32[0]; |
kayekss | 0:4617bf407fe5 | 96 | height = buf32[1]; |
kayekss | 0:4617bf407fe5 | 97 | |
kayekss | 0:4617bf407fe5 | 98 | // (26 +2) Number of planes (unconfirmed) |
kayekss | 0:4617bf407fe5 | 99 | // (28 +2) Color depth |
kayekss | 0:4617bf407fe5 | 100 | fread(buf16, 2, 2, fp); |
kayekss | 0:4617bf407fe5 | 101 | colorDepth = buf16[1]; |
kayekss | 0:4617bf407fe5 | 102 | if (colorDepth != 24) { |
kayekss | 0:4617bf407fe5 | 103 | status = UnsupportedDepth; |
kayekss | 0:4617bf407fe5 | 104 | fclose(fp); |
kayekss | 0:4617bf407fe5 | 105 | return; |
kayekss | 0:4617bf407fe5 | 106 | } |
kayekss | 0:4617bf407fe5 | 107 | |
kayekss | 0:4617bf407fe5 | 108 | // (30 +4) Compression method (unconfirmed) |
kayekss | 0:4617bf407fe5 | 109 | // (34 +4) Bitmap data size (unconfirmed) |
kayekss | 0:4617bf407fe5 | 110 | // (38 +4) Horizontal resolution (unused) |
kayekss | 0:4617bf407fe5 | 111 | // (42 +4) Vertical resolution (unconfirmed) |
kayekss | 0:4617bf407fe5 | 112 | // (46 +4) Colors (unconfirmed) |
kayekss | 0:4617bf407fe5 | 113 | // (50 +4) Important colors (unconfirmed) |
kayekss | 0:4617bf407fe5 | 114 | fread(buf32, 4, 3, fp); |
kayekss | 0:4617bf407fe5 | 115 | fread(buf32, 4, 3, fp); |
kayekss | 0:4617bf407fe5 | 116 | break; |
kayekss | 0:4617bf407fe5 | 117 | case Windows_V4: |
kayekss | 0:4617bf407fe5 | 118 | case Windows_V5: |
kayekss | 0:4617bf407fe5 | 119 | case OS2_V1: |
kayekss | 0:4617bf407fe5 | 120 | case OS2_V2: |
kayekss | 0:4617bf407fe5 | 121 | case Unknown: |
kayekss | 0:4617bf407fe5 | 122 | status = UnsupportedFormat; |
kayekss | 0:4617bf407fe5 | 123 | fclose(fp); |
kayekss | 0:4617bf407fe5 | 124 | return; |
kayekss | 0:4617bf407fe5 | 125 | } |
kayekss | 0:4617bf407fe5 | 126 | // Seek to image data offset |
kayekss | 0:4617bf407fe5 | 127 | fseek(fp, offset, SEEK_SET); |
kayekss | 0:4617bf407fe5 | 128 | |
kayekss | 0:4617bf407fe5 | 129 | // Calculate data length |
kayekss | 0:4617bf407fe5 | 130 | dataSize = ((colorDepth / 8) * width + 3) / 4 * 4 * height; |
kayekss | 0:4617bf407fe5 | 131 | |
kayekss | 0:4617bf407fe5 | 132 | // Allocate data space |
kayekss | 0:4617bf407fe5 | 133 | data = new uint8_t[dataSize]; |
kayekss | 0:4617bf407fe5 | 134 | |
kayekss | 0:4617bf407fe5 | 135 | // Read bitmap data |
kayekss | 0:4617bf407fe5 | 136 | fread(data, 1, dataSize, fp); |
kayekss | 0:4617bf407fe5 | 137 | |
kayekss | 0:4617bf407fe5 | 138 | fclose(fp); |
kayekss | 0:4617bf407fe5 | 139 | } |
kayekss | 0:4617bf407fe5 | 140 | |
kayekss | 0:4617bf407fe5 | 141 | BMPFile::~BMPFile() { |
kayekss | 0:4617bf407fe5 | 142 | if (data) { |
kayekss | 0:4617bf407fe5 | 143 | delete[] data; |
kayekss | 0:4617bf407fe5 | 144 | } |
kayekss | 0:4617bf407fe5 | 145 | } |