1
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <math.h>
7
8 #include "../compatibility/tnz4.h"
9 #include "../compatibility/inforegion.h"
10 #include "filebmp.h"
11 /*
12 typedef unsigned long ULONG;
13 typedef unsigned short USHORT;
14 typedef unsigned char UCHAR;
15 typedef unsigned int UINT;
16 typedef void IMAGERGB;
17 typedef struct {USHORT m,b,g,r;} SPIXEL;
18 #define CASE break; case
19 #define __OR ; case
20 #define DEFAULT break; default
21 #define TRUE 1
22 #define FALSE 0
23 #define NIL (void*)0
24 */
25
26 typedef enum {
27 BMP_NONE,
28 BMP_BW,
29 BMP_GREY16,
30 BMP_GREY16C,
31 BMP_GREY256,
32 BMP_GREY256C,
33 BMP_CMAPPED16,
34 BMP_CMAPPED16C,
35 BMP_CMAPPED256,
36 BMP_CMAPPED256C,
37 BMP_RGB
38
39 } BMP_SUBTYPE;
40
41 /*
42 typedef struct bmpimage {
43 int xsize,ysize;
44 LPIXEL *buffer;
45 BMP_SUBTYPE type;
46 } IMAGE;
47 */
48
49 #define UNUSED_REDUCE_COLORS
50
51 /*---------------------------------------------------------------------------*/
52 /*-- Defines ----------------------------------------------------------------*/
53
54 #define BMP_BI_RGB 0
55 #define BMP_BI_RLE8 1
56 #define BMP_BI_RLE4 2
57
58 #define BMP_WIN_OS2_OLD 12
59 #define BMP_WIN_NEW 40
60 #define BMP_OS2_NEW 64
61
62 #define BMP_READ_INFO 1
63 #define BMP_READ_IMAGE 2
64
65 #define BMP_FERROR(fp) (ferror(fp) || feof(fp))
66
67 #define BMP_RMAP(x) (x & 0xe0) | ((x & 0xe0) >> 3) | ((x & 0xc0) >> 6)
68 #define BMP_GMAP(x) ((x & 0x1c) << 3) | (x & 0x1c) | ((x & 0x18) >> 3)
69 #define BMP_BMAP(x) \
70 ((x & 0x03) << 6) | ((x & 0x03) << 4) | ((x & 0x03) << 2) | (x & 0x03)
71
72 #define BMP_RMAP16(x) \
73 ((x & 0xc0) << 0) | ((x & 0xc0) >> 2) | ((x & 0xc0) >> 4) | ((x & 0xc0) >> 6)
74 #define BMP_GMAP16(x) \
75 ((x & 0x60) << 1) | ((x & 0x60) >> 1) | ((x & 0x60) >> 3) | ((x & 0x60) >> 5)
76 #define BMP_BMAP16(x) \
77 ((x & 0x30) << 2) | ((x & 0x30) << 0) | ((x & 0x30) >> 2) | ((x & 0x30) >> 4)
78
79 #define BMP_CUT(a, b, c) \
80 { \
81 if (a < b) \
82 a = b; \
83 else if (a > c) \
84 a = c; \
85 }
86
87 #define BMP_REDUCE_COLORS(r, g, b) \
88 ((r & 0xe0) | ((g & 0xe0) >> 3) | ((b & 0xc0) >> 6))
89
90 #define BMP_ADD_ERROR(pix, weight) \
91 { \
92 tmp = (pix).r + ((r1 * weight) >> 4); \
93 BMP_CUT(tmp, 0, 255); \
94 (pix).r = tmp; \
95 tmp = (pix).g + ((g1 * weight) >> 4); \
96 BMP_CUT(tmp, 0, 255); \
97 (pix).g = tmp; \
98 tmp = (pix).b + ((b1 * weight) >> 4); \
99 BMP_CUT(tmp, 0, 255); \
100 (pix).b = tmp; \
101 }
102
103 #define BMP_ADD_ERROR_BW(pix, error) \
104 { \
105 tmp = (pix).r + (error); \
106 BMP_CUT(tmp, 0, 255); \
107 (pix).r = tmp; \
108 tmp = (pix).g + (error); \
109 BMP_CUT(tmp, 0, 255); \
110 (pix).g = tmp; \
111 tmp = (pix).b + (error); \
112 BMP_CUT(tmp, 0, 255); \
113 (pix).b = tmp; \
114 }
115
116 /*---------------------------------------------------------------------------*/
117 /*-- Structures and Enums ---------------------------------------------------*/
118
119 typedef struct {
120 UINT bfSize;
121 UINT bfOffBits;
122 UINT biSize;
123 UINT biWidth;
124 UINT biHeight;
125 UINT biPlanes;
126 UINT biBitCount;
127 UINT biCompression;
128 UINT biSizeImage;
129 UINT biXPelsPerMeter;
130 UINT biYPelsPerMeter;
131 UINT biClrUsed;
132 UINT biClrImportant;
133 UINT biFilesize;
134 UINT biPad;
135
136 } BMP_HEADER;
137
138 /*---------------------------------------------------------------------------*/
139 /*-- Prototypes -------------------------------------------------------------*/
140
141 int load_bmp_header(FILE *fp, BMP_HEADER **pHd);
142 int write_bmp_header(FILE *fp, BMP_HEADER *hd);
143 void release_bmp_header(BMP_HEADER *hd);
144
145 int write_bmp_palette(FILE *fp, int nc, UCHAR *b, UCHAR *g, UCHAR *r);
146
147 int make_bmp_palette(int colors, int grey, UCHAR *r, UCHAR *g, UCHAR *b);
148
149 BMP_SUBTYPE bmp_get_colorstyle(IMAGE *img);
150
151 int error_checking_bmp(BMP_HEADER *hd);
152
153 int read_bmp_line(FILE *fp, void *line, UINT w, UINT h, UCHAR **map,
154 BMP_SUBTYPE type);
155
156 int write_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR *map,
157 BMP_SUBTYPE type);
158
159 int skip_bmp_lines(FILE *fp, UINT w, UINT rows, int whence, BMP_SUBTYPE type);
160
161 /*---------------------------------------------------------------------------*/
162 /*-- Local Prototypes -------------------------------------------------------*/
163
164 static UINT getshort(FILE *fp);
165 static UINT getint(FILE *fp);
166 static void putshort(FILE *fp, int value);
167 static void putint(FILE *fp, int value);
168
169 static int img_read_bmp_generic(const MYSTRING fname, int type, IMAGE **);
170 #ifndef UNUSED_REDUCE_COLORS
171 static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, UCHAR *rmap,
172 UCHAR *gmap, UCHAR *bmap, int nc);
173
174 #endif
175
176 static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g,
177 UCHAR *b);
178 static int loadBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r,
179 UCHAR *g, UCHAR *b);
180 static int loadBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r,
181 UCHAR *g, UCHAR *b);
182 static int loadBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT h);
183
184 static int writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *map);
185 static int writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *map);
186 static int writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *map);
187 static int writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *map);
188 static int writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *map);
189 static int writeBMP24(FILE *fp, UCHAR *pic24, UINT w, UINT h, UCHAR *map);
190
191 static int load_lineBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map);
192 static int load_lineBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map);
193 static int load_lineBMPC4(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map);
194 static int load_lineBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map);
195 static int load_lineBMPC8(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map);
196 static int load_lineBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT padb);
197
198 static int line_writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT padw,
199 UCHAR *pc2nc);
200 static int line_writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT padw,
201 UCHAR *pc2nc);
202 static int line_writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT row,
203 UCHAR *pc2nc);
204 static int line_writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT padw,
205 UCHAR *pc2nc);
206 static int line_writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT row,
207 UCHAR *pc2nc);
208 static int line_writeBMP24(FILE *fp, LPIXEL *pp, UINT w, UINT padb);
209
210 static int skip_rowsBMP1(FILE *fp, UINT w, UINT pad, UINT rows, int whence);
211 static int skip_rowsBMP4(FILE *fp, UINT w, UINT pad, UINT rows, int whence);
212 static int skip_rowsBMPC4(FILE *fp, UINT rows);
213 static int skip_rowsBMP8(FILE *fp, UINT w, UINT pad, UINT rows, int whence);
214 static int skip_rowsBMPC8(FILE *fp, UINT rows);
215 static int skip_rowsBMP24(FILE *fp, UINT w, UINT pad, UINT rows, int whence);
216
217 #define BMP_DEBUG 0
218 #define __BMP_WRITE_LINE_BY_LINE
219 #define __BMP_READ_LINE_BY_LINE
220
221 /*---------------------------------------------------------------------------*/
read_bmp_line(FILE * fp,void * line_buffer,UINT w,UINT row,UCHAR ** map,BMP_SUBTYPE type)222 int read_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR **map,
223 BMP_SUBTYPE type)
224 /*---------------------------------------------------------------------------*/
225 {
226 LPIXEL *pic = (LPIXEL *)line_buffer;
227 unsigned int pad;
228 int rv = 0;
229
230 switch (type) {
231 case BMP_BW:
232 pad = ((w + 31) / 32) * 32;
233 rv = load_lineBMP1(fp, pic, w, pad, map);
234 CASE BMP_GREY16 : __OR BMP_CMAPPED16 : pad = ((w + 7) / 8) * 8;
235 rv = load_lineBMP4(fp, pic, w, pad, map);
236 CASE BMP_GREY16C : __OR BMP_CMAPPED16C
237 : rv = load_lineBMPC4(fp, pic, w, row, map);
238 if (rv == -1)
239 rv = 1;
240 else if (rv == -2)
241 rv = 0;
242 else if (rv == -3)
243 rv = 0;
244 else
245 rv = 0;
246 CASE BMP_GREY256 : __OR BMP_CMAPPED256 : pad = ((w + 3) / 4) * 4;
247 rv = load_lineBMP8(fp, pic, w, pad, map);
248 CASE BMP_GREY256C : __OR BMP_CMAPPED256C
249 : rv = load_lineBMPC8(fp, pic, w, row, map);
250 if (rv == -1)
251 rv = 1;
252 else if (rv == -2)
253 rv = 0;
254 else if (rv == -3)
255 rv = 0;
256 else
257 rv = 0;
258 CASE BMP_RGB : pad = (4 - ((w * 3) % 4)) & 0x03;
259 rv = load_lineBMP24(fp, pic, w, pad);
260 DEFAULT:
261 break;
262 }
263
264 return !rv; /* return 0 for unsuccess */
265 }
266
267 /*---------------------------------------------------------------------------*/
write_bmp_line(FILE * fp,void * line_buffer,UINT w,UINT row,UCHAR * map,BMP_SUBTYPE type)268 int write_bmp_line(FILE *fp, void *line_buffer, UINT w, UINT row, UCHAR *map,
269 BMP_SUBTYPE type)
270 /*---------------------------------------------------------------------------*/
271 {
272 UCHAR *pic = (UCHAR *)line_buffer;
273 LPIXEL *p24 = (LPIXEL *)line_buffer;
274 unsigned int pad;
275 int rv = 0;
276
277 switch (type) {
278 case BMP_BW:
279 pad = ((w + 31) / 32) * 32;
280 rv = line_writeBMP1(fp, pic, w, pad, map);
281 CASE BMP_GREY16 : __OR BMP_CMAPPED16 : pad = ((w + 7) / 8) * 8;
282 rv = line_writeBMP4(fp, pic, w, pad, map);
283 CASE BMP_GREY16C : __OR BMP_CMAPPED16C
284 : rv = line_writeBMPC4(fp, pic, w, row, map);
285 CASE BMP_GREY256 : __OR BMP_CMAPPED256 : pad = ((w + 3) / 4) * 4;
286 rv = line_writeBMP8(fp, pic, w, pad, map);
287 CASE BMP_GREY256C : __OR BMP_CMAPPED256C
288 : rv = line_writeBMPC8(fp, pic, w, row, map);
289 CASE BMP_RGB : pad = (4 - ((w * 3) % 4)) & 0x03;
290 rv = line_writeBMP24(fp, p24, w, pad);
291 DEFAULT:
292 break;
293 }
294
295 return rv; /* 0 for unsuccess */
296 }
297
298 /*---------------------------------------------------------------------------*/
skip_bmp_lines(FILE * fp,UINT w,UINT rows,int whence,BMP_SUBTYPE type)299 int skip_bmp_lines(FILE *fp, UINT w, UINT rows, int whence, BMP_SUBTYPE type)
300 /*---------------------------------------------------------------------------*/
301 {
302 unsigned int pad;
303 int rv = 0;
304
305 switch (type) {
306 case BMP_BW:
307 pad = ((w + 31) / 32) * 32;
308 rv = skip_rowsBMP1(fp, w, pad, rows, whence);
309 CASE BMP_GREY16 : __OR BMP_CMAPPED16 : pad = ((w + 7) / 8) * 8;
310 rv = skip_rowsBMP4(fp, w, pad, rows, whence);
311 CASE BMP_GREY16C : __OR BMP_CMAPPED16C : rv = skip_rowsBMPC4(fp, rows);
312 CASE BMP_GREY256 : __OR BMP_CMAPPED256 : pad = ((w + 3) / 4) * 4;
313 rv = skip_rowsBMP8(fp, w, pad, rows, whence);
314 CASE BMP_GREY256C : __OR BMP_CMAPPED256C : rv = skip_rowsBMPC8(fp, rows);
315 CASE BMP_RGB : pad = (4 - ((w * 3) % 4)) & 0x03;
316 rv = skip_rowsBMP24(fp, w, pad, rows, whence);
317 DEFAULT:
318 break;
319 }
320
321 return !rv;
322 }
323
324 /*---------------------------------------------------------------------------*/
error_checking_bmp(BMP_HEADER * hd)325 int error_checking_bmp(BMP_HEADER *hd)
326 /*---------------------------------------------------------------------------*/
327 {
328 /* error checking */
329 if ((hd->biBitCount != 1 && hd->biBitCount != 4 && hd->biBitCount != 8 &&
330 hd->biBitCount != 24) ||
331 hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) {
332 return UNSUPPORTED_BMP_FORMAT;
333 }
334
335 /* error checking */
336 if (((hd->biBitCount == 1 || hd->biBitCount == 24) &&
337 hd->biCompression != BMP_BI_RGB) ||
338 (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) ||
339 (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) {
340 return UNSUPPORTED_BMP_FORMAT;
341 }
342
343 return OK;
344 }
345
346 /*---------------------------------------------------------------------------*/
load_bmp_header(FILE * fp,BMP_HEADER ** header)347 int load_bmp_header(FILE *fp, BMP_HEADER **header)
348 /*---------------------------------------------------------------------------*/
349 {
350 BMP_HEADER *hd = NULL;
351 int c, c1;
352
353 *header = NULL;
354
355 hd = (BMP_HEADER *)calloc((size_t)1, sizeof(BMP_HEADER));
356 if (!hd) return OUT_OF_MEMORY;
357
358 /* figure out the file size */
359 fseek(fp, 0L, SEEK_END);
360 hd->biFilesize = ftell(fp);
361 fseek(fp, 0L, 0);
362
363 /* read the file type (first two bytes) */
364 c = getc(fp);
365 c1 = getc(fp);
366 if (c != 'B' || c1 != 'M') {
367 free(hd);
368 return UNSUPPORTED_BMP_FORMAT;
369 }
370
371 hd->bfSize = getint(fp);
372
373 /* reserved and ignored */
374 getshort(fp);
375 getshort(fp);
376
377 hd->bfOffBits = getint(fp);
378 hd->biSize = getint(fp);
379
380 if (hd->biSize == BMP_WIN_NEW || hd->biSize == BMP_OS2_NEW) {
381 hd->biWidth = getint(fp);
382 hd->biHeight = getint(fp);
383 hd->biPlanes = getshort(fp);
384 hd->biBitCount = getshort(fp);
385 hd->biCompression = getint(fp);
386 hd->biSizeImage = getint(fp);
387 hd->biXPelsPerMeter = getint(fp);
388 hd->biYPelsPerMeter = getint(fp);
389 hd->biClrUsed = getint(fp);
390 hd->biClrImportant = getint(fp);
391 } else /* old bitmap format */
392 {
393 hd->biWidth = getshort(fp);
394 hd->biHeight = getshort(fp);
395 hd->biPlanes = getshort(fp);
396 hd->biBitCount = getshort(fp);
397
398 /* Not in old versions so have to compute them */
399 hd->biSizeImage =
400 (((hd->biPlanes * hd->biBitCount * hd->biWidth) + 31) / 32) * 4 *
401 hd->biHeight;
402
403 hd->biCompression = BMP_BI_RGB;
404 hd->biXPelsPerMeter = 0;
405 hd->biYPelsPerMeter = 0;
406 hd->biClrUsed = 0;
407 hd->biClrImportant = 0;
408 }
409
410 if (BMP_DEBUG) {
411 printf("\nLoadBMP:\tbfSize=%u, bfOffBits=%u\n", hd->bfSize, hd->bfOffBits);
412 printf("\t\tbiSize=%u, biWidth=%u, biHeight=%u, biPlanes=%u\n", hd->biSize,
413 hd->biWidth, hd->biHeight, hd->biPlanes);
414 printf("\t\tbiBitCount=%u, biCompression=%u, biSizeImage=%u\n",
415 hd->biBitCount, hd->biCompression, hd->biSizeImage);
416 printf("\t\tbiX,YPelsPerMeter=%u,%u biClrUsed=%u, biClrImp=%u\n",
417 hd->biXPelsPerMeter, hd->biYPelsPerMeter, hd->biClrUsed,
418 hd->biClrImportant);
419 }
420
421 if (BMP_FERROR(fp)) {
422 free(hd);
423 return UNEXPECTED_EOF;
424 }
425
426 *header = hd;
427 return OK;
428 }
429
430 /*---------------------------------------------------------------------------*/
release_bmp_header(BMP_HEADER * hd)431 void release_bmp_header(BMP_HEADER *hd)
432 /*---------------------------------------------------------------------------*/
433 {
434 if (hd) free(hd);
435 }
436
437 #ifndef __LIBSIMAGE__
438
439 /*---------------------------------------------------------------------------*/
img_read_bmp(const MYSTRING fname,IMAGE ** pimg)440 int img_read_bmp(const MYSTRING fname, IMAGE **pimg)
441 /*---------------------------------------------------------------------------*/
442 {
443 return img_read_bmp_generic(fname, BMP_READ_IMAGE, pimg);
444 }
445
446 /*---------------------------------------------------------------------------*/
img_read_bmp_generic(const MYSTRING fname,int type,IMAGE ** pimg)447 static int img_read_bmp_generic(const MYSTRING fname, int type, IMAGE **pimg)
448 /*---------------------------------------------------------------------------*/
449 {
450 int retCode = OK;
451
452 UCHAR r[256], g[256], b[256];
453 BMP_HEADER *hd = NULL;
454 IMAGE *img = NULL;
455
456 int rv, c, i;
457 LPIXEL *pic;
458 FILE *fp;
459
460 *pimg = 0;
461
462 /* returns 'NULL' on unsuccess */
463
464 pic = (LPIXEL *)NULL;
465
466 /* open image file */
467 fp = _wfopen(fname, L"rb");
468 if (!fp) return CANT_OPEN_FILE;
469
470 /* load up the image header */
471 retCode = load_bmp_header(fp, &hd);
472 if (retCode != OK) goto ERROR;
473
474 /* error checking */
475 if ((hd->biBitCount != 1 && hd->biBitCount != 4 && hd->biBitCount != 8 &&
476 hd->biBitCount != 24) ||
477 hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) {
478 retCode = UNSUPPORTED_BMP_FORMAT;
479 goto ERROR;
480 }
481
482 /* error checking */
483 if (((hd->biBitCount == 1 || hd->biBitCount == 24) &&
484 hd->biCompression != BMP_BI_RGB) ||
485 (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) ||
486 (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) {
487 retCode = UNSUPPORTED_BMP_FORMAT;
488 goto ERROR;
489 }
490
491 img = new_img();
492 img->type = TOONZRGB;
493
494 if (type == BMP_READ_INFO) {
495 fclose(fp);
496 img->xSBsize = img->xsize = hd->biWidth;
497 img->ySBsize = img->ysize = hd->biHeight;
498 release_bmp_header(hd);
499 *pimg = img;
500 return OK;
501 }
502
503 allocate_pixmap(img, (int)hd->biWidth, (int)hd->biHeight);
504
505 /* hd->biPad; */
506 if (hd->biSize != BMP_WIN_OS2_OLD) {
507 /* skip ahead to colormap, using biSize */
508 c = hd->biSize - 40; /* 40 bytes read from biSize to biClrImportant */
509 for (i = 0; i < c; i++) getc(fp);
510 hd->biPad = hd->bfOffBits - (hd->biSize + 14);
511 }
512
513 /* load up colormap, if any */
514 if (hd->biBitCount != 24) {
515 int i, cmaplen;
516
517 /*cmaplen = (hd->biClrUsed) ? hd->biClrUsed : 1 << hd->biBitCount;*/
518 if (hd->biClrUsed)
519 cmaplen = hd->biClrUsed;
520 else
521 cmaplen = 1 << hd->biBitCount;
522
523 for (i = 0; i < cmaplen; i++) {
524 b[i] = getc(fp);
525 g[i] = getc(fp);
526 r[i] = getc(fp);
527 if (hd->biSize != BMP_WIN_OS2_OLD) {
528 getc(fp);
529 hd->biPad -= 4;
530 }
531 }
532
533 if (BMP_FERROR(fp)) {
534 retCode = UNEXPECTED_EOF;
535 goto ERROR;
536 }
537
538 if (BMP_DEBUG) {
539 printf("LoadBMP: BMP colormap: (RGB order)\n");
540 for (i = 0; i < cmaplen; i++) printf("%02x%02x%02x ", r[i], g[i], b[i]);
541 printf("\n\n");
542 }
543 }
544
545 if (hd->biSize != BMP_WIN_OS2_OLD) {
546 /* Waste any unused bytes between the colour map (if present)
547 and the start of the actual bitmap data.
548 */
549
550 while (hd->biPad > 0) {
551 (void)getc(fp);
552 hd->biPad--;
553 }
554 }
555
556 /* create 32 bit image buffer */
557
558 pic = (LPIXEL *)img->buffer;
559
560 /* load up the image */
561 switch (hd->biBitCount) {
562 case 1:
563 rv = loadBMP1(fp, pic, hd->biWidth, hd->biHeight, r, g, b);
564 CASE 4 : rv = loadBMP4(fp, pic, hd->biWidth, hd->biHeight,
565 hd->biCompression, r, g, b);
566 CASE 8 : rv = loadBMP8(fp, pic, hd->biWidth, hd->biHeight,
567 hd->biCompression, r, g, b);
568 CASE 24 : rv = loadBMP24(fp, pic, hd->biWidth, hd->biHeight);
569 DEFAULT:
570 retCode = UNSUPPORTED_BMP_FORMAT;
571 goto ERROR;
572 }
573
574 if (rv) {
575 retCode = UNEXPECTED_EOF;
576 goto ERROR;
577 }
578
579 fclose(fp);
580 release_bmp_header(hd);
581
582 *pimg = img;
583 return OK;
584
585 ERROR:
586
587 fclose(fp);
588 release_bmp_header(hd);
589
590 if (img) {
591 TFREE(img->buffer)
592 TFREE(img)
593 }
594
595 return retCode;
596 }
597
598 #endif /* __LIBSIMAGE__ */
599
img_read_bmp_region(const MYSTRING fname,IMAGE ** pimg,int x1,int y1,int x2,int y2,int scale)600 static int img_read_bmp_region(const MYSTRING fname, IMAGE **pimg, int x1,
601 int y1, int x2, int y2, int scale) {
602 UCHAR r[256], g[256], b[256] /* ,*map[3] */;
603 LPIXEL *line = NULL;
604 UINT line_size = 0;
605 BMP_HEADER *hd = NULL;
606 EXT_INFO_REGION info;
607 BMP_SUBTYPE subtype;
608 LPIXEL *pic, *appo;
609 IMAGE *img = NULL;
610 UINT start_offset;
611 UINT c, i, j;
612 char buf[512];
613 FILE *fp;
614 UINT pad;
615 enum BMP_ERROR_CODE bmp_error = OK;
616
617 /* initialize some variables */
618 i = pad = 0;
619
620 /* returns 'NULL' on unsuccess */
621 pic = (LPIXEL *)NULL;
622
623 /* open image file */
624 fp = _wfopen(fname, L"rb");
625 if (!fp) {
626 return CANT_OPEN_FILE;
627 }
628
629 /* load up the image header */
630 load_bmp_header(fp, &hd);
631 if (!hd) goto ERROR;
632
633 /* error checking */
634 if ((hd->biBitCount != 1 && hd->biBitCount != 4 && hd->biBitCount != 8 &&
635 hd->biBitCount != 24) ||
636 hd->biPlanes != 1 || hd->biCompression > BMP_BI_RLE4) {
637 snprintf(buf, sizeof(buf),
638 "Bogus BMP File! (bitCount=%d, Planes=%d, Compression=%d)",
639 hd->biBitCount, hd->biPlanes, hd->biCompression);
640
641 bmp_error = UNSUPPORTED_BMP_FORMAT;
642 goto ERROR;
643 }
644
645 /* error checking */
646 if (((hd->biBitCount == 1 || hd->biBitCount == 24) &&
647 hd->biCompression != BMP_BI_RGB) ||
648 (hd->biBitCount == 4 && hd->biCompression == BMP_BI_RLE8) ||
649 (hd->biBitCount == 8 && hd->biCompression == BMP_BI_RLE4)) {
650 snprintf(buf, sizeof(buf),
651 "Bogus BMP File! (bitCount=%d, Compression=%d)",
652 hd->biBitCount, hd->biCompression);
653 bmp_error = UNSUPPORTED_BMP_FORMAT;
654 goto ERROR;
655 }
656
657 img = new_img();
658
659 img->type = TOONZRGB;
660
661 img->xsize = hd->biWidth;
662 img->ysize = hd->biHeight;
663 img->xSBsize = hd->biWidth;
664 img->ySBsize = hd->biHeight;
665 img->x_dpi = (double)(hd->biXPelsPerMeter / 39);
666 img->y_dpi = (double)(hd->biYPelsPerMeter / 39);
667
668 hd->biPad = 0;
669 if (hd->biSize != BMP_WIN_OS2_OLD) {
670 /* skip ahead to colormap, using biSize */
671 c = hd->biSize - 40; /* 40 bytes read from biSize to biClrImportant */
672 for (i = 0; i < c; i++) getc(fp);
673 hd->biPad = hd->bfOffBits - (hd->biSize + 14);
674 }
675
676 /* load up colormap, if any */
677 if (hd->biBitCount != 24) {
678 int i, cmaplen;
679
680 /*cmaplen = (hd->biClrUsed) ? hd->biClrUsed : 1 << hd->biBitCount;*/
681 if (hd->biClrUsed)
682 cmaplen = hd->biClrUsed;
683 else
684 cmaplen = hd->biBitCount;
685
686 for (i = 0; i < cmaplen; i++) {
687 b[i] = getc(fp);
688 g[i] = getc(fp);
689 r[i] = getc(fp);
690 if (hd->biSize != BMP_WIN_OS2_OLD) {
691 getc(fp);
692 hd->biPad -= 4;
693 }
694 }
695
696 if (BMP_FERROR(fp)) {
697 bmp_error = UNEXPECTED_EOF;
698 goto ERROR;
699 }
700
701 if (BMP_DEBUG) {
702 printf("LoadBMP: BMP colormap: (RGB order)\n");
703 for (i = 0; i < cmaplen; i++) printf("%02x%02x%02x ", r[i], g[i], b[i]);
704 printf("\n\n");
705 }
706 }
707
708 if (hd->biSize != BMP_WIN_OS2_OLD) {
709 /* Waste any unused bytes between the colour map (if present)
710 and the start of the actual bitmap data.
711 */
712
713 while (hd->biPad > 0) {
714 (void)getc(fp);
715 hd->biPad--;
716 }
717 }
718
719 /* get information about the portion of the image to load */
720 get_info_region(&info, x1, y1, x2, y2, scale, (int)hd->biWidth,
721 (int)hd->biHeight, TNZ_BOTLEFT);
722
723 /* create 32 bit image buffer */
724 if (!allocate_pixmap(img, info.xsize, info.ysize)) {
725 bmp_error = OUT_OF_MEMORY;
726 goto ERROR;
727 }
728
729 start_offset = info.y_offset * info.xsize + info.x_offset;
730 pic = ((LPIXEL *)img->buffer) + start_offset;
731
732 if (line_size < hd->biWidth + 32) {
733 line_size = hd->biWidth + 32;
734 if (!line)
735 TCALLOC((LPIXEL *)line, (size_t)line_size)
736 else
737 TREALLOC(line, line_size)
738 }
739 if (!line) {
740 bmp_error = OUT_OF_MEMORY;
741 goto ERROR;
742 }
743
744 switch (hd->biBitCount) {
745 case 1:
746 pad = ((hd->biWidth + 31) / 32) * 32;
747 CASE 4 : pad = ((hd->biWidth + 7) / 8) * 8;
748 CASE 8 : pad = ((hd->biWidth + 3) / 4) * 4;
749 CASE 24 : pad = (4 - ((hd->biWidth * 3) % 4)) & 0x03;
750 DEFAULT:
751 /* segnala errore ed esci */
752 break;
753 }
754
755 subtype = bmp_get_colorstyle(img);
756 if (subtype == BMP_NONE) goto ERROR;
757
758 if (info.y_offset > 0) info.scanNrow++;
759 if (info.x_offset > 0) info.scanNcol++;
760
761 /* print_info_region(&info); */
762
763 if (info.startScanRow > 0)
764 skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.startScanRow - 1),
765 (unsigned int)SEEK_CUR, subtype);
766
767 for (i = 0; i < (UINT)info.scanNrow; i++) {
768 if (load_lineBMP24(fp, line, hd->biWidth, pad)) goto ERROR;
769
770 /* QUESTO SWITCH VA AGGIUSTATO!
771 switch (subtype)
772 {
773 CASE BMP_BW:
774 if (load_lineBMP1(fp, line, hd->biWidth, pad, map))
775 goto ERROR;
776 CASE BMP_GREY16:
777 __OR BMP_CMAPPED16:
778 if (load_lineBMP4(fp, line, hd->biWidth, pad, map))
779 goto ERROR;
780 CASE BMP_GREY16C:
781 __OR BMP_CMAPPED16C:
782 if (load_lineBMPC4(fp, line, hd->biWidth, i, map)==-1)
783 goto ERROR;
784 CASE BMP_GREY256:
785 __OR BMP_CMAPPED256:
786 if (load_lineBMP8(fp, line, hd->biWidth, pad, map))
787 goto ERROR;
788 CASE BMP_GREY256C:
789 __OR BMP_CMAPPED256C:
790 if (load_lineBMPC8(fp, line, hd->biWidth, i, map)==-1)
791 goto ERROR;
792 CASE BMP_RGB:
793 if (load_lineBMP24(fp, line, hd->biWidth, pad))
794 goto ERROR;
795 }
796 */
797 for (appo = pic, j = c = 0; j < (UINT)info.scanNcol; j++, c += info.step)
798 *appo++ = *(line + info.startScanCol + c);
799 pic += info.xsize;
800
801 skip_bmp_lines(fp, hd->biWidth, (unsigned int)(info.step - 1),
802 (unsigned int)SEEK_CUR, subtype);
803 }
804
805 /*
806 if (BMP_FERROR(fp))
807 {
808 bmp_error(fname, "File appears truncated. Winging it.\n");
809 goto ERROR;
810 }
811 */
812
813 fclose(fp);
814 release_bmp_header(hd);
815 TFREE(line);
816 *pimg = img;
817 return OK;
818
819 ERROR:
820
821 printf("error: (row=%d)\n", i);
822
823 fclose(fp);
824 release_bmp_header(hd);
825
826 if (img) free_img(img);
827 TFREE(line);
828 return bmp_error;
829 }
830 /*---------------------------------------------------------------------------*/
loadBMP1(FILE * fp,LPIXEL * pic,UINT w,UINT h,UCHAR * r,UCHAR * g,UCHAR * b)831 static int loadBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT h, UCHAR *r, UCHAR *g,
832 UCHAR *b)
833 /*---------------------------------------------------------------------------*/
834 {
835 UINT i, j, c, bitnum, padw, rv;
836 UCHAR byte;
837 LPIXEL *pp;
838 #ifdef BMP_READ_LINE_BY_LINE
839 UCHAR *map[3];
840
841 map[0] = r;
842 map[1] = g;
843 map[2] = b;
844 #endif
845
846 rv = c = 0;
847 padw = ((w + 31) / 32) * 32; /* 'w', padded to be a multiple of 32 */
848
849 for (i = 0; i < h; i++) {
850 #ifdef BMP_READ_LINE_BY_LINE
851 pp = pic + (i * w);
852 rv = load_lineBMP1(fp, pp, w, padw, map);
853 if (rv) break;
854 #else
855 pp = pic + (i * w);
856 for (j = bitnum = 0; j < padw; j++, bitnum++) {
857 if ((bitnum & 7) == 0) /* read the next byte */
858 {
859 c = getc(fp);
860 bitnum = 0;
861 }
862 if (j < w) {
863 byte = (c & 0x80) ? 1 : 0;
864 c <<= 1;
865
866 pp->r = r[byte];
867 pp->g = g[byte];
868 pp->b = b[byte];
869 pp->m = 255;
870
871 pp++;
872 }
873 }
874 if (BMP_FERROR(fp)) break;
875 #endif
876 }
877
878 if (BMP_FERROR(fp)) rv = 1;
879
880 return rv;
881 }
882
883 /*---------------------------------------------------------------------------*/
load_lineBMP1(FILE * fp,LPIXEL * pic,UINT w,UINT padw,UCHAR ** map)884 int load_lineBMP1(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map)
885 /*---------------------------------------------------------------------------*/
886 {
887 UINT j, c, bitnum;
888 UCHAR byte;
889 LPIXEL *pp;
890
891 for (c = 0, pp = pic, j = bitnum = 0; j < padw; j++, bitnum++) {
892 if ((bitnum & 7) == 0) /* read the next byte */
893 {
894 c = getc(fp);
895 bitnum = 0;
896 }
897 if (j < w) {
898 byte = (c & 0x80) ? 1 : 0;
899 c <<= 1;
900
901 pp->r = map[0][byte];
902 pp->g = map[1][byte];
903 pp->b = map[2][byte];
904 pp->m = 255;
905
906 pp++;
907 }
908 }
909
910 return (BMP_FERROR(fp));
911 }
912
913 /*---------------------------------------------------------------------------*/
skip_rowsBMP1(FILE * fp,UINT w,UINT pad,UINT rows,int whence)914 static int skip_rowsBMP1(FILE *fp, UINT w, UINT pad, UINT rows, int whence)
915 /*---------------------------------------------------------------------------*/
916 {
917 UINT offset = pad * rows;
918 UINT i, bitnum;
919
920 for (i = bitnum = 0; i < offset; i++, bitnum++) {
921 if ((bitnum & 7) == 0) {
922 getc(fp);
923 bitnum = 0;
924 }
925 }
926
927 return (BMP_FERROR(fp));
928 }
929
930 /*---------------------------------------------------------------------------*/
loadBMP4(FILE * fp,LPIXEL * pic,UINT w,UINT h,UINT comp,UCHAR * r,UCHAR * g,UCHAR * b)931 static int loadBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r,
932 UCHAR *g, UCHAR *b)
933 /*---------------------------------------------------------------------------*/
934 {
935 UINT i, j, c, c1, x, y, nybnum, padw, rv;
936 UCHAR byte;
937 LPIXEL *pp;
938 #ifdef BMP_READ_LINE_BY_LINE
939 UCHAR *map[3];
940
941 map[0] = r;
942 map[1] = g;
943 map[2] = b;
944 #endif
945
946 rv = 0;
947 c = c1 = 0;
948
949 if (comp == BMP_BI_RGB) /* read uncompressed data */
950 {
951 padw = ((w + 7) / 8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */
952 for (i = 0; i < h; i++) {
953 pp = pic + (i * w);
954 #ifdef BMP_READ_LINE_BY_LINE
955 rv = load_lineBMP4(fp, pp, w, padw, map);
956 if (rv) break;
957 #else
958 for (j = nybnum = 0; j < padw; j++, nybnum++) {
959 if ((nybnum & 1) == 0) /* read next byte */
960 {
961 c = getc(fp);
962 nybnum = 0;
963 }
964 if (j < w) {
965 byte = (c & 0xf0) >> 4;
966 c <<= 4;
967
968 pp->r = r[byte];
969 pp->g = g[byte];
970 pp->b = b[byte];
971 pp->m = 255;
972
973 pp++;
974 }
975 }
976 if (BMP_FERROR(fp)) break;
977 #endif
978 }
979 } else if (comp == BMP_BI_RLE4) /* read RLE4 compressed data */
980 {
981 x = y = 0;
982 pp = pic + x + (y)*w;
983 while (y < h) {
984 #ifdef BMP_READ_LINE_BY_LINE
985
986 rv = load_lineBMPC4(fp, pp, w, y, map);
987 if (rv == -1) {
988 rv = 1;
989 break;
990 } else if (rv == -2) {
991 rv = 0;
992 y++;
993 pp = pic + y * w;
994 } else if (rv == -3) {
995 rv = 0;
996 break;
997 } else {
998 y += (rv / w);
999 pp = pic + rv;
1000 rv = 0;
1001 }
1002
1003 #else
1004 c = getc(fp);
1005 if ((int)c == EOF) {
1006 rv = 1;
1007 break;
1008 }
1009
1010 if (c) /* encoded mode */
1011 {
1012 c1 = getc(fp);
1013 for (i = 0; i < c; i++, x++, pp++) {
1014 byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f);
1015 pp->r = r[byte];
1016 pp->g = g[byte];
1017 pp->b = b[byte];
1018 pp->m = 255;
1019 }
1020 } else /* c==0x00 : escape codes */
1021 {
1022 c = getc(fp);
1023 if ((int)c == EOF) {
1024 rv = 1;
1025 break;
1026 }
1027
1028 if (c == 0x00) /* end of line */
1029 {
1030 x = 0;
1031 y++;
1032 if (y < h) pp = pic + x + (y)*w;
1033 } else if (c == 0x01)
1034 break; /* end of pic */
1035 else if (c == 0x02) /* delta */
1036 {
1037 c = getc(fp);
1038 x += c;
1039 c = getc(fp);
1040 y += c;
1041 if (y < h) pp = pic + x + (y)*w;
1042 } else /* absolute mode */
1043 {
1044 for (i = 0; i < c; i++, x++, pp++) {
1045 if ((i & 1) == 0) c1 = getc(fp);
1046 byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f);
1047 pp->r = r[byte];
1048 pp->g = g[byte];
1049 pp->b = b[byte];
1050 pp->m = 255;
1051 }
1052 if (((c & 3) == 1) || ((c & 3) == 2)) /* read pad byte */
1053 getc(fp);
1054 }
1055 }
1056 if (BMP_FERROR(fp)) break;
1057 #endif
1058 }
1059 } else {
1060 return 1;
1061 }
1062
1063 if (BMP_FERROR(fp)) rv = 1;
1064
1065 return rv;
1066 }
1067
1068 /*---------------------------------------------------------------------------*/
load_lineBMP4(FILE * fp,LPIXEL * pic,UINT w,UINT padw,UCHAR ** map)1069 int load_lineBMP4(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map)
1070 /*---------------------------------------------------------------------------*/
1071 {
1072 UINT nybnum, j, c;
1073 UCHAR byte;
1074 LPIXEL *pp;
1075
1076 for (c = 0, pp = pic, j = nybnum = 0; j < padw; j++, nybnum++) {
1077 if ((nybnum & 1) == 0) /* read next byte */
1078 {
1079 c = getc(fp);
1080 nybnum = 0;
1081 }
1082 if (j < w) {
1083 byte = (c & 0xf0) >> 4;
1084 c <<= 4;
1085
1086 pp->r = map[0][byte];
1087 pp->g = map[1][byte];
1088 pp->b = map[2][byte];
1089 pp->m = 255;
1090
1091 pp++;
1092 }
1093 }
1094
1095 return (BMP_FERROR(fp));
1096 }
1097
1098 /*---------------------------------------------------------------------------*/
skip_rowsBMP4(FILE * fp,UINT w,UINT pad,UINT rows,int whence)1099 static int skip_rowsBMP4(FILE *fp, UINT w, UINT pad, UINT rows, int whence)
1100 /*---------------------------------------------------------------------------*/
1101 {
1102 UINT offset = pad * rows;
1103 UINT i, nybnum;
1104
1105 for (i = nybnum = 0; i < offset; i++, nybnum++) {
1106 if ((nybnum & 1) == 0) {
1107 getc(fp);
1108 nybnum = 0;
1109 }
1110 }
1111
1112 return (BMP_FERROR(fp));
1113 }
1114
1115 /*---------------------------------------------------------------------------*/
load_lineBMPC4(FILE * fp,LPIXEL * pic,UINT w,UINT y,UCHAR ** map)1116 int load_lineBMPC4(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map)
1117 /*---------------------------------------------------------------------------*/
1118 {
1119 UINT i, c, c1, x;
1120 UCHAR byte;
1121 LPIXEL *pp;
1122
1123 /*
1124 * Codici di ritorno:
1125 *
1126 * -1: incontrata la file del file (EOF)
1127 * -2: incontrata la fine della linea (Escape code 0x00 0x00)
1128 * -3: incontrata la fine dell' immagine (Escape code 0x00 0x01)
1129 * altro: incontrato un delta (Escape code 0x00 0x02)
1130 */
1131
1132 /* initialize some variables */
1133 x = 0;
1134 pp = pic;
1135 c = c1 = 0;
1136
1137 while (1) {
1138 c = getc(fp);
1139 if ((int)c == EOF) return -1;
1140 if (c) { /* encoded mode */
1141 c1 = getc(fp);
1142 for (i = 0; i < c; i++, x++, pp++) {
1143 byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f);
1144 pp->r = map[0][byte];
1145 pp->g = map[1][byte];
1146 pp->b = map[2][byte];
1147 pp->m = 255;
1148 }
1149 } else /* c==0x00 : escape codes */
1150 {
1151 c = getc(fp);
1152 if ((int)c == EOF) return -1;
1153 if (c == 0x00) /* end of line */
1154 return -2;
1155 else if (c == 0x01) /* end of pic */
1156 return -3;
1157 else if (c == 0x02) /* delta */
1158 {
1159 c = getc(fp);
1160 x += c;
1161 c = getc(fp);
1162 y += c;
1163
1164 return (x + y * w);
1165 } else /* absolute mode */
1166 {
1167 for (i = 0; i < c; i++, x++, pp++) {
1168 if ((i & 1) == 0) c1 = getc(fp);
1169 byte = (i & 1) ? (c1 & 0x0f) : ((c1 >> 4) & 0x0f);
1170 pp->r = map[0][byte];
1171 pp->g = map[1][byte];
1172 pp->b = map[2][byte];
1173 pp->m = 255;
1174 }
1175 if (((c & 3) == 1) || ((c & 3) == 2)) /* read pad byte */
1176 getc(fp);
1177 }
1178 }
1179 if (BMP_FERROR(fp)) break;
1180 }
1181
1182 return -1;
1183 }
1184
1185 /*---------------------------------------------------------------------------*/
skip_rowsBMPC4(FILE * fp,UINT rows)1186 static int skip_rowsBMPC4(FILE *fp, UINT rows)
1187 /*---------------------------------------------------------------------------*/
1188 {
1189 UINT i, c, c1, rv = 0;
1190
1191 while (rows > 0) {
1192 c = getc(fp);
1193 switch (c) {
1194 case 0x00:
1195 c = getc(fp);
1196 switch (c) {
1197 case 0x00:
1198 rows--;
1199 CASE 0x01 : rows = 0;
1200 CASE 0x02 : c1 = getc(fp); /* x buffer offest */
1201 c1 = getc(fp); /* y buffer offest */
1202 rows -= c1;
1203 DEFAULT:
1204 for (i = 0; i < c; i++) {
1205 if ((i & 1) == 0) getc(fp);
1206 }
1207 if (((c & 3) == 1) || ((c & 3) == 2)) getc(fp);
1208 }
1209 DEFAULT:
1210 c1 = getc(fp);
1211 }
1212 }
1213
1214 if (BMP_FERROR(fp)) rv = 1;
1215
1216 return rv;
1217 }
1218
1219 /*---------------------------------------------------------------------------*/
loadBMP8(FILE * fp,LPIXEL * pic,UINT w,UINT h,UINT comp,UCHAR * r,UCHAR * g,UCHAR * b)1220 static int loadBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT h, UINT comp, UCHAR *r,
1221 UCHAR *g, UCHAR *b)
1222 /*---------------------------------------------------------------------------*/
1223 {
1224 UINT i, j, c, c1, padw, x, y, rv;
1225
1226 LPIXEL *pp;
1227 #ifdef BMP_READ_LINE_BY_LINE
1228 UCHAR *map[3];
1229
1230 map[0] = r;
1231 map[1] = g;
1232 map[2] = b;
1233 #endif
1234
1235 rv = 0;
1236
1237 if (comp == BMP_BI_RGB) /* read uncompressed data */
1238 {
1239 padw = ((w + 3) / 4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
1240 for (i = 0; i < h; i++) {
1241 #ifdef BMP_READ_LINE_BY_LINE
1242 pp = pic + (i * w);
1243 rv = load_lineBMP8(fp, pp, w, padw, map);
1244 if (rv) break;
1245 #else
1246 pp = pic + (i * w);
1247 for (j = 0; j < padw; j++) {
1248 c = getc(fp);
1249 if ((int)c == EOF) rv = 1;
1250 if (j < w) {
1251 pp->r = r[c];
1252 pp->g = g[c];
1253 pp->b = b[c];
1254 pp->m = 255;
1255
1256 pp++;
1257 }
1258 }
1259 if (BMP_FERROR(fp)) break;
1260 #endif
1261 }
1262 } else if (comp == BMP_BI_RLE8) /* read RLE8 compressed data */
1263 {
1264 x = y = 0;
1265 pp = pic + x + y * w;
1266 while (y < h) {
1267 #ifdef BMP_READ_LINE_BY_LINE
1268
1269 rv = load_lineBMPC8(fp, pp, w, y, map);
1270 if (rv == -1) {
1271 rv = 1;
1272 break;
1273 } else if (rv == -2) {
1274 rv = 0;
1275 y++;
1276 pp = pic + y * w;
1277 } else if (rv == -3) {
1278 rv = 0;
1279 break;
1280 } else {
1281 y += (rv / w);
1282 pp = pic + rv;
1283 rv = 0;
1284 }
1285
1286 #else
1287 c = getc(fp);
1288 if ((int)c == EOF) {
1289 rv = 1;
1290 break;
1291 }
1292
1293 if (c) { /* encoded mode */
1294 c1 = getc(fp);
1295 for (i = 0; i < c; i++, x++, pp++) {
1296 pp->r = r[c1];
1297 pp->g = g[c1];
1298 pp->b = b[c1];
1299 pp->m = 255;
1300 }
1301 } else /* c==0x00 : escape codes */
1302 {
1303 c = getc(fp);
1304 if ((int)c == EOF) {
1305 rv = 1;
1306 break;
1307 }
1308
1309 if (c == 0x00) /* end of line */
1310 {
1311 x = 0;
1312 y++;
1313 pp = pic + x + y * w;
1314 } else if (c == 0x01)
1315 break; /* end of pic */
1316 else if (c == 0x02) /* delta */
1317 {
1318 c = getc(fp);
1319 x += c;
1320 c = getc(fp);
1321 y += c;
1322 pp = pic + x + y * w;
1323 } else /* absolute mode */
1324 {
1325 for (i = 0; i < c; i++, x++, pp++) {
1326 c1 = getc(fp);
1327
1328 pp->r = r[c1];
1329 pp->g = g[c1];
1330 pp->b = b[c1];
1331 pp->m = 255;
1332 }
1333 if (c & 1) /* odd length run: read an extra pad byte */
1334 getc(fp);
1335 }
1336 }
1337 if (BMP_FERROR(fp)) break;
1338 #endif
1339 }
1340 } else {
1341 return 1;
1342 }
1343
1344 if (BMP_FERROR(fp)) rv = 1;
1345
1346 return rv;
1347 }
1348
1349 /*---------------------------------------------------------------------------*/
load_lineBMP8(FILE * fp,LPIXEL * pic,UINT w,UINT padw,UCHAR ** map)1350 int load_lineBMP8(FILE *fp, LPIXEL *pic, UINT w, UINT padw, UCHAR **map)
1351 /*---------------------------------------------------------------------------*/
1352 {
1353 UINT j, c, rv = 0;
1354 LPIXEL *pp;
1355
1356 for (pp = pic, j = 0; j < padw; j++) {
1357 c = getc(fp);
1358 if ((int)c == EOF) {
1359 rv = 1;
1360 break;
1361 }
1362 if (j < w) {
1363 pp->r = map[0][c];
1364 pp->g = map[1][c];
1365 pp->b = map[2][c];
1366 pp->m = 255;
1367
1368 pp++;
1369 }
1370 }
1371 if (BMP_FERROR(fp)) rv = 1;
1372
1373 return rv;
1374 }
1375
1376 /*---------------------------------------------------------------------------*/
skip_rowsBMP8(FILE * fp,UINT w,UINT pad,UINT rows,int whence)1377 static int skip_rowsBMP8(FILE *fp, UINT w, UINT pad, UINT rows, int whence)
1378 /*---------------------------------------------------------------------------*/
1379 {
1380 UINT offset = pad * rows;
1381
1382 fseek(fp, (long)offset, whence);
1383
1384 return (BMP_FERROR(fp));
1385 }
1386
1387 /*---------------------------------------------------------------------------*/
load_lineBMPC8(FILE * fp,LPIXEL * pic,UINT w,UINT y,UCHAR ** map)1388 int load_lineBMPC8(FILE *fp, LPIXEL *pic, UINT w, UINT y, UCHAR **map)
1389 /*---------------------------------------------------------------------------*/
1390 {
1391 int i, c, c1, x;
1392 LPIXEL *pp;
1393
1394 /*
1395 * Codici di ritorno:
1396 *
1397 * -1: incontrata la file del file (EOF)
1398 * -2: incontrata la fine della linea (Escape code 0x00 0x00)
1399 * -3: incontrata la fine dell' immagine (Escape code 0x00 0x01)
1400 * altro: incontrato un delta (Escape code 0x00 0x02)
1401 */
1402
1403 x = 0;
1404 pp = pic;
1405
1406 while (1) {
1407 c = getc(fp);
1408 if (c == EOF) return -1;
1409 if (c) { /* encoded mode */
1410 c1 = getc(fp);
1411 for (i = 0; i < c; i++, x++, pp++) {
1412 pp->r = map[0][c1];
1413 pp->g = map[1][c1];
1414 pp->b = map[2][c1];
1415 pp->m = 255;
1416 }
1417 } else /* c==0x00 : escape codes */
1418 {
1419 c = getc(fp);
1420 if (c == EOF) return -1;
1421 if (c == 0x00) /* end of line */
1422 return -2;
1423 else if (c == 0x01) /* end of pic */
1424 return -3;
1425 else if (c == 0x02) /* delta */
1426 {
1427 c = getc(fp);
1428 x += c;
1429 c = getc(fp);
1430 y += c;
1431
1432 return (x + y * w);
1433 } else /* absolute mode */
1434 {
1435 for (i = 0; i < c; i++, x++, pp++) {
1436 c1 = getc(fp);
1437
1438 pp->r = map[0][c1];
1439 pp->g = map[1][c1];
1440 pp->b = map[2][c1];
1441 pp->m = 255;
1442 }
1443 if (c & 1) /* odd length run: read an extra pad byte */
1444 getc(fp);
1445 }
1446 }
1447 }
1448 }
1449
1450 /*---------------------------------------------------------------------------*/
skip_rowsBMPC8(FILE * fp,UINT rows)1451 static int skip_rowsBMPC8(FILE *fp, UINT rows)
1452 /*---------------------------------------------------------------------------*/
1453 {
1454 int i, c, c1, rv = 0;
1455
1456 while (rows > 0) {
1457 c = getc(fp);
1458 switch (c) {
1459 case 0x00:
1460 c = getc(fp);
1461 switch (c) {
1462 case 0x00:
1463 rows--;
1464 CASE 0x01 : rows = 0;
1465 CASE 0x02 : c1 = getc(fp); /* x buffer offest */
1466 c1 = getc(fp); /* y buffer offest */
1467 rows -= c1;
1468 DEFAULT:
1469 for (i = 0; i < c; i++) getc(fp);
1470 if (c & 1) getc(fp);
1471 }
1472 DEFAULT:
1473 c1 = getc(fp);
1474 }
1475 }
1476
1477 if (BMP_FERROR(fp)) rv = 1;
1478
1479 return rv;
1480 }
1481
1482 /*---------------------------------------------------------------------------*/
loadBMP24(FILE * fp,LPIXEL * pic,UINT w,UINT h)1483 static int loadBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT h)
1484 /*---------------------------------------------------------------------------*/
1485 {
1486 UINT i, j, padb, rv;
1487 LPIXEL *pp;
1488
1489 rv = 0;
1490
1491 padb = (4 - ((w * 3) % 4)) & 0x03; /* # of pad bytes to read at EOscanline */
1492
1493 for (i = 0; i < h; i++) {
1494 #ifdef BMP_READ_LINE_BY_LINE
1495 pp = pic + i * w;
1496 rv = load_lineBMP24(fp, pp, w, padb);
1497 #else
1498 for (pp = pic + i * w, j = 0; j < w; j++, pp++) {
1499 pp->b = getc(fp); /* blue */
1500 pp->g = getc(fp); /* green */
1501 pp->r = getc(fp); /* red */
1502 pp->m = 255;
1503 }
1504 for (j = 0; j < padb; j++) getc(fp);
1505
1506 rv = (BMP_FERROR(fp));
1507 #endif
1508 if (rv) break;
1509 }
1510
1511 return rv;
1512 }
1513
1514 /*---------------------------------------------------------------------------*/
load_lineBMP24(FILE * fp,LPIXEL * pic,UINT w,UINT padb)1515 int load_lineBMP24(FILE *fp, LPIXEL *pic, UINT w, UINT padb)
1516 /*---------------------------------------------------------------------------*/
1517 {
1518 LPIXEL *pp;
1519 UINT j;
1520
1521 for (pp = pic, j = 0; j < w; j++, pp++) {
1522 pp->b = getc(fp); /* blue */
1523 pp->g = getc(fp); /* green */
1524 pp->r = getc(fp); /* red */
1525 pp->m = 255;
1526 }
1527 for (j = 0; j < padb; j++) getc(fp);
1528
1529 return (BMP_FERROR(fp));
1530 }
1531
1532 /*---------------------------------------------------------------------------*/
skip_rowsBMP24(FILE * fp,UINT w,UINT pad,UINT rows,int whence)1533 static int skip_rowsBMP24(FILE *fp, UINT w, UINT pad, UINT rows, int whence)
1534 /*---------------------------------------------------------------------------*/
1535 {
1536 UINT offset = (w * 3 + pad) * rows;
1537
1538 fseek(fp, (long)offset, whence);
1539
1540 return (BMP_FERROR(fp));
1541 }
1542
1543 /*---------------------------------------------------------------------------*/
1544 /*-- BMP WRITE --------------------------------------------------------------*/
1545
1546 /*---------------------------------------------------------------------------*/
bmp_get_colorstyle(IMAGE * img)1547 BMP_SUBTYPE bmp_get_colorstyle(IMAGE *img)
1548 /*---------------------------------------------------------------------------*/
1549 {
1550 return img->type;
1551 }
1552
1553 /*---------------------------------------------------------------------------*/
write_bmp_header(FILE * fp,BMP_HEADER * hd)1554 int write_bmp_header(FILE *fp, BMP_HEADER *hd)
1555 /*---------------------------------------------------------------------------*/
1556 {
1557 putc('B', fp);
1558 putc('M', fp); /* BMP file magic number */
1559
1560 putint(fp, (int)hd->bfSize);
1561 putshort(fp, 0); /* reserved1 */
1562 putshort(fp, 0); /* reserved2 */
1563
1564 putint(fp, (int)hd->bfOffBits); /* offset from BOfile to BObitmap */
1565
1566 putint(fp, (int)hd->biSize); /* size of bitmap info header */
1567 putint(fp, (int)hd->biWidth); /* width */
1568 putint(fp, (int)hd->biHeight); /* height */
1569 putshort(fp, (int)hd->biPlanes); /* must be '1' */
1570 putshort(fp, (int)hd->biBitCount); /* 1,4,8, or 24 */
1571 putint(fp,
1572 (int)hd->biCompression); /* BMP_BI_RGB, BMP_BI_RLE8 or BMP_BI_RLE4 */
1573 putint(fp, (int)hd->biSizeImage); /* size of raw image data */
1574 putint(fp, (int)hd->biXPelsPerMeter); /* dpi * 39" per meter */
1575 putint(fp, (int)hd->biYPelsPerMeter); /* dpi * 39" per meter */
1576 putint(fp, (int)hd->biClrUsed); /* colors used in cmap */
1577 putint(fp, (int)hd->biClrImportant); /* same as above */
1578
1579 if (BMP_FERROR(fp)) return FALSE;
1580
1581 return TRUE;
1582 }
1583
1584 /*---------------------------------------------------------------------------*/
write_bmp_palette(FILE * fp,int nc,UCHAR * b,UCHAR * g,UCHAR * r)1585 int write_bmp_palette(FILE *fp, int nc, UCHAR *b, UCHAR *g, UCHAR *r)
1586 /*---------------------------------------------------------------------------*/
1587 {
1588 int i;
1589
1590 for (i = 0; i < nc; i++) {
1591 putc(b[i], fp);
1592 putc(g[i], fp);
1593 putc(r[i], fp);
1594 putc(0, fp);
1595 }
1596
1597 if (BMP_FERROR(fp)) return FALSE;
1598
1599 return TRUE;
1600 }
1601
1602 #ifndef __LIBSIMAGE__
1603
1604 /*---------------------------------------------------------------------------*/
img_write_bmp(const MYSTRING fname,IMAGE * img)1605 int img_write_bmp(const MYSTRING fname, IMAGE *img)
1606 /*---------------------------------------------------------------------------*/
1607 {
1608 int (*write_function)(FILE * fp, UCHAR * pic, UINT w, UINT h, UCHAR * map);
1609 int h, w, i, nc, nbits, bperlin, comp;
1610 UCHAR val;
1611 UCHAR pc2nc[256], r1[256], g1[256], b1[256];
1612 UCHAR *pic, *graypic;
1613 BMP_SUBTYPE subtype;
1614 BMP_HEADER hd;
1615 FILE *fp;
1616
1617 subtype = bmp_get_colorstyle(img);
1618 if (subtype == BMP_NONE) return UNSUPPORTED_BMP_FORMAT;
1619
1620 fp = _wfopen(fname, L"wb");
1621 if (!fp) return CANT_OPEN_FILE;
1622
1623 graypic = NULL;
1624 nc = 0;
1625 nbits = 0;
1626 comp = 0;
1627 h = img->ysize;
1628 w = img->xsize;
1629 pic = (UCHAR *)img->buffer;
1630
1631 switch (subtype) {
1632 case BMP_BW:
1633 __OR BMP_GREY16 : __OR BMP_GREY16C :
1634
1635 __OR BMP_CMAPPED256 : __OR BMP_CMAPPED256C
1636 : return UNSUPPORTED_BMP_FORMAT;
1637 CASE BMP_GREY256 : __OR BMP_GREY256C : nbits = 8;
1638 CASE BMP_RGB : nbits = 24;
1639 DEFAULT:
1640 goto BMP_WRITE_ERROR;
1641 }
1642
1643 /* number bytes written per line */
1644 bperlin = ((w * nbits + 31) / 32) * 4;
1645
1646 /* compute filesize and write it */
1647 i = 14 + /* size of bitmap file header */
1648 40 + /* size of bitmap info header */
1649 (nc * 4) + /* size of colormap */
1650 bperlin * h; /* size of image data */
1651
1652 switch (nbits) {
1653 case 4:
1654 comp = (comp == TRUE) ? BMP_BI_RLE4 : BMP_BI_RGB;
1655 CASE 8 : comp = (comp == TRUE) ? BMP_BI_RLE8 : BMP_BI_RGB;
1656 DEFAULT:
1657 comp = BMP_BI_RGB;
1658 }
1659
1660 /* fill image header */
1661 hd.bfSize = i;
1662 hd.bfOffBits = 14 + 40 + (nc * 4);
1663 hd.biSize = 40;
1664 hd.biWidth = w;
1665 hd.biHeight = h;
1666 hd.biPlanes = 1;
1667 hd.biBitCount = nbits;
1668 hd.biCompression = comp;
1669 hd.biSizeImage = bperlin * h;
1670 hd.biXPelsPerMeter = 0 * 39;
1671 hd.biYPelsPerMeter = 0 * 39;
1672 hd.biClrUsed = nc;
1673 hd.biClrImportant = nc;
1674
1675 if (!write_bmp_header(fp, &hd)) goto BMP_WRITE_ERROR;
1676
1677 write_bmp_palette(fp, nc, b1, g1, r1);
1678
1679 switch (nbits) {
1680 case 1:
1681 write_function = writeBMP1;
1682 CASE 4 : if (comp == BMP_BI_RGB) write_function = writeBMP4;
1683 else write_function = writeBMPC4;
1684 CASE 8 : if (comp == BMP_BI_RGB) write_function = writeBMP8;
1685 else write_function = writeBMPC8;
1686 CASE 24 : write_function = writeBMP24;
1687 DEFAULT:
1688 goto BMP_WRITE_ERROR;
1689 }
1690
1691 /* write out the image */
1692 val = write_function(fp, pic, (unsigned int)w, (unsigned int)h, pc2nc);
1693
1694 if (graypic) free(graypic);
1695 fclose(fp);
1696
1697 /* 0 failed , 1 ok */
1698 return val == 1 ? OK : WRITE_ERROR;
1699
1700 BMP_WRITE_ERROR:
1701
1702 fclose(fp);
1703 if (graypic) free(graypic);
1704
1705 _wremove(fname);
1706
1707 return WRITE_ERROR;
1708 }
1709
1710 #endif /* __LIBSIMAGE__ */
1711
1712 /*---------------------------------------------------------------------------*/
writeBMP1(FILE * fp,UCHAR * pic8,UINT w,UINT h,UCHAR * pc2nc)1713 static int writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc)
1714 /*---------------------------------------------------------------------------*/
1715 {
1716 UINT i, j, c, bitnum, padw;
1717 UCHAR *pp;
1718
1719 padw = ((w + 31) / 32) * 32; /* 'w', padded to be a multiple of 32 */
1720
1721 for (i = 0; i < h; i++) {
1722 pp = pic8 + (i * w);
1723 #ifdef BMP_WRITE_LINE_BY_LINE
1724 if (line_writeBMP1(fp, pp, w, padw, pc2nc) == FALSE) return FALSE;
1725 #else
1726 for (j = bitnum = c = 0; j <= padw; j++, bitnum++) {
1727 if (bitnum == 8) /* write the next byte */
1728 {
1729 putc((int)c, fp);
1730 bitnum = c = 0;
1731 }
1732 c <<= 1;
1733 if (j < w) {
1734 c |= (pc2nc[*pp++] & 0x01);
1735 }
1736 }
1737 #endif
1738 }
1739 if (BMP_FERROR(fp)) return FALSE;
1740
1741 return TRUE;
1742 }
1743
1744 /*---------------------------------------------------------------------------*/
line_writeBMP1(FILE * fp,UCHAR * pic8,UINT w,UINT padw,UCHAR * pc2nc)1745 static int line_writeBMP1(FILE *fp, UCHAR *pic8, UINT w, UINT padw,
1746 UCHAR *pc2nc)
1747 /*---------------------------------------------------------------------------*/
1748 {
1749 UCHAR *pp = pic8;
1750 UINT j, c, bitnum;
1751
1752 for (j = bitnum = c = 0; j <= padw; j++, bitnum++) {
1753 if (bitnum == 8) /* write the next byte */
1754 {
1755 putc((int)c, fp);
1756 bitnum = c = 0;
1757 }
1758 c <<= 1;
1759 if (j < w) {
1760 c |= (pc2nc[*pp++] & 0x01);
1761 }
1762 }
1763 if (BMP_FERROR(fp)) return FALSE;
1764
1765 return TRUE;
1766 }
1767
1768 /*---------------------------------------------------------------------------*/
writeBMP4(FILE * fp,UCHAR * pic8,UINT w,UINT h,UCHAR * pc2nc)1769 static int writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc)
1770 /*---------------------------------------------------------------------------*/
1771 {
1772 UINT i, j, c, nybnum, padw;
1773 UCHAR *pp;
1774
1775 padw = ((w + 7) / 8) * 8; /* 'w' padded to a multiple of 8pix (32 bits) */
1776
1777 for (i = 0; i < h; i++) {
1778 pp = pic8 + (i * w);
1779 #ifdef BMP_WRITE_LINE_BY_LINE
1780 if (line_writeBMP4(fp, pp, w, padw, pc2nc) == FALSE) return FALSE;
1781 #else
1782 for (j = nybnum = c = 0; j <= padw; j++, nybnum++) {
1783 if (nybnum == 2) /* write next byte */
1784 {
1785 putc((int)(c & 0xff), fp);
1786 nybnum = c = 0;
1787 }
1788 c <<= 4;
1789 if (j < w) {
1790 c |= (pc2nc[*pp] & 0x0f);
1791 pp++;
1792 }
1793 }
1794 #endif
1795 }
1796 if (BMP_FERROR(fp)) return FALSE;
1797
1798 return TRUE;
1799 }
1800
1801 /*---------------------------------------------------------------------------*/
line_writeBMP4(FILE * fp,UCHAR * pic8,UINT w,UINT padw,UCHAR * pc2nc)1802 static int line_writeBMP4(FILE *fp, UCHAR *pic8, UINT w, UINT padw,
1803 UCHAR *pc2nc)
1804 /*---------------------------------------------------------------------------*/
1805 {
1806 UINT j, c, nybnum;
1807 UCHAR *pp = pic8;
1808
1809 for (j = nybnum = c = 0; j <= padw; j++, nybnum++) {
1810 if (nybnum == 2) /* write next byte */
1811 {
1812 putc((int)(c & 0xff), fp);
1813 nybnum = c = 0;
1814 }
1815 c <<= 4;
1816 if (j < w) {
1817 c |= (pc2nc[*pp] & 0x0f);
1818 pp++;
1819 }
1820 }
1821 if (BMP_FERROR(fp)) return FALSE;
1822
1823 return TRUE;
1824 }
1825
1826 /*---------------------------------------------------------------------------*/
writeBMPC4(FILE * fp,UCHAR * pic8,UINT w,UINT h,UCHAR * pc2nc)1827 static int writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc)
1828 /*---------------------------------------------------------------------------*/
1829 {
1830 UCHAR *pp1, *pp2, *pp3, byte1, byte2;
1831 UINT i, cnt;
1832
1833 for (i = 0; i < h; i++) {
1834 pp1 = pic8 + i * w;
1835 pp2 = pp1 + 2;
1836 pp3 = pp1 + w + 2;
1837
1838 for (; pp2 < pp3; pp2 += 2) {
1839 cnt = 2;
1840
1841 byte1 = ((pc2nc[*pp1] << 4) & 0xf0) | (pc2nc[*(pp1 + 1)] & 0x0f);
1842 byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f);
1843
1844 if (byte1 != byte2) {
1845 putc((int)cnt, fp);
1846 putc(byte1, fp);
1847 pp1 = pp2;
1848 } else {
1849 while (cnt <= 254 && pp2 < pp3) {
1850 cnt += 2;
1851 pp2 += 2;
1852 byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f);
1853 if (byte1 != byte2 || cnt >= 254 || pp2 + 2 > pp3) {
1854 if (pp2 + 2 > pp3) cnt -= 2;
1855 putc((int)cnt, fp);
1856 putc(byte1, fp);
1857 break;
1858 }
1859 }
1860 pp1 = pp2;
1861 }
1862 }
1863 putc(0x00, fp);
1864 putc(0x00, fp);
1865 if (BMP_FERROR(fp)) return FALSE;
1866 }
1867 putc(0x00, fp);
1868 putc(0x01, fp);
1869
1870 if (BMP_FERROR(fp)) return FALSE;
1871
1872 return TRUE;
1873 }
1874
1875 /*---------------------------------------------------------------------------*/
line_writeBMPC4(FILE * fp,UCHAR * pic8,UINT w,UINT row,UCHAR * pc2nc)1876 static int line_writeBMPC4(FILE *fp, UCHAR *pic8, UINT w, UINT row,
1877 UCHAR *pc2nc)
1878 /*---------------------------------------------------------------------------*/
1879 {
1880 UCHAR *pp1, *pp2, *pp3, byte1, byte2;
1881 UINT cnt;
1882
1883 pp1 = pic8 + row * w;
1884 pp2 = pp1 + 2;
1885 pp3 = pp1 + w + 2;
1886
1887 for (; pp2 < pp3; pp2 += 2) {
1888 cnt = 2;
1889
1890 byte1 = ((pc2nc[*pp1] << 4) & 0xf0) | (pc2nc[*(pp1 + 1)] & 0x0f);
1891 byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f);
1892
1893 if (byte1 != byte2) {
1894 putc((int)cnt, fp);
1895 putc(byte1, fp);
1896 pp1 = pp2;
1897 } else {
1898 while (cnt <= 254 && pp2 < pp3) {
1899 cnt += 2;
1900 pp2 += 2;
1901 byte2 = ((pc2nc[*pp2] << 4) & 0xf0) | (pc2nc[*(pp2 + 1)] & 0x0f);
1902 if (byte1 != byte2 || cnt >= 254 || pp2 + 2 > pp3) {
1903 if (pp2 + 2 > pp3) cnt -= 2;
1904 putc((int)cnt, fp);
1905 putc(byte1, fp);
1906 break;
1907 }
1908 }
1909 pp1 = pp2;
1910 }
1911 }
1912 putc(0x00, fp);
1913 putc(0x00, fp);
1914
1915 if (BMP_FERROR(fp)) return FALSE;
1916
1917 return TRUE;
1918 }
1919
1920 /*---------------------------------------------------------------------------*/
writeBMP8(FILE * fp,UCHAR * pic8,UINT w,UINT h,UCHAR * pc2nc)1921 static int writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc)
1922 /*---------------------------------------------------------------------------*/
1923 {
1924 UINT i, j, padw;
1925 UCHAR *pp;
1926
1927 padw = ((w + 3) / 4) * 4; /* 'w' padded to a multiple of 4pix (32 bits) */
1928
1929 for (i = 0; i < h; i++) {
1930 pp = pic8 + (i * w);
1931 #ifdef BMP_WRITE_LINE_BY_LINE
1932 if (line_writeBMP8(fp, pp, w, padw, pc2nc) == FALSE) return FALSE;
1933 #else
1934 /* for (j=0; j<w; j++) putc(pc2nc[*pp++], fp);*/
1935 for (j = 0; j < w; j++) {
1936 putc(*pp, fp);
1937 pp++;
1938 }
1939 for (; j < padw; j++) putc(0, fp);
1940 #endif
1941 }
1942 if (BMP_FERROR(fp)) return FALSE;
1943
1944 return TRUE;
1945 }
1946
1947 /*---------------------------------------------------------------------------*/
line_writeBMP8(FILE * fp,UCHAR * pic8,UINT w,UINT padw,UCHAR * pc2nc)1948 static int line_writeBMP8(FILE *fp, UCHAR *pic8, UINT w, UINT padw,
1949 UCHAR *pc2nc)
1950 /*---------------------------------------------------------------------------*/
1951 {
1952 UCHAR *pp = pic8;
1953 UINT j;
1954
1955 for (j = 0; j < w; j++) putc(pc2nc[*pp++], fp);
1956 for (; j < padw; j++) putc(0, fp);
1957 if (BMP_FERROR(fp)) return FALSE;
1958
1959 return TRUE;
1960 }
1961
1962 /*---------------------------------------------------------------------------*/
writeBMPC8(FILE * fp,UCHAR * pic8,UINT w,UINT h,UCHAR * pc2nc)1963 static int writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT h, UCHAR *pc2nc)
1964 /*---------------------------------------------------------------------------*/
1965 {
1966 UCHAR *pp1, *pp2, *pp3, byte1, byte2;
1967 UINT i, cnt;
1968
1969 for (i = 0; i < h; i++) {
1970 pp1 = pic8 + i * w;
1971 pp2 = pp1 + 1;
1972 pp3 = pp1 + w + 1;
1973
1974 for (; pp2 < pp3; pp2++) {
1975 cnt = 1;
1976
1977 byte1 = pc2nc[*pp1];
1978 byte2 = pc2nc[*pp2];
1979
1980 if (byte1 != byte2) {
1981 putc((int)cnt, fp);
1982 putc(byte1, fp);
1983 pp1 = pp2;
1984 } else {
1985 while (cnt <= 254 && pp2 < pp3) {
1986 cnt++;
1987 pp2++;
1988 byte2 = pc2nc[*pp2];
1989 if (byte1 != byte2 || cnt >= 254 || pp2 + 1 > pp3) {
1990 if (pp2 + 1 > pp3) cnt--;
1991 putc((int)cnt, fp);
1992 putc(byte1, fp);
1993 break;
1994 }
1995 }
1996 pp1 = pp2;
1997 }
1998 }
1999 putc(0x00, fp);
2000 putc(0x00, fp);
2001 if (BMP_FERROR(fp)) return FALSE;
2002 }
2003 putc(0x00, fp);
2004 putc(0x01, fp);
2005
2006 if (BMP_FERROR(fp)) return FALSE;
2007
2008 return TRUE;
2009 }
2010
2011 /*---------------------------------------------------------------------------*/
line_writeBMPC8(FILE * fp,UCHAR * pic8,UINT w,UINT row,UCHAR * pc2nc)2012 static int line_writeBMPC8(FILE *fp, UCHAR *pic8, UINT w, UINT row,
2013 UCHAR *pc2nc)
2014 /*---------------------------------------------------------------------------*/
2015 {
2016 UCHAR *pp1, *pp2, *pp3, byte1, byte2;
2017 UINT cnt;
2018
2019 pp1 = pic8 + row * w;
2020 pp2 = pp1 + 1;
2021 pp3 = pp1 + w + 1;
2022
2023 for (; pp2 < pp3; pp2++) {
2024 cnt = 1;
2025
2026 byte1 = pc2nc[*pp1];
2027 byte2 = pc2nc[*pp2];
2028
2029 if (byte1 != byte2) {
2030 putc((int)cnt, fp);
2031 putc(byte1, fp);
2032 pp1 = pp2;
2033 } else {
2034 while (cnt <= 254 && pp2 < pp3) {
2035 cnt++;
2036 pp2++;
2037 byte2 = pc2nc[*pp2];
2038 if (byte1 != byte2 || cnt >= 254 || pp2 + 1 > pp3) {
2039 if (pp2 + 1 > pp3) cnt--;
2040 putc((int)cnt, fp);
2041 putc(byte1, fp);
2042 break;
2043 }
2044 }
2045 pp1 = pp2;
2046 }
2047 }
2048 putc(0x00, fp);
2049 putc(0x00, fp);
2050
2051 if (BMP_FERROR(fp)) return FALSE;
2052
2053 return TRUE;
2054 }
2055
2056 /*---------------------------------------------------------------------------*/
writeBMP24(FILE * fp,UCHAR * pic24,UINT w,UINT h,UCHAR * whence)2057 static int writeBMP24(FILE *fp, UCHAR *pic24, UINT w, UINT h, UCHAR *whence)
2058 /*---------------------------------------------------------------------------*/
2059 {
2060 UINT i, j, padb;
2061 LPIXEL *pixel;
2062 UCHAR *pp;
2063
2064 /* pc2nc not used */
2065
2066 padb = (4 - ((w * 3) % 4)) & 0x03; /* # of pad bytes to write at EOscanline */
2067
2068 for (i = 0; i < h; i++) {
2069 pp = pic24 + (i * w * 4);
2070 pixel = (LPIXEL *)pp;
2071 #ifdef BMP_WRITE_LINE_BY_LINE
2072 if (line_writeBMP24(fp, pixel, w, padb) == FALSE) return FALSE;
2073 #else
2074 for (j = 0; j < w; j++) {
2075 putc(pixel->b, fp);
2076 putc(pixel->g, fp);
2077 putc(pixel->r, fp);
2078
2079 pixel++;
2080 }
2081 for (j = 0; j < padb; j++) putc(0, fp);
2082 #endif
2083 }
2084 if (BMP_FERROR(fp)) return FALSE;
2085
2086 return TRUE;
2087 }
2088
2089 /*---------------------------------------------------------------------------*/
line_writeBMP24(FILE * fp,LPIXEL * pp,UINT w,UINT padb)2090 static int line_writeBMP24(FILE *fp, LPIXEL *pp, UINT w, UINT padb)
2091 /*---------------------------------------------------------------------------*/
2092 {
2093 UINT j;
2094
2095 for (j = 0; j < w; j++) {
2096 putc(pp->b, fp);
2097 putc(pp->g, fp);
2098 putc(pp->r, fp);
2099
2100 pp++;
2101 }
2102 for (j = 0; j < padb; j++) putc(0, fp);
2103 if (BMP_FERROR(fp)) return FALSE;
2104
2105 return TRUE;
2106 }
2107
2108 #ifndef __LIBSIMAGE__
2109
2110 #ifndef UNUSED_REDUCE_COLORS
2111 /*---------------------------------------------------------------------------*/
reduce_colors(UCHAR * buffin,int xsize,int ysize,UCHAR * rmap,UCHAR * gmap,UCHAR * bmap,int nc)2112 static UCHAR *reduce_colors(UCHAR *buffin, int xsize, int ysize, UCHAR *rmap,
2113 UCHAR *gmap, UCHAR *bmap, int nc)
2114 /*---------------------------------------------------------------------------*/
2115 {
2116 LPIXEL *curr_pix, *next_pix, *prev_pix, *buffer;
2117 static LPIXEL *mbuffer = NULL;
2118 static UCHAR *ret_buf = NULL;
2119 static int outbuf_size = 0;
2120 static int buffin_size = 0;
2121 int r1, g1, b1, dim;
2122 int i, j, tmp;
2123 int imax, jmax;
2124 UCHAR *outbuf;
2125 USHORT val;
2126
2127 dim = xsize * ysize;
2128
2129 if (dim > outbuf_size) {
2130 if (!ret_buf)
2131 TCALLOC(ret_buf, dim)
2132 else
2133 TREALLOC(ret_buf, dim);
2134 if (!ret_buf) return NULL;
2135 outbuf_size = dim;
2136 }
2137
2138 if (dim > buffin_size) {
2139 if (!mbuffer)
2140 TCALLOC(mbuffer, dim)
2141 else
2142 TREALLOC(mbuffer, dim);
2143 if (!ret_buf) return NULL;
2144 buffin_size = dim;
2145 }
2146
2147 memcpy(mbuffer, buffin, dim * sizeof(LPIXEL));
2148 buffer = mbuffer;
2149 outbuf = ret_buf;
2150
2151 imax = ysize - 1;
2152 jmax = xsize - 1;
2153
2154 for (i = 0; i < ysize; i++) {
2155 curr_pix = buffer;
2156 buffer += xsize;
2157 next_pix = buffer;
2158 prev_pix = NIL;
2159
2160 for (j = 0; j < xsize; j++) {
2161 r1 = curr_pix->r;
2162 g1 = curr_pix->g;
2163 b1 = curr_pix->b;
2164
2165 val = BMP_REDUCE_COLORS(r1, g1, b1);
2166
2167 *(outbuf++) = (unsigned char)val;
2168
2169 /* errors on colors */
2170 r1 -= rmap[val];
2171 g1 -= gmap[val];
2172 b1 -= bmap[val];
2173
2174 if (j != jmax) BMP_ADD_ERROR(curr_pix[1], 7) /* RIGHT */
2175 if (i != imax) /* UP */
2176 {
2177 BMP_ADD_ERROR(*next_pix, 5)
2178 if (j > 0) BMP_ADD_ERROR(*prev_pix, 3) /* UP LEFT */
2179 if (j != jmax) BMP_ADD_ERROR(next_pix[1], 1) /* UP RIGHT */
2180 prev_pix = next_pix;
2181 next_pix++;
2182 }
2183 curr_pix++;
2184 }
2185 }
2186
2187 return ret_buf;
2188 }
2189 #endif
2190
2191 #endif /* __LIBSIMAGE__ */
2192
2193 /*---------------------------------------------------------------------------*/
make_bmp_palette(int colors,int grey,UCHAR * r,UCHAR * g,UCHAR * b)2194 int make_bmp_palette(int colors, int grey, UCHAR *r, UCHAR *g, UCHAR *b)
2195 /*---------------------------------------------------------------------------*/
2196 {
2197 int i, j, ind, val;
2198
2199 switch (colors) {
2200 case 2:
2201 for (i = 0; i < 2; i++) r[i] = g[i] = b[i] = i * 255;
2202 CASE 16 : for (i = 0; i < 16; i++) {
2203 for (j = 0; j < 16; j++) {
2204 ind = i * 16 + j;
2205 val = i * 16;
2206 r[ind] = g[ind] = b[ind] = val;
2207 }
2208 }
2209 CASE 256 : if (grey) {
2210 for (i = 0; i < 256; i++) r[i] = g[i] = b[i] = i;
2211 }
2212 else {
2213 for (i = 0; i < 256; i++) {
2214 r[i] = BMP_RMAP(i);
2215 g[i] = BMP_GMAP(i);
2216 b[i] = BMP_BMAP(i);
2217 }
2218 }
2219 DEFAULT:
2220 return FALSE;
2221 }
2222
2223 return TRUE;
2224 }
2225
2226 /*---------------------------------------------------------------------------*/
getshort(FILE * fp)2227 static UINT getshort(FILE *fp)
2228 /*---------------------------------------------------------------------------*/
2229 {
2230 int c = getc(fp), c1 = getc(fp);
2231
2232 return ((UINT)c) + (((UINT)c1) << 8);
2233 }
2234
2235 /*---------------------------------------------------------------------------*/
getint(FILE * fp)2236 static UINT getint(FILE *fp)
2237 /*---------------------------------------------------------------------------*/
2238 {
2239 int c = getc(fp), c1 = getc(fp), c2 = getc(fp), c3 = getc(fp);
2240
2241 return (((UINT)c) << 0) + (((UINT)c1) << 8) + (((UINT)c2) << 16) +
2242 (((UINT)c3) << 24);
2243 }
2244
2245 /*---------------------------------------------------------------------------*/
putshort(FILE * fp,int i)2246 static void putshort(FILE *fp, int i)
2247 /*---------------------------------------------------------------------------*/
2248 {
2249 int c = (((UINT)i)) & 0xff, c1 = (((UINT)i) >> 8) & 0xff;
2250
2251 putc(c, fp);
2252 putc(c1, fp);
2253 }
2254
2255 /*---------------------------------------------------------------------------*/
putint(FILE * fp,int i)2256 static void putint(FILE *fp, int i)
2257 /*---------------------------------------------------------------------------*/
2258 {
2259 int c = ((UINT)i) & 0xff, c1 = (((UINT)i) >> 8) & 0xff,
2260 c2 = (((UINT)i) >> 16) & 0xff, c3 = (((UINT)i) >> 24) & 0xff;
2261
2262 putc(c, fp);
2263 putc(c1, fp);
2264 putc(c2, fp);
2265 putc(c3, fp);
2266 }
2267
2268 /*---------------------------------------------------------------------------*/
2269
writebmp(const MYSTRING filename,int xsize,int ysize,void * buffer,int bpp)2270 int writebmp(const MYSTRING filename, int xsize, int ysize, void *buffer,
2271 int bpp) {
2272 IMAGE img;
2273 img.xsize = xsize;
2274 img.ysize = ysize;
2275 img.buffer = buffer;
2276 switch (bpp) {
2277 case 8:
2278 img.type = BMP_GREY256C;
2279 CASE 32 : img.type = BMP_RGB;
2280 }
2281 return img_write_bmp(filename, &img);
2282 }
2283
2284 /*---------------------------------------------------------------------------*/
2285
readbmp(const MYSTRING filename,int * xsize,int * ysize,void ** buffer)2286 int readbmp(const MYSTRING filename, int *xsize, int *ysize, void **buffer) {
2287 IMAGE *img;
2288 int retCode = img_read_bmp(filename, &img);
2289 if (retCode != OK) {
2290 *xsize = *ysize = 0;
2291 *buffer = 0;
2292 } else {
2293 *xsize = img->xsize;
2294 *ysize = img->ysize;
2295 *buffer = img->buffer;
2296 img->buffer = 0;
2297 free_img(img);
2298 }
2299 return retCode;
2300 }
2301
2302 /*---------------------------------------------------------------------------*/
2303
readbmpregion(const MYSTRING filename,void ** pimg,int x1,int y1,int x2,int y2,int scale)2304 int readbmpregion(const MYSTRING filename, void **pimg, int x1, int y1, int x2,
2305 int y2, int scale) {
2306 IMAGE *img;
2307
2308 int retCode = img_read_bmp_region(filename, &img, x1, y1, x2, y2, scale);
2309
2310 if (retCode != OK) {
2311 *pimg = 0;
2312 } else {
2313 *pimg = img->buffer;
2314 free(img);
2315 }
2316 return retCode;
2317 }
2318 /*---------------------------------------------------------------------------*/
2319
readbmp_size(const MYSTRING fname,int * lx,int * ly)2320 int readbmp_size(const MYSTRING fname, int *lx, int *ly) {
2321 IMAGE *img;
2322 int retCode = img_read_bmp_generic(fname, BMP_READ_INFO, &img);
2323 if (retCode == OK) {
2324 *lx = img->xsize;
2325 *ly = img->ysize;
2326 free(img);
2327 }
2328 return retCode;
2329 }
2330
2331 /*---------------------------------------------------------------------------*/
2332
readbmp_bbox(const MYSTRING fname,int * x0,int * y0,int * x1,int * y1)2333 int readbmp_bbox(const MYSTRING fname, int *x0, int *y0, int *x1, int *y1) {
2334 IMAGE *img;
2335 int retCode = img_read_bmp_generic(fname, BMP_READ_INFO, &img);
2336 if (retCode == OK) {
2337 *x0 = 0;
2338 *x1 = 0;
2339 *x1 = img->xsize - 1;
2340 *y1 = img->ysize - 1;
2341 free(img);
2342 }
2343 return retCode;
2344 }
2345