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