source: trunk/JPGPROC/source/gbmsrc/gbmbmp.c@ 2

Last change on this file since 2 was 2, checked in by stevenhl, 8 years ago

Import sources from cwmm-full.zip dated 2005-03-21

File size: 17.7 KB
Line 
1/*
2
3gbmbmp.c - OS/2 1.1, 1.2, 2.0 and Windows 3.0 support
4
5Reads and writes any OS/2 1.x bitmap.
6Will also read uncompressed, RLE4 and RLE8 Windows 3.x bitmaps too.
7There are horrific file structure alignment considerations hence each
8word,dword is read individually.
9Input options: index=# (default: 0)
10
11*/
12
13/*...sincludes:0:*/
14#include <stdio.h>
15#include <ctype.h>
16#include <stddef.h>
17#include <stdlib.h>
18#include <string.h>
19#include "gbm.h"
20#include "gbmhelp.h"
21
22/*...vgbm\46\h:0:*/
23/*...vgbmhelp\46\h:0:*/
24
25#ifndef min
26#define min(a,b) (((a)<(b))?(a):(b))
27#endif
28/*...e*/
29
30/*...suseful:0:*/
31#define low_byte(w) ((byte) ((w)&0x00ff) )
32#define high_byte(w) ((byte) (((w)&0xff00)>>8))
33#define make_word(a,b) (((word)a) + (((word)b) << 8))
34
35/*...sread_word:0:*/
36static BOOLEAN read_word(int fd, word *w)
37 {
38 byte low = 0, high = 0;
39
40 if ( gbm_file_read(fd, (char *) &low, 1) != 1 )
41 return FALSE;
42 if ( gbm_file_read(fd, (char *) &high, 1) != 1 )
43 return FALSE;
44 *w = (word) (low + ((word) high << 8));
45 return TRUE;
46 }
47/*...e*/
48/*...sread_dword:0:*/
49static BOOLEAN read_dword(int fd, dword *d)
50 {
51 word low, high;
52 if ( !read_word(fd, &low) )
53 return FALSE;
54 if ( !read_word(fd, &high) )
55 return FALSE;
56 *d = low + ((dword) high << 16);
57 return TRUE;
58 }
59/*...e*/
60/*...swrite_word:0:*/
61static BOOLEAN write_word(int fd, word w)
62 {
63 byte low = (byte) w;
64 byte high = (byte) (w >> 8);
65
66 gbm_file_write(fd, &low, 1);
67 gbm_file_write(fd, &high, 1);
68 return TRUE;
69 }
70/*...e*/
71/*...swrite_dword:0:*/
72static BOOLEAN write_dword(int fd, dword d)
73 {
74 write_word(fd, (word) d);
75 write_word(fd, (word) (d >> 16));
76 return TRUE;
77 }
78/*...e*/
79/*...e*/
80
81static GBMFT bmp_gbmft =
82 {
83 "Bitmap",
84 "OS/2 1.1, 1.2, 2.0 / Windows 3.0 bitmap",
85 "BMP VGA BGA RLE DIB RL4 RL8",
86 GBM_FT_R1|GBM_FT_R4|GBM_FT_R8|GBM_FT_R24|
87 GBM_FT_W1|GBM_FT_W4|GBM_FT_W8|GBM_FT_W24,
88 };
89
90#define GBM_ERR_BMP_PLANES ((GBM_ERR) 300)
91#define GBM_ERR_BMP_BITCOUNT ((GBM_ERR) 301)
92#define GBM_ERR_BMP_CBFIX ((GBM_ERR) 302)
93#define GBM_ERR_BMP_COMP ((GBM_ERR) 303)
94#define GBM_ERR_BMP_OFFSET ((GBM_ERR) 304)
95
96typedef struct
97 {
98 dword base;
99 BOOLEAN windows;
100 dword cbFix;
101 dword ulCompression;
102 dword cclrUsed;
103 dword offBits;
104 BOOLEAN inv, invb;
105 } BMP_PRIV;
106
107#define BFT_BMAP 0x4d42
108#define BFT_BITMAPARRAY 0x4142
109#define BCA_UNCOMP 0x00000000L
110#define BCA_RLE8 0x00000001L
111#define BCA_RLE4 0x00000002L
112#define BCA_HUFFFMAN1D 0x00000003L
113#define BCA_RLE24 0x00000004L
114#define MSWCC_EOL 0
115#define MSWCC_EOB 1
116#define MSWCC_DELTA 2
117
118/*...sinvert:0:*/
119static void invert(byte *buffer, unsigned count)
120 {
121 while ( count-- )
122 *buffer++ ^= (byte) 0xffU;
123 }
124/*...e*/
125/*...sswap_pal:0:*/
126static void swap_pal(GBMRGB *gbmrgb)
127 {
128 GBMRGB tmp = gbmrgb[0];
129 gbmrgb[0] = gbmrgb[1];
130 gbmrgb[1] = tmp;
131 }
132/*...e*/
133
134/*...sbmp_qft:0:*/
135GBM_ERR bmp_qft(GBMFT *gbmft)
136 {
137 *gbmft = bmp_gbmft;
138 return GBM_ERR_OK;
139 }
140/*...e*/
141/*...sbmp_rhdr:0:*/
142GBM_ERR bmp_rhdr(const char *fn, int fd, GBM *gbm, const char *opt)
143 {
144 word usType, xHotspot, yHotspot;
145 dword cbSize, offBits, cbFix;
146 BMP_PRIV *bmp_priv = (BMP_PRIV *) gbm->priv;
147 bmp_priv->inv = ( gbm_find_word(opt, "inv" ) != NULL );
148 bmp_priv->invb = ( gbm_find_word(opt, "invb") != NULL );
149
150 fn=fn; /* Suppress 'unref arg' compiler warnings */
151
152 if ( !read_word(fd, &usType) )
153 return GBM_ERR_READ;
154 if ( usType == BFT_BITMAPARRAY )
155/*...shandle bitmap arrays:16:*/
156{
157const char *index;
158int i;
159
160if ( (index = gbm_find_word_prefix(opt, "index=")) != NULL )
161 sscanf(index + 6, "%d", &i);
162else
163 i = 0;
164
165while ( i-- > 0 )
166 {
167 dword cbSize2, offNext;
168
169 if ( !read_dword(fd, &cbSize2) )
170 return GBM_ERR_READ;
171 if ( !read_dword(fd, &offNext) )
172 return GBM_ERR_READ;
173 if ( offNext == 0L )
174 return GBM_ERR_BMP_OFFSET;
175 gbm_file_lseek(fd, (long) offNext, SEEK_SET);
176 if ( !read_word(fd, &usType) )
177 return GBM_ERR_READ;
178 if ( usType != BFT_BITMAPARRAY )
179 return GBM_ERR_BAD_MAGIC;
180 }
181gbm_file_lseek(fd, 4L + 4L + 2L + 2L, SEEK_CUR);
182if ( !read_word(fd, &usType) )
183 return GBM_ERR_READ;
184}
185/*...e*/
186
187 if ( usType != BFT_BMAP )
188 return GBM_ERR_BAD_MAGIC;
189
190 bmp_priv->base = (dword) ( gbm_file_lseek(fd, 0L, SEEK_CUR) - 2L );
191
192 if ( !read_dword(fd, &cbSize) )
193 return GBM_ERR_READ;
194 if ( !read_word(fd, &xHotspot) )
195 return GBM_ERR_READ;
196 if ( !read_word(fd, &yHotspot) )
197 return GBM_ERR_READ;
198 if ( !read_dword(fd, &offBits) )
199 return GBM_ERR_READ;
200 if ( !read_dword(fd, &cbFix) )
201 return GBM_ERR_READ;
202
203 bmp_priv->offBits = offBits;
204
205 if ( cbFix == 12 )
206/*...sOS\47\2 1\46\1\44\ 1\46\2:16:*/
207/* OS/2 1.x uncompressed bitmap */
208{
209word cx, cy, cPlanes, cBitCount;
210
211if ( !read_word(fd, &cx) )
212 return GBM_ERR_READ;
213if ( !read_word(fd, &cy) )
214 return GBM_ERR_READ;
215if ( !read_word(fd, &cPlanes) )
216 return GBM_ERR_READ;
217if ( !read_word(fd, &cBitCount) )
218 return GBM_ERR_READ;
219
220if ( cx == 0 || cy == 0 )
221 return GBM_ERR_BAD_SIZE;
222if ( cPlanes != 1 )
223 return GBM_ERR_BMP_PLANES;
224if ( cBitCount != 1 && cBitCount != 4 && cBitCount != 8 && cBitCount != 24 )
225 return GBM_ERR_BMP_BITCOUNT;
226
227gbm->w = (int) cx;
228gbm->h = (int) cy;
229gbm->bpp = (int) cBitCount;
230
231bmp_priv->windows = FALSE;
232}
233/*...e*/
234 else if ( cbFix >= 16 && cbFix <= 64 &&
235 ((cbFix & 3) == 0 || cbFix == 42 || cbFix == 46) )
236/*...sOS\47\2 2\46\0 and Windows 3\46\0:16:*/
237{
238word cPlanes, cBitCount, usUnits, usReserved, usRecording, usRendering;
239dword ulWidth, ulHeight, ulCompression;
240dword ulSizeImage, ulXPelsPerMeter, ulYPelsPerMeter;
241dword cclrUsed, cclrImportant, cSize1, cSize2, ulColorEncoding, ulIdentifier;
242BOOLEAN ok;
243
244ok = read_dword(fd, &ulWidth);
245ok &= read_dword(fd, &ulHeight);
246ok &= read_word(fd, &cPlanes);
247ok &= read_word(fd, &cBitCount);
248if ( cbFix > 16 )
249 ok &= read_dword(fd, &ulCompression);
250else
251 ulCompression = BCA_UNCOMP;
252if ( cbFix > 20 )
253 ok &= read_dword(fd, &ulSizeImage);
254if ( cbFix > 24 )
255 ok &= read_dword(fd, &ulXPelsPerMeter);
256if ( cbFix > 28 )
257 ok &= read_dword(fd, &ulYPelsPerMeter);
258if ( cbFix > 32 )
259 ok &= read_dword(fd, &cclrUsed);
260else
261 cclrUsed = ( (dword)1 << cBitCount );
262if ( cBitCount != 24 && cclrUsed == 0 )
263 cclrUsed = ( (dword)1 << cBitCount );
264
265/* Protect against badly written bitmaps! */
266if ( cclrUsed > ( (dword)1 << cBitCount ) )
267 cclrUsed = ( (dword)1 << cBitCount );
268
269if ( cbFix > 36 )
270 ok &= read_dword(fd, &cclrImportant);
271if ( cbFix > 40 )
272 ok &= read_word(fd, &usUnits);
273if ( cbFix > 42 )
274 ok &= read_word(fd, &usReserved);
275if ( cbFix > 44 )
276 ok &= read_word(fd, &usRecording);
277if ( cbFix > 46 )
278 ok &= read_word(fd, &usRendering);
279if ( cbFix > 48 )
280 ok &= read_dword(fd, &cSize1);
281if ( cbFix > 52 )
282 ok &= read_dword(fd, &cSize2);
283if ( cbFix > 56 )
284 ok &= read_dword(fd, &ulColorEncoding);
285if ( cbFix > 60 )
286 ok &= read_dword(fd, &ulIdentifier);
287
288if ( !ok )
289 return GBM_ERR_READ;
290
291if ( ulWidth == 0L || ulHeight == 0L )
292 return GBM_ERR_BAD_SIZE;
293if ( cPlanes != 1 )
294 return GBM_ERR_BMP_PLANES;
295if ( cBitCount != 1 && cBitCount != 4 && cBitCount != 8 && cBitCount != 24 )
296 return GBM_ERR_BMP_BITCOUNT;
297
298gbm->w = (int) ulWidth;
299gbm->h = (int) ulHeight;
300gbm->bpp = (int) cBitCount;
301
302bmp_priv->windows = TRUE;
303bmp_priv->cbFix = cbFix;
304bmp_priv->ulCompression = ulCompression;
305bmp_priv->cclrUsed = cclrUsed;
306}
307/*...e*/
308 else
309 return GBM_ERR_BMP_CBFIX;
310
311 return GBM_ERR_OK;
312 }
313/*...e*/
314/*...sbmp_rpal:0:*/
315GBM_ERR bmp_rpal(int fd, GBM *gbm, GBMRGB *gbmrgb)
316 {
317 BMP_PRIV *bmp_priv = (BMP_PRIV *) gbm->priv;
318
319 if ( gbm->bpp != 24 )
320 {
321 int i;
322 byte b[4];
323
324 if ( bmp_priv->windows )
325/*...sOS\47\2 2\46\0 and Windows 3\46\0:24:*/
326{
327gbm_file_lseek(fd, (long) (bmp_priv->base + 14L + bmp_priv->cbFix), SEEK_SET);
328for ( i = 0; i < (1 << gbm->bpp); i++ )
329/* Used to use bmp_priv->cclrUsed, but bitmaps have been found which have
330 their used colours not at the start of the palette. */
331 {
332 gbm_file_read(fd, b, 4);
333 gbmrgb[i].b = b[0];
334 gbmrgb[i].g = b[1];
335 gbmrgb[i].r = b[2];
336 }
337}
338/*...e*/
339 else
340/*...sOS\47\2 1\46\1\44\ 1\46\2:24:*/
341{
342gbm_file_lseek(fd, (long) (bmp_priv->base + 26L), SEEK_SET);
343for ( i = 0; i < (1 << gbm->bpp); i++ )
344 {
345 gbm_file_read(fd, b, 3);
346 gbmrgb[i].b = b[0];
347 gbmrgb[i].g = b[1];
348 gbmrgb[i].r = b[2];
349 }
350}
351/*...e*/
352 }
353
354 if ( gbm->bpp == 1 && !bmp_priv->inv )
355 swap_pal(gbmrgb);
356
357 return GBM_ERR_OK;
358 }
359/*...e*/
360/*...sbmp_rdata:0:*/
361GBM_ERR bmp_rdata(int fd, GBM *gbm, byte *data)
362 {
363 BMP_PRIV *bmp_priv = (BMP_PRIV *) gbm->priv;
364 int cLinesWorth = ((gbm->bpp * gbm->w + 31) / 32) * 4;
365
366 if ( bmp_priv->windows )
367/*...sOS\47\2 2\46\0 and Windows 3\46\0:16:*/
368{
369gbm_file_lseek(fd, (long)bmp_priv->offBits, SEEK_SET);
370
371switch ( (int) bmp_priv->ulCompression )
372 {
373/*...sBCA_UNCOMP:24:*/
374case BCA_UNCOMP:
375 gbm_file_read(fd, data, gbm->h * cLinesWorth);
376 break;
377/*...e*/
378/*...sBCA_RLE8:24:*/
379case BCA_RLE8:
380 {
381 AHEAD *ahead;
382 int x = 0, y = 0;
383 BOOLEAN eof8 = FALSE;
384
385 if ( (ahead = gbm_create_ahead(fd)) == NULL )
386 return GBM_ERR_MEM;
387
388 while ( !eof8 )
389 {
390 byte c = (byte) gbm_read_ahead(ahead);
391 byte d = (byte) gbm_read_ahead(ahead);
392/* fprintf(stderr, "(%d,%d) c=%d,d=%d\n", x, y, c, d); debug*/
393
394 if ( c )
395 {
396 memset(data, d, c);
397 x += c;
398 data += c;
399 }
400 else
401 switch ( d )
402 {
403/*...sMSWCC_EOL:56:*/
404case MSWCC_EOL:
405 {
406 int to_eol = cLinesWorth - x;
407
408 memset(data, 0, (size_t) to_eol);
409 data += to_eol;
410 x = 0;
411 if ( ++y == gbm->h )
412 eof8 = TRUE;
413 }
414 break;
415/*...e*/
416/*...sMSWCC_EOB:56:*/
417case MSWCC_EOB:
418 if ( y < gbm->h )
419 {
420 int to_eol = cLinesWorth - x;
421
422 memset(data, 0, (size_t) to_eol);
423 x = 0; y++;
424 data += to_eol;
425 while ( y < gbm->h )
426 {
427 memset(data, 0, (size_t) cLinesWorth);
428 data += cLinesWorth;
429 y++;
430 }
431 }
432 eof8 = TRUE;
433 break;
434/*...e*/
435/*...sMSWCC_DELTA:56:*/
436case MSWCC_DELTA:
437 {
438 byte dx = (byte) gbm_read_ahead(ahead);
439 byte dy = (byte) gbm_read_ahead(ahead);
440 int fill = dx + dy * cLinesWorth;
441 memset(data, 0, (size_t) fill);
442 data += fill;
443 x += dx; y += dy;
444 if ( y == gbm->h )
445 eof8 = TRUE;
446 }
447 break;
448/*...e*/
449/*...sdefault:56:*/
450default:
451 {
452 int n = (int) d;
453
454 while ( n-- > 0 )
455 *data++ = (byte) gbm_read_ahead(ahead);
456 x += d;
457if ( x > gbm->w ) { x = 0; ++y; } /* @@@AK */
458 if ( d & 1 )
459 gbm_read_ahead(ahead); /* Align */
460 }
461 break;
462/*...e*/
463 }
464 }
465
466 gbm_destroy_ahead(ahead);
467 }
468 break;
469/*...e*/
470/*...sBCA_RLE4:24:*/
471case BCA_RLE4:
472 {
473 AHEAD *ahead;
474 int x = 0, y = 0;
475 BOOLEAN eof4 = FALSE;
476 int inx = 0;
477
478 if ( (ahead = gbm_create_ahead(fd)) == NULL )
479 return GBM_ERR_MEM;
480
481 memset(data, 0, (size_t) (gbm->h * cLinesWorth));
482
483 while ( !eof4 )
484 {
485 byte c = (byte) gbm_read_ahead(ahead);
486 byte d = (byte) gbm_read_ahead(ahead);
487
488 if ( c )
489 {
490 byte h, l;
491 int i;
492 if ( x & 1 )
493 { h = (byte) (d >> 4); l = (byte) (d << 4); }
494 else
495 { h = (byte) (d&0xf0); l = (byte) (d&0x0f); }
496 for ( i = 0; i < (int) c; i++, x++ )
497 {
498 if ( x & 1U )
499 data[inx++] |= l;
500 else
501 data[inx] |= h;
502 }
503 }
504 else
505 switch ( d )
506 {
507/*...sMSWCC_EOL:56:*/
508case MSWCC_EOL:
509 x = 0;
510 if ( ++y == gbm->h )
511 eof4 = TRUE;
512 inx = cLinesWorth * y;
513 break;
514/*...e*/
515/*...sMSWCC_EOB:56:*/
516case MSWCC_EOB:
517 eof4 = TRUE;
518 break;
519/*...e*/
520/*...sMSWCC_DELTA:56:*/
521case MSWCC_DELTA:
522 {
523 byte dx = (byte) gbm_read_ahead(ahead);
524 byte dy = (byte) gbm_read_ahead(ahead);
525
526 x += dx; y += dy;
527 inx = y * cLinesWorth + (x/2);
528
529 if ( y == gbm->h )
530 eof4 = TRUE;
531 }
532 break;
533/*...e*/
534/*...sdefault:56:*/
535default:
536 {
537 int i, nr = 0;
538
539 if ( x & 1 )
540 {
541 for ( i = 0; i+2 <= (int) d; i += 2 )
542 {
543 byte b = (byte) gbm_read_ahead(ahead);
544 data[inx++] |= (b >> 4);
545 data[inx ] |= (b << 4);
546 nr++;
547 }
548 if ( i < (int) d )
549 {
550 data[inx++] |= ((byte) gbm_read_ahead(ahead) >> 4);
551 nr++;
552 }
553 }
554 else
555 {
556 for ( i = 0; i+2 <= (int) d; i += 2 )
557 {
558 data[inx++] = (byte) gbm_read_ahead(ahead);
559 nr++;
560 }
561 if ( i < (int) d )
562 {
563 data[inx] = (byte) gbm_read_ahead(ahead);
564 nr++;
565 }
566 }
567 x += d;
568
569 if ( nr & 1 )
570 gbm_read_ahead(ahead); /* Align input stream to next word */
571 }
572 break;
573/*...e*/
574 }
575 }
576
577 gbm_destroy_ahead(ahead);
578 }
579 break;
580/*...e*/
581/*...sdefault:24:*/
582default:
583 return GBM_ERR_BMP_COMP;
584/*...e*/
585 }
586}
587/*...e*/
588 else
589/*...sOS\47\2 1\46\1\44\ 1\46\2:16:*/
590{
591gbm_file_lseek(fd, (long) bmp_priv->offBits, SEEK_SET);
592gbm_file_read(fd, data, cLinesWorth * gbm->h);
593}
594/*...e*/
595
596 if ( bmp_priv->invb )
597 invert(data, (unsigned) (cLinesWorth * gbm->h));
598
599 return GBM_ERR_OK;
600 }
601/*...e*/
602/*...sbmp_w:0:*/
603/*...sbright:0:*/
604static int bright(const GBMRGB *gbmrgb)
605 {
606 return gbmrgb->r*30+gbmrgb->g*60+gbmrgb->b*10;
607 }
608/*...e*/
609/*...swrite_inv:0:*/
610static int write_inv(int fd, const byte *buffer, int count)
611 {
612 byte small_buf[1024];
613 int so_far = 0, this_go, written;
614
615 while ( so_far < count )
616 {
617 this_go = min(count - so_far, 1024);
618 memcpy(small_buf, buffer + so_far, (size_t) this_go);
619 invert(small_buf, (unsigned) this_go);
620 if ( (written = gbm_file_write(fd, small_buf, this_go)) != this_go )
621 return so_far + written;
622 so_far += written;
623 }
624
625 return so_far;
626 }
627/*...e*/
628
629GBM_ERR bmp_w(const char *fn, int fd, const GBM *gbm, const GBMRGB *gbmrgb, const byte *data, const char *opt)
630 {
631 BOOLEAN pm11 = ( gbm_find_word(opt, "1.1" ) != NULL );
632 BOOLEAN win = ( gbm_find_word(opt, "win" ) != NULL ||
633 gbm_find_word(opt, "2.0" ) != NULL );
634 BOOLEAN inv = ( gbm_find_word(opt, "inv" ) != NULL );
635 BOOLEAN invb = ( gbm_find_word(opt, "invb" ) != NULL );
636 BOOLEAN darkfg = ( gbm_find_word(opt, "darkfg" ) != NULL );
637 BOOLEAN lightfg = ( gbm_find_word(opt, "lightfg") != NULL );
638 int cRGB;
639 GBMRGB gbmrgb_1bpp[2];
640
641 if ( pm11 && win )
642 return GBM_ERR_BAD_OPTION;
643
644 fn=fn; /* Suppress 'unref arg' compiler warning */
645
646 cRGB = ( (1 << gbm->bpp) & 0x1ff );
647 /* 1->2, 4->16, 8->256, 24->0 */
648
649 if ( cRGB == 2 )
650/*...shandle messy 1bpp case:16:*/
651{
652/*
653The palette entries inside a 1bpp PM bitmap are not honored, or handled
654correctly by most programs. Current thinking is that they have no actual
655meaning. Under OS/2 PM, bitmap 1's re fg and 0's are bg, and it is the job of
656the displayer to pick fg and bg. We will pick fg=black, bg=white in the bitmap
657file we save. If we do not write black and white, we find that most programs
658will incorrectly honor these entries giving unpredicatable (and often black on
659a black background!) results.
660*/
661
662gbmrgb_1bpp[0].r = gbmrgb_1bpp[0].g = gbmrgb_1bpp[0].b = 0xff;
663gbmrgb_1bpp[1].r = gbmrgb_1bpp[1].g = gbmrgb_1bpp[1].b = 0x00;
664
665/*
666We observe these values must be the wrong way around to keep most PM
667programs happy, such as WorkPlace Shell WPFolder backgrounds.
668*/
669
670if ( !inv )
671 swap_pal(gbmrgb_1bpp);
672
673/*
674If the user has picked the darkfg option, then they intend that the darkest
675colour in the image is to be the foreground. This is a very sensible option
676because the foreground will appear to be black when the image is reloaded.
677To acheive this we must invert the bitmap bits, if the palette dictates.
678*/
679
680if ( darkfg && bright(&gbmrgb[0]) < bright(&gbmrgb[1]) )
681 invb = !invb;
682if ( lightfg && bright(&gbmrgb[0]) >= bright(&gbmrgb[1]) )
683 invb = !invb;
684
685gbmrgb = gbmrgb_1bpp;
686}
687/*...e*/
688
689 if ( pm11 )
690/*...sOS\47\2 1\46\1:16:*/
691{
692word usType = BFT_BMAP;
693word xHotspot = 0;
694word yHotspot = 0;
695dword cbFix = (dword) 12;
696word cx = (word) gbm->w;
697word cy = (word) gbm->h;
698word cPlanes = (word) 1;
699word cBitCount = (word) gbm->bpp;
700int cLinesWorth = (((cBitCount * cx + 31) / 32) * cPlanes) * 4;
701dword offBits = (dword) 26 + cRGB * (dword) 3;
702dword cbSize = offBits + (dword) cy * (dword) cLinesWorth;
703int i, total, actual;
704
705write_word(fd, usType);
706write_dword(fd, cbSize);
707write_word(fd, xHotspot);
708write_word(fd, yHotspot);
709write_dword(fd, offBits);
710write_dword(fd, cbFix);
711write_word(fd, cx);
712write_word(fd, cy);
713write_word(fd, cPlanes);
714write_word(fd, cBitCount);
715
716for ( i = 0; i < cRGB; i++ )
717 {
718 byte b[3];
719
720 b[0] = gbmrgb[i].b;
721 b[1] = gbmrgb[i].g;
722 b[2] = gbmrgb[i].r;
723 if ( gbm_file_write(fd, b, 3) != 3 )
724 return GBM_ERR_WRITE;
725 }
726
727total = gbm->h * cLinesWorth;
728if ( invb )
729 actual = write_inv(fd, data, total);
730else
731 actual = gbm_file_write(fd, data, total);
732if ( actual != total )
733 return GBM_ERR_WRITE;
734}
735/*...e*/
736 else
737/*...sOS\47\2 2\46\0 and Windows 3\46\0:16:*/
738{
739word usType = BFT_BMAP;
740word xHotspot = 0;
741word yHotspot = 0;
742dword cbFix = (dword) 40;
743dword cx = (dword) gbm->w;
744dword cy = (dword) gbm->h;
745word cPlanes = (word) 1;
746word cBitCount = (word) gbm->bpp;
747int cLinesWorth = (((cBitCount * (int) cx + 31) / 32) * cPlanes) * 4;
748dword offBits = (dword) 54 + cRGB * (dword) 4;
749dword cbSize = offBits + (dword) cy * (dword) cLinesWorth;
750dword ulCompression = BCA_UNCOMP;
751dword cbImage = (dword) cLinesWorth * (dword) gbm->h;
752dword cxResolution = 0;
753dword cyResolution = 0;
754dword cclrUsed = 0;
755dword cclrImportant = 0;
756int i, total, actual;
757
758write_word(fd, usType);
759write_dword(fd, cbSize);
760write_word(fd, xHotspot);
761write_word(fd, yHotspot);
762write_dword(fd, offBits);
763
764write_dword(fd, cbFix);
765write_dword(fd, cx);
766write_dword(fd, cy);
767write_word(fd, cPlanes);
768write_word(fd, cBitCount);
769write_dword(fd, ulCompression);
770write_dword(fd, cbImage);
771write_dword(fd, cxResolution);
772write_dword(fd, cyResolution);
773write_dword(fd, cclrUsed);
774write_dword(fd, cclrImportant);
775
776for ( i = 0; i < cRGB; i++ )
777 {
778 byte b[4];
779
780 b[0] = gbmrgb[i].b;
781 b[1] = gbmrgb[i].g;
782 b[2] = gbmrgb[i].r;
783 b[3] = 0;
784 if ( gbm_file_write(fd, b, 4) != 4 )
785 return GBM_ERR_WRITE;
786 }
787
788total = gbm->h * cLinesWorth;
789if ( invb )
790 actual = write_inv(fd, data, total);
791else
792 actual = gbm_file_write(fd, data, total);
793if ( actual != total )
794 return GBM_ERR_WRITE;
795}
796/*...e*/
797
798 return GBM_ERR_OK;
799 }
800/*...e*/
801/*...sbmp_err:0:*/
802const char *bmp_err(GBM_ERR rc)
803 {
804 switch ( (int) rc )
805 {
806 case GBM_ERR_BMP_PLANES:
807 return "number of bitmap planes is not 1";
808 case GBM_ERR_BMP_BITCOUNT:
809 return "bit count not 1, 4, 8 or 24";
810 case GBM_ERR_BMP_CBFIX:
811 return "cbFix bad";
812 case GBM_ERR_BMP_COMP:
813 return "compression type not uncompressed, RLE4 or RLE8";
814 case GBM_ERR_BMP_OFFSET:
815 return "less bitmaps in file than index requested";
816 }
817 return NULL;
818 }
819/*...e*/
Note: See TracBrowser for help on using the repository browser.