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