1 | /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
---|
2 | #include <stdio.h> |
---|
3 | #include <memory.h> |
---|
4 | #include <stdlib.h> |
---|
5 | |
---|
6 | #include "BMPImageLoaderImpl.h" |
---|
7 | #include "Image.h" |
---|
8 | #include "Trace.h" |
---|
9 | |
---|
10 | BMPImageLoaderImpl::BMPImageLoaderImpl() |
---|
11 | { |
---|
12 | } |
---|
13 | |
---|
14 | BMPImageLoaderImpl::~BMPImageLoaderImpl() |
---|
15 | { |
---|
16 | } |
---|
17 | |
---|
18 | // I referred to cjbackhouse@hotmail.com www.backhouse.tk |
---|
19 | Image *BMPImageLoaderImpl::load(const char *fileName) |
---|
20 | { |
---|
21 | TRACE("BMP loader\n"); |
---|
22 | Image *image = NULL; |
---|
23 | |
---|
24 | TRACE("opening image file \"%s\"\n", fileName); |
---|
25 | FILE *f = fopen(fileName, "rb"); |
---|
26 | |
---|
27 | if (!f) { |
---|
28 | TRACE("File not found\n"); |
---|
29 | return 0; |
---|
30 | } |
---|
31 | |
---|
32 | char header[54]; |
---|
33 | if (fread(&header, 54, 1, f) != 1) { |
---|
34 | TRACE("can't read header of BMP file\n"); |
---|
35 | return 0; |
---|
36 | } |
---|
37 | |
---|
38 | if (header[0] != 'B' || header[1] != 'M') { |
---|
39 | TRACE("File is not BMP format\n"); |
---|
40 | return 0; |
---|
41 | } |
---|
42 | |
---|
43 | //it seems gimp sometimes makes its headers small, so we have to do |
---|
44 | //this. hence all the fseeks |
---|
45 | int offset = *(unsigned int*)(header+10); |
---|
46 | |
---|
47 | const unsigned int width = *(int*)(header+18); |
---|
48 | const unsigned int height = *(int*)(header+22); |
---|
49 | |
---|
50 | int bits = int(header[28]); //colourdepth |
---|
51 | |
---|
52 | TRACE("image width = %d height = %d bits=%d\n", width, height, bits); |
---|
53 | |
---|
54 | image = new Image(width, height, _targetImageFormat, |
---|
55 | Image::IMG_UNSIGNED_BYTE, NULL); |
---|
56 | |
---|
57 | TRACE("image created\n"); |
---|
58 | |
---|
59 | unsigned char *bytes = (unsigned char *)image->getImageBuffer(); |
---|
60 | memset(bytes, 0, sizeof(unsigned char) * width * height * _targetImageFormat); |
---|
61 | |
---|
62 | TRACE("reset image buffer\n"); |
---|
63 | |
---|
64 | unsigned int x, y; |
---|
65 | unsigned char cols[256*4]; //colourtable |
---|
66 | switch (bits) { |
---|
67 | case 24: |
---|
68 | fseek(f, offset, SEEK_SET); |
---|
69 | if (_targetImageFormat == Image::IMG_RGB) { |
---|
70 | if (fread(bytes, width*height*3, 1, f) != 1) { |
---|
71 | ERROR("can't read image data\n"); |
---|
72 | } |
---|
73 | for (x = 0; x < width*height*3; x += 3) { //except the format is BGR, grr |
---|
74 | unsigned char temp = bytes[x]; |
---|
75 | bytes[x] = bytes[x+2]; |
---|
76 | bytes[x+2] = temp; |
---|
77 | } |
---|
78 | } else if (_targetImageFormat == Image::IMG_RGBA) { |
---|
79 | unsigned char *buff = (unsigned char*)malloc(width * height * sizeof(unsigned char) * 3); |
---|
80 | if (fread(buff, width*height*3, 1, f) != 1) { |
---|
81 | ERROR("can't read BMP image data\n"); |
---|
82 | } |
---|
83 | for (x = 0, y = 0; x < width*height*3; x += 3, y += 4) { //except the format is BGR, grr |
---|
84 | bytes[y] = buff[x+2]; |
---|
85 | bytes[y+1] = buff[x+1]; |
---|
86 | bytes[y+2] = buff[x]; |
---|
87 | bytes[y+3] = 255; |
---|
88 | } |
---|
89 | free(buff); |
---|
90 | } |
---|
91 | break; |
---|
92 | case 32: |
---|
93 | fseek(f, offset, SEEK_SET); |
---|
94 | if (_targetImageFormat == Image::IMG_RGBA) { |
---|
95 | if (fread(bytes, width*height*4, 1, f) != 1) { |
---|
96 | ERROR("can't read image data\n"); |
---|
97 | } |
---|
98 | for (x = 0; x < width*height*4; x += 4) { //except the format is BGR, grr |
---|
99 | unsigned char temp = bytes[x]; |
---|
100 | bytes[x] = bytes[x+2]; |
---|
101 | bytes[x+2] = temp; |
---|
102 | } |
---|
103 | } else if (_targetImageFormat == Image::IMG_RGB) { |
---|
104 | unsigned char *buff = (unsigned char*)malloc(width * height * sizeof(unsigned char) * 4); |
---|
105 | if (fread(buff, width*height*4, 1, f) != 1) { |
---|
106 | ERROR("can't read BMP image data\n"); |
---|
107 | } |
---|
108 | for (x = 0, y = 0; x < width*height*4; x += 4, y += 3) { //except the format is BGR, grr |
---|
109 | bytes[y] = buff[x+2]; |
---|
110 | bytes[y+1] = buff[x+1]; |
---|
111 | bytes[y+2] = buff[x]; |
---|
112 | } |
---|
113 | free(buff); |
---|
114 | } |
---|
115 | break; |
---|
116 | case 8: |
---|
117 | if (fread(cols, 256 * 4, 1, f) != 1) { |
---|
118 | ERROR("can't read colortable from BMP file\n"); |
---|
119 | } |
---|
120 | fseek(f,offset,SEEK_SET); |
---|
121 | for (y = 0; y < height; ++y) { //(Notice 4bytes/col for some reason) |
---|
122 | for (x = 0; x < width; ++x) { |
---|
123 | unsigned char byte; |
---|
124 | if (fread(&byte, 1, 1, f) != 1) { |
---|
125 | ERROR("error reading BMP file\n"); |
---|
126 | } |
---|
127 | for (int c = 0; c < 3; ++c) { |
---|
128 | //bytes[(y*width+x)*3+c] = cols[byte*4+2-c]; //and look up in the table |
---|
129 | bytes[(y*width+x)*_targetImageFormat + c] = cols[byte*4+2-c]; //and look up in the table |
---|
130 | } |
---|
131 | if (_targetImageFormat == Image::IMG_RGBA) { |
---|
132 | bytes[(y*width+x)*_targetImageFormat + 3] = 255; |
---|
133 | } |
---|
134 | } |
---|
135 | } |
---|
136 | break; |
---|
137 | } |
---|
138 | |
---|
139 | TRACE("image initialized\n"); |
---|
140 | return image; |
---|
141 | } |
---|