ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/abitmapio.cpp
Revision: 2.1
Committed: Wed Aug 14 20:05:23 2024 UTC (8 months, 2 weeks ago) by greg
Branch: MAIN
Log Message:
feat(rxpict): Added new C++ picture rendering tool with multi-processing and spectral output

File Contents

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