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