Alamo
PNG.H
Go to the documentation of this file.
1
2#include <string.h>
3
4#include "Set/Set.H"
5#include "IO/ParmParse.H"
6#include "Util/Util.H"
7#include "Unit/Unit.H"
8
9#ifndef ALAMO_NOPNG
10#include <png.h>
11#endif
12
13namespace Util
14{
15class PNG
16{
17public:
18 PNG() {}
19 PNG(IO::ParmParse &pp,std::string name)
20 {pp.queryclass(name, *this);}
22 {
23#ifndef ALAMO_NOPNG
24 for (int y = 0; y < png_height; y++) {
25 free(row_pointers[y]);
26 }
27 free(row_pointers);
28#endif
29 }
30
31 //enum Type {XYZ, XY, YZ, XZ};
33 enum Channel { R = 0, G = 1, B = 2, A = 3 };
34
35 static void Parse(PNG &value, IO::ParmParse &pp)
36 {
37#ifndef ALAMO_NOPNG
38
39 std::string filename;
40 pp_query_file("filename", filename); // BMP filename.
41
42 std::string fit = "stretch";
43 // how to position the image
44 pp_query_validate("fit", fit, {"stretch","fitheight","fitwidth","coord"});
45 if (fit == "stretch") value.fit = Fit::Stretch;
46 else if (fit == "fitheight") value.fit = Fit::FitHeight;
47 else if (fit == "fitwidth") value.fit = Fit::FitWidth;
48 else if (fit == "coord")
49 {
50 value.fit = Fit::Coord;
51 // Lower-left coordinates of image in domain
52 pp_queryarr("coord.lo", value.coord_lo,Unit::Length());
53 // Upper-right coordinates of image in domain
54 pp_queryarr("coord.hi", value.coord_hi,Unit::Length());
55 }
56 else Util::Abort(INFO);
57
58 // Desired minimum value to scale pixels by
59 pp_query_default("min", value.min, 0.0 );
60 // Desired maximum value to scale pixels by
61 pp_query_default("max", value.max, 255.0);
62
63 //
64 //
65 // Now, read in the PNG
66 //
67 //
68
69
70 FILE* fp = std::fopen(filename.c_str(), "rb");
71
72 if (fp == NULL) Util::Abort(INFO, "Cannot find file", filename);
73
74 png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
75 if (!png) Util::Abort(INFO);
76
77 png_infop info = png_create_info_struct(png);
78 if (!info) Util::Abort(INFO);
79
80 if (setjmp(png_jmpbuf(png))) Util::Abort(INFO);
81
82
83 png_init_io(png, fp);
84
85 png_read_info(png, info);
86
87 value.png_width = png_get_image_width(png, info);
88 value.png_height = png_get_image_height(png, info);
89 value.color_type = png_get_color_type(png, info);
90 value.bit_depth = png_get_bit_depth(png, info);
91
92 if (value.bit_depth == 16)
93 png_set_strip_16(png);
94
95 if (value.color_type == PNG_COLOR_TYPE_PALETTE)
96 png_set_palette_to_rgb(png);
97
98 if (value.color_type == PNG_COLOR_TYPE_GRAY && value.bit_depth < 8)
99 png_set_expand_gray_1_2_4_to_8(png);
100
101 if (png_get_valid(png, info, PNG_INFO_tRNS))
102 png_set_tRNS_to_alpha(png);
103
104 if (value.color_type == PNG_COLOR_TYPE_RGB ||
105 value.color_type == PNG_COLOR_TYPE_GRAY ||
106 value.color_type == PNG_COLOR_TYPE_PALETTE)
107 png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
108
109 if (value.color_type == PNG_COLOR_TYPE_GRAY ||
110 value.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
111 png_set_gray_to_rgb(png);
112
113 png_read_update_info(png, info);
114
115 if (value.row_pointers) Util::Abort(INFO);
116
117 value.row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * value.png_height);
118 for (int y = 0; y < value.png_height; y++) {
119 value.row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png, info));
120 }
121
122 png_read_image(png, value.row_pointers);
123
124 fclose(fp);
125
126 png_destroy_read_struct(&png, &info, NULL);
127#else
128 Util::IgnoreUnused(value,pp);
129 Util::Abort(INFO,"PNG is disabled");
130#endif
131
132 }
134 {
135#ifndef ALAMO_NOPNG
136 domain_lo = _lo;
137 domain_hi = _hi;
138 domain_defined = false;
139#else
140 Util::IgnoreUnused(_lo,_hi);
141#endif
142 }
143
144 [[nodiscard]]
145 std::array<int, 4> operator() (int I, int J)
146 {
147#ifndef ALAMO_NOPNG
148 std::array<int, 4> ret;
149 png_bytep px = &row_pointers[J][I * 4];
150 ret = { px[0], px[1], px[2], px[3] };
151 return ret;
152#else
154#endif
155 }
156
157 [[nodiscard]]
158 std::array<Set::Scalar, 4> operator()(Set::Vector &x)
159 {
160#ifndef ALAMO_NOPNG
161 Util::Assert(INFO, TEST(row_pointers), "Running IC without initialization...");
162
163 std::array<Set::Scalar, 4> ret;
164
165 Set::Scalar img_width = (Set::Scalar)(png_width - 1);
166 Set::Scalar img_height = (Set::Scalar)(png_height - 1);
167 Set::Scalar img_dx = 1.0;
168 Set::Scalar img_dy = 1.0;
169
170 //Set::Scalar x, y;
171 Set::Vector ximg;
172
173 if (fit == Fit::Stretch)
174 {
175 ximg(0) = (x(0) - domain_lo(0)) / (domain_hi(0) - domain_lo(0));
176 ximg(1) = (x(1) - domain_lo(1)) / (domain_hi(1) - domain_lo(1));
177 }
178 else if (fit == Fit::FitWidth)
179 {
180 Set::Scalar aspect_ratio = img_width / img_height;
181 ximg(0) = (x(0) - domain_lo(0)) / (domain_hi(0) - domain_lo(0));
182 ximg(1) = (x(1) - domain_lo(1)) / (domain_hi(1) - domain_lo(1));
183 ximg(1) -= 0.5 - 0.5 / aspect_ratio;
184 ximg(1) *= aspect_ratio;
185 }
186 else if (fit == Fit::FitHeight)
187 {
188 Set::Scalar aspect_ratio = img_height / img_width;
189 ximg(0) = (x(0) - domain_lo(0)) / (domain_hi(0) - domain_lo(0));
190 ximg(1) = (x(1) - domain_lo(1)) / (domain_hi(1) - domain_lo(1));
191 ximg(0) -= 0.5 - 0.5 / aspect_ratio;
192 ximg(0) *= aspect_ratio;
193 }
194 else if (fit == Fit::Coord)
195 {
196 ximg(0) = (x(0) - coord_lo(0)) / (coord_hi(0) - coord_lo(0));
197 ximg(1) = (x(1) - coord_lo(1)) / (coord_hi(1) - coord_lo(1));
198 }
199
200
201
202 ximg(0) = std::min(ximg(0), 1.0); ximg(1) = std::min(ximg(1), 1.0);
203 ximg(0) = std::max(ximg(0), 0.0); ximg(1) = std::max(ximg(1), 0.0);
204
205 ximg(0) *= img_width;
206 ximg(1) *= img_height;
207
208 int I = (int)(ximg(0));
209 int J = (int)(ximg(1));
210
211 Set::Scalar x1 = I * img_dx, x2 = (I + 1) * img_dx;
212 Set::Scalar y1 = J * img_dy, y2 = (J + 1) * img_dy;
213
214
215 for (int channel = 0; channel < 4; channel++)
216 {
217
218 if (I > 0 && I < png_width - 1 &&
219 J>0 && J < png_height - 1)
220 {
221 png_bytep px_sw = &(row_pointers[J][I * 4]);
222 png_bytep px_se = &(row_pointers[J][(I + 1) * 4]);
223 png_bytep px_nw = &(row_pointers[J + 1][I * 4]);
224 png_bytep px_ne = &(row_pointers[J + 1][(I + 1) * 4]);
225
226
227 Set::Scalar fQ11 = ((Set::Scalar)(px_sw[channel]) - min) / (max - min);
228 Set::Scalar fQ12 = ((Set::Scalar)(px_nw[channel]) - min) / (max - min);
229 Set::Scalar fQ21 = ((Set::Scalar)(px_se[channel]) - min) / (max - min);
230 Set::Scalar fQ22 = ((Set::Scalar)(px_ne[channel]) - min) / (max - min);
231
232 ret[channel] = (
233 fQ11 * (x2 - ximg(0)) * (y2 - ximg(1)) +
234 fQ21 * (ximg(0) - x1) * (y2 - ximg(1)) +
235 fQ12 * (x2 - ximg(0)) * (ximg(1) - y1) +
236 fQ22 * (ximg(0) - x1) * (ximg(1) - y1)) / (img_dx * img_dy);
237
238 }
239 else if ((I == 0 || I == png_width - 1) && J < png_height - 1)
240 {
241 png_bytep px_sw = &(row_pointers[J][I * 4]);
242 png_bytep px_nw = &(row_pointers[J + 1][I * 4]);
243
244 Set::Scalar fQ11 = ((Set::Scalar)(px_sw[channel]) - min) / (max - min);
245 Set::Scalar fQ12 = ((Set::Scalar)(px_nw[channel]) - min) / (max - min);
246 ret[channel] = fQ11 + (fQ12 - fQ11) * (ximg(1) - y1);
247 }
248 else if (I < png_width - 1 && (J == 0 || J == png_height - 1))
249 {
250 png_bytep px_sw = &(row_pointers[J][I * 4]);
251 png_bytep px_se = &(row_pointers[J][(I + 1) * 4]);
252
253 Set::Scalar fQ11 = ((Set::Scalar)(px_sw[channel]) - min) / (max - min);
254 Set::Scalar fQ21 = ((Set::Scalar)(px_se[channel]) - min) / (max - min);
255 ret[channel] = fQ11 + (fQ21 - fQ11) * (ximg(0) - x1);
256 }
257 else if (I == png_width - 1 && J == png_height - 1)
258 {
259 png_bytep px_sw = &(row_pointers[J][I * 4]);
260
261 Set::Scalar fQ11 = ((Set::Scalar)(px_sw[channel]) - min) / (max - min);
262 ret[channel] = fQ11;
263 }
264 else
265 {
266 ret[channel] = 0.0;
267 }
268 }
269 return ret;
270#else
272 return {NAN,NAN,NAN,NAN};
273#endif
274 }
275
276private:
277
278#ifndef ALAMO_NOPNG
280 png_byte color_type;
281 png_byte bit_depth;
282 png_bytep* row_pointers = NULL;
283 Set::Vector coord_lo = Set::Vector::Zero();
284 Set::Vector coord_hi = Set::Vector::Zero();
285
286 //Util::BMP bmp;
288 Set::Scalar min = NAN, max = NAN;
289
290 bool domain_defined = false;
291 Set::Vector domain_lo = Set::Vector::Zero();
292 Set::Vector domain_hi = Set::Vector::Zero();
293#endif
294
295};
296
297}
#define pp_query_validate(...)
Definition ParmParse.H:103
#define pp_queryarr(...)
Definition ParmParse.H:105
#define pp_query_file(...)
Definition ParmParse.H:104
#define pp_query_default(...)
Definition ParmParse.H:102
#define TEST(x)
Definition Util.H:22
#define INFO
Definition Util.H:21
void queryclass(std::string name, T *value)
Definition ParmParse.H:934
Set::Vector domain_lo
Definition PNG.H:291
PNG(IO::ParmParse &pp, std::string name)
Definition PNG.H:19
~PNG()
Definition PNG.H:21
std::array< Set::Scalar, 4 > operator()(Set::Vector &x)
Definition PNG.H:158
@ Coord
Definition PNG.H:32
@ FitWidth
Definition PNG.H:32
@ Stretch
Definition PNG.H:32
@ FitHeight
Definition PNG.H:32
Fit fit
Definition PNG.H:287
int png_height
Definition PNG.H:279
bool domain_defined
Definition PNG.H:290
Set::Scalar min
Definition PNG.H:288
PNG()
Definition PNG.H:18
int png_width
Definition PNG.H:279
Set::Vector coord_hi
Definition PNG.H:284
Set::Scalar max
Definition PNG.H:288
Channel
Definition PNG.H:33
@ A
Definition PNG.H:33
@ G
Definition PNG.H:33
@ R
Definition PNG.H:33
@ B
Definition PNG.H:33
Set::Vector coord_lo
Definition PNG.H:283
png_byte bit_depth
Definition PNG.H:281
Set::Vector domain_hi
Definition PNG.H:292
void setDomain(Set::Vector &_lo, Set::Vector &_hi)
Definition PNG.H:133
static void Parse(PNG &value, IO::ParmParse &pp)
Definition PNG.H:35
std::array< int, 4 > operator()(int I, int J)
Definition PNG.H:145
png_byte color_type
Definition PNG.H:280
png_bytep * row_pointers
Definition PNG.H:282
amrex::Real Scalar
Definition Base.H:18
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
A collection of utility routines.
Definition Set.cpp:8
void Abort(const char *msg)
Definition Util.cpp:225
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void IgnoreUnused(const Ts &...)
Definition Util.H:355
std::string filename
Definition Util.cpp:21
AMREX_FORCE_INLINE void Assert(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:55
static Unit Length()
Definition Unit.H:188