trunk 20080912
[gitenigma.git] / lib / picviewer / bmp.cpp
blobf4fcf3548c830c9b3c2031d5c680a528895ca7aa
1 #ifndef DISABLE_FILE
2 #include <lib/picviewer/format_config.h>
3 #ifdef FBV_SUPPORT_BMP
4 #include <lib/picviewer/pictureviewer.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <fcntl.h>
9 #include <unistd.h>
11 #define BMP_TORASTER_OFFSET 10
12 #define BMP_SIZE_OFFSET 18
13 #define BMP_BPP_OFFSET 28
14 #define BMP_RLE_OFFSET 30
15 #define BMP_COLOR_OFFSET 54
17 #define fill4B(a) ((4 - ((a) % 4 )) & 0x03)
19 struct color {
20 unsigned char red;
21 unsigned char green;
22 unsigned char blue;
25 int fh_bmp_id(const char *name)
27 int fd;
28 char id[2];
30 fd = open(name, O_RDONLY);
31 if (fd == -1)
33 // dbout("fh_bmp_id {\n");
34 return(0);
37 read(fd, id, 2);
38 close(fd);
39 if (id[0] == 'B' && id[1] == 'M' )
41 return(1);
43 return(0);
46 void fetch_pallete(int fd, struct color pallete[], int count)
48 // dbout("fetch_palette {\n");
49 unsigned char buff[4];
50 int i;
52 lseek(fd, BMP_COLOR_OFFSET, SEEK_SET);
53 for (i = 0; i < count; i++)
55 read(fd, buff, 4);
56 pallete[i].red = buff[2];
57 pallete[i].green = buff[1];
58 pallete[i].blue = buff[0];
60 // dbout("fetch_palette }\n");
61 return;
64 int fh_bmp_load(const char *name, unsigned char *buffer, int x, int y)
66 // dbout("fh_bmp_load {\n");
67 int fd, bpp, raster, i, j, k, skip;
68 unsigned char buff[4];
69 unsigned char *wr_buffer = buffer + x * (y - 1) * 3;
70 struct color pallete[256];
72 fd = open(name, O_RDONLY);
73 if (fd == -1)
75 return(FH_ERROR_FILE);
78 if (lseek(fd, BMP_TORASTER_OFFSET, SEEK_SET) == -1)
80 return(FH_ERROR_FORMAT);
83 read(fd, buff, 4);
84 raster = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
86 if (lseek(fd, BMP_BPP_OFFSET, SEEK_SET) == -1)
88 return(FH_ERROR_FORMAT);
91 read(fd, buff, 2);
92 bpp = buff[0] + (buff[1] << 8);
94 switch (bpp)
96 case 1: /* monochrome */
97 skip = fill4B(x / 8 + (x % 8 ? 1 : 0));
98 lseek(fd, raster, SEEK_SET);
100 int bytes = x / 8;
101 if (x % 8 > 0)
102 bytes++;
103 unsigned char * tbuffer = new unsigned char[bytes];
104 if (tbuffer == NULL)
106 eDebug("Error: malloc");
107 return (FH_ERROR_MALLOC);
109 for (i = 0; i < y; i++)
111 read(fd, tbuffer, bytes);
112 for (j = 0; j < x / 8; j++)
114 for (k = 0; k < 8; k++)
116 if (tbuffer[j] & 0x80)
118 *wr_buffer++ = 0xff;
119 *wr_buffer++ = 0xff;
120 *wr_buffer++ = 0xff;
122 else
124 *wr_buffer++ = 0x00;
125 *wr_buffer++ = 0x00;
126 *wr_buffer++ = 0x00;
128 tbuffer[j] = tbuffer[j] << 1;
132 if (x % 8)
134 for (k = 0; k < x % 8; k++)
136 if (tbuffer[j] & 0x80)
138 *wr_buffer++ = 0xff;
139 *wr_buffer++ = 0xff;
140 *wr_buffer++ = 0xff;
142 else
144 *wr_buffer++ = 0x00;
145 *wr_buffer++ = 0x00;
146 *wr_buffer++ = 0x00;
148 tbuffer[j] = tbuffer[j] << 1;
152 if (skip)
154 read(fd, tbuffer, skip);
156 wr_buffer -= x * 6; /* backoff 2 lines - x*2 *3 */
158 delete [] tbuffer;
160 break;
161 case 4: /* 4bit palletized */
163 skip = fill4B(x / 2 + x % 2);
164 fetch_pallete(fd, pallete, 16);
165 lseek(fd, raster, SEEK_SET);
166 unsigned char * tbuffer = new unsigned char[x / 2 + 1];
167 if (tbuffer == NULL)
169 eDebug("Error: malloc");
170 return (FH_ERROR_MALLOC);
172 unsigned char c1,c2;
173 for (i = 0; i < y; i++)
175 read(fd, tbuffer, x / 2 + x % 2);
176 for (j = 0; j < x / 2; j++)
178 c1 = tbuffer[j] >> 4;
179 c2 = tbuffer[j] & 0x0f;
180 *wr_buffer++ = pallete[c1].red;
181 *wr_buffer++ = pallete[c1].green;
182 *wr_buffer++ = pallete[c1].blue;
183 *wr_buffer++ = pallete[c2].red;
184 *wr_buffer++ = pallete[c2].green;
185 *wr_buffer++ = pallete[c2].blue;
187 if (x % 2)
189 c1 = tbuffer[j] >> 4;
190 *wr_buffer++ = pallete[c1].red;
191 *wr_buffer++ = pallete[c1].green;
192 *wr_buffer++ = pallete[c1].blue;
194 if (skip)
196 read(fd, buff, skip);
198 wr_buffer -= x * 6; /* backoff 2 lines - x*2 *3 */
200 delete [] tbuffer;
202 break;
203 case 8: /* 8bit palletized */
205 skip = fill4B(x);
206 fetch_pallete(fd, pallete, 256);
207 lseek(fd, raster, SEEK_SET);
208 unsigned char * tbuffer = new unsigned char[x];
209 if (tbuffer == NULL)
211 eDebug("Error: malloc");
212 return (FH_ERROR_MALLOC);
214 for (i = 0; i < y; i++)
216 read(fd, tbuffer, x);
217 for (j = 0; j < x; j++) {
218 wr_buffer[j * 3] = pallete[tbuffer[j]].red;
219 wr_buffer[j * 3 + 1] = pallete[tbuffer[j]].green;
220 wr_buffer[j * 3 + 2] = pallete[tbuffer[j]].blue;
222 if (skip)
224 read(fd, buff, skip);
226 wr_buffer -= x * 3; /* backoff 2 lines - x*2 *3 */
228 delete [] tbuffer;
230 break;
231 case 16: /* 16bit RGB */
232 return(FH_ERROR_FORMAT);
233 break;
234 case 24: /* 24bit RGB */
235 skip = fill4B(x * 3);
236 lseek(fd, raster, SEEK_SET);
237 unsigned char c;
238 for (i = 0; i < y; i++)
240 read(fd, wr_buffer, x * 3);
241 for (j = 0; j < x * 3 ; j = j + 3)
243 c = wr_buffer[j];
244 wr_buffer[j] = wr_buffer[j + 2];
245 wr_buffer[j + 2] = c;
247 if (skip)
249 read(fd, buff, skip);
251 wr_buffer -= x * 3; // backoff 1 lines - x*3
253 break;
254 default:
255 return(FH_ERROR_FORMAT);
258 close(fd);
259 // dbout("fh_bmp_load }\n");
260 return(FH_ERROR_OK);
262 int fh_bmp_getsize(const char *name, int *x, int *y, int wanted_width, int wanted_height)
264 // dbout("fh_bmp_getsize {\n");
265 int fd;
266 unsigned char size[4];
268 fd = open(name, O_RDONLY);
269 if (fd == -1)
271 return(FH_ERROR_FILE);
273 if (lseek(fd, BMP_SIZE_OFFSET, SEEK_SET) == -1) {
274 return(FH_ERROR_FORMAT);
277 read(fd, size, 4);
278 *x = size[0] + (size[1] << 8) + (size[2] << 16) + (size[3] << 24);
279 // *x-=1;
280 read(fd, size, 4);
281 *y = size[0] + (size[1] << 8) + (size[2] << 16) + (size[3] << 24);
283 close(fd);
284 // dbout("fh_bmp_getsize }\n");
285 return(FH_ERROR_OK);
287 #endif
288 #endif