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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
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 }