ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/abitmapio.cpp
Revision: 2.2
Committed: Sat Aug 24 23:25:24 2024 UTC (8 months, 1 week ago) by greg
Branch: MAIN
CVS Tags: HEAD
Changes since 2.1: +3 -0 lines
Log Message:
chore: Added RCS tags to files

File Contents

# User Rev Content
1 greg 2.2 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4 greg 2.1 /*
5     * abitmapio.cpp
6     * panlib
7     *
8     * BitMap class file i/o using BMP format.
9     *
10     * Created by Greg Ward on 6/30/16.
11     * Copyright 2016 Anyhere Software. All rights reserved.
12     *
13     */
14    
15     #include <stdio.h>
16     #include <stdlib.h>
17     #include <string.h>
18     #include "abitmap.h"
19     #include "bmpfile.h"
20     #include "dmessage.h"
21    
22     static const char BitMap1Dmagic[] = "1-D BitMap";
23     static const char BitMap2Dmagic[] = "2-D BitMap";
24    
25     // Function to write a bitmap to a BMP file
26     bool
27     WriteBitMap(const ABitMap &bm, const char *fname)
28     {
29     if (!bm.Length() || fname == NULL || !*fname)
30     return false;
31     if (bm.Length() >= 1L<<31) {
32     DMESG(DMCparameter, "BitMap too long to write as one scanline");
33     return false;
34     }
35     BMPHeader * hdr = BMPmappedHeader(bm.Length(), 1, 16, 2);
36     if (hdr == NULL) {
37     DMESG(DMCparameter, "Cannot create BMP header");
38     return false;
39     }
40     strncpy(BMPinfo(hdr), BitMap1Dmagic, 16);
41    
42     BMPWriter * wtr = BMPopenOutputFile(fname, hdr);
43     if (wtr == NULL) {
44     DMESGF(DMCresource, "Cannot open BMP output file '%s'", fname);
45     free(hdr);
46     return false;
47     }
48     DMESGF(DMCtrace, "Writing 1-D bitmap to '%s'", fname);
49    
50     memset(wtr->scanline, 0, (bm.Length()+7)>>3);
51     for (uint32 i = 0; bm.Find(&i); i++)
52     wtr->scanline[i>>3] |= 128>>(i&7);
53    
54     int rval = BMPwriteScanline(wtr);
55    
56     BMPcloseOutput(wtr);
57    
58     if (rval != BIR_OK) {
59     DMESG(DMCdata, BMPerrorMessage(rval));
60     return false;
61     }
62     return true;
63     }
64    
65     // Function to write a 2-D bitmap to a BMP file
66     bool
67     WriteBitMap2(const ABitMap2 &bm2, const char *fname)
68     {
69     if (!bm2.Width() | !bm2.Height() || fname == NULL || !*fname)
70     return false;
71    
72     BMPHeader * hdr = BMPmappedHeader(bm2.Width(), bm2.Height(), 16, 2);
73     if (hdr == NULL) {
74     DMESG(DMCparameter, "Cannot create BMP header");
75     return false;
76     }
77     strncpy(BMPinfo(hdr), BitMap2Dmagic, 16);
78     hdr->yIsDown = 1; // sane scanline ordering
79    
80     BMPWriter * wtr = BMPopenOutputFile(fname, hdr);
81     if (wtr == NULL) {
82     DMESGF(DMCresource, "Cannot open BMP output file '%s'", fname);
83     free(hdr);
84     return false;
85     }
86     DMESGF(DMCtrace, "Writing 2-D bitmap to '%s'", fname);
87     int rval = BIR_OK;
88     int my = 0;
89     for (int y = 0; y < bm2.Height(); y++) {
90     memset(wtr->scanline, 0, (bm2.Width()+7)>>3);
91     while (y < my) { // write empty scanlines
92     if ((rval = BMPwriteScanline(wtr)) != BIR_OK)
93     break;
94     ++y;
95     }
96     if ((rval != BIR_OK) | (y >= bm2.Height()))
97     break;
98     for (int x = 0; bm2.Find(&x, &my) && my == y; x++)
99     wtr->scanline[x>>3] |= 128>>(x&7);
100    
101     if ((rval = BMPwriteScanline(wtr)) != BIR_OK)
102     break;
103     }
104     BMPcloseOutput(wtr);
105    
106     if (rval != BIR_OK) {
107     DMESG(DMCdata, BMPerrorMessage(rval));
108     return false;
109     }
110     return true;
111     }
112    
113     // Function to read a bitmap from a BMP file
114     bool
115     ReadBitMap(ABitMap *bmp, const char *fname)
116     {
117     if (bmp == NULL || fname == NULL || !*fname)
118     return false;
119     // open call reads 1st scanline
120     BMPReader * rdr = BMPopenInputFile(fname);
121    
122     if (rdr == NULL) {
123     DMESGF(DMCresource, "Cannot open BMP input file '%s'", fname);
124     return false;
125     }
126     if (rdr->hdr->nColors > 2) {
127     DMESGF(DMCdata, "BMP input file '%s' is not a bitmap", fname);
128     BMPcloseInput(rdr);
129     return false;
130     }
131     if (rdr->hdr->height != 1) {
132     DMESGF(DMCdata, "BMP input file '%s' has more than one scan line", fname);
133     BMPcloseInput(rdr);
134     return false;
135     }
136     if (rdr->hdr->infoSiz <= 0 ||
137     strncmp(BMPinfo(rdr->hdr), BitMap1Dmagic, rdr->hdr->infoSiz))
138     DMESGF(DMCwarning, "BMP file '%s' not flagged as 1-D bitmap", fname);
139    
140     DASSERT(rdr->yscan == 0);
141     DMESGF(DMCtrace, "Reading 1-D bitmap from '%s'", fname);
142     bmp->NewBitMap(rdr->hdr->width);
143     for (uint32 i = rdr->hdr->width; i--; )
144     if (rdr->scanline[i>>3] & 128>>(i&7))
145     bmp->Set(i);
146     if (rdr->hdr->palette[0].g >= 128)
147     bmp->Invert(); // against normal convention!
148     BMPcloseInput(rdr);
149     return true;
150     }
151    
152     // Function to read a 2-D bitmap from a BMP file
153     bool
154     ReadBitMap2(ABitMap2 *bm2p, const char *fname)
155     {
156     if (bm2p == NULL || fname == NULL || !*fname)
157     return false;
158    
159     BMPReader * rdr = BMPopenInputFile(fname);
160    
161     if (rdr == NULL) {
162     DMESGF(DMCresource, "Cannot open BMP input file '%s'", fname);
163     return false;
164     }
165     if (rdr->hdr->nColors > 2) {
166     DMESGF(DMCdata, "BMP input file '%s' is not a bitmap", fname);
167     BMPcloseInput(rdr);
168     return false;
169     }
170     if (rdr->hdr->infoSiz <= 0 ||
171     strncmp(BMPinfo(rdr->hdr), BitMap2Dmagic, rdr->hdr->infoSiz))
172     DMESGF(DMCwarning, "BMP file '%s' not flagged as 2-D bitmap", fname);
173    
174     int y, rval = BIR_OK;
175     bm2p->NewBitMap(rdr->hdr->width, rdr->hdr->height);
176     DMESGF(DMCtrace, "Reading 2-D bitmap from '%s'", fname);
177     for (y = 0; y < rdr->hdr->height; y++) {
178     const int my = rdr->hdr->yIsDown ? y
179     : rdr->hdr->height-1 - y;
180     while (rdr->yscan < y && (rval = BMPreadScanline(rdr)) == BIR_OK)
181     ;
182     if (rval != BIR_OK)
183     break;
184     for (uint32 x = rdr->hdr->width; x--; )
185     if (rdr->scanline[x>>3] & 128>>(x&7))
186     bm2p->Set(x, my);
187     }
188     if (rval == BIR_OK && rdr->hdr->palette[0].g >= 128)
189     bm2p->Invert(); // against normal convention!
190     BMPcloseInput(rdr);
191    
192     if (rval != BIR_OK) {
193     bm2p->NewBitMap(0,0);
194     sprintf(dmessage_buf, "%s at y==%d", BMPerrorMessage(rval), y);
195     DMESG(DMCdata, dmessage_buf);
196     return false;
197     }
198     return true;
199     }