16 #include "config_pfm.h"
18 #include "pfmVizzer.h"
21 #include "texturePool.h"
22 #include "pointerTo.h"
23 #include "string_utils.h"
24 #include "pandaFileStream.h"
33 _no_data_nan_num_channels = 0;
34 _got_transform =
false;
40 set_program_brief(
"transform .pfm files");
41 set_program_description
42 (
"pfm-trans reads an pfm file and transforms it, filters it, "
43 "operates on it, writing the output to another pfm file. A pfm "
44 "file contains a 2-d table of floating-point values.");
48 "Treats (0,0,0) in the pfm file as a special don't-touch value.",
49 &PfmTrans::dispatch_none, &_got_zero_special);
52 (
"nan",
"num_channels", 0,
53 "Treats a NaN in any of the first num_channels channels as a special don't-touch value.",
54 &PfmTrans::dispatch_int, &_got_no_data_nan, &_no_data_nan_num_channels);
57 (
"resize",
"width,height", 0,
58 "Resamples the pfm file to scale it to the indicated grid size. "
59 "A simple box filter is applied during the scale. Don't confuse this "
60 "with -TS, which scales the individual point values, but doesn't "
61 "change the number of points.",
62 &PfmTrans::dispatch_int_pair, &_got_resize, &_resize);
65 (
"crop",
"xbegin,xend,ybegin,yend", 0,
66 "Crops the pfm file to the indicated subregion.",
67 &PfmTrans::dispatch_int_quad, &_got_crop, &_crop);
71 "Automatically crops to the smallest possible rectangle that includes "
72 "all points. Requires -z or -nan.",
73 &PfmTrans::dispatch_none, &_got_autocrop);
76 (
"rotate",
"degrees", 0,
77 "Rotates the pfm file the specified number of degrees counterclockwise, "
78 "which must be a multiple of 90.",
79 &PfmTrans::dispatch_int, NULL, &_rotate);
83 "Flips the pfm file about the x axis.",
84 &PfmTrans::dispatch_none, &_got_mirror_x);
88 "Flips the pfm file about the y axis.",
89 &PfmTrans::dispatch_none, &_got_mirror_y);
93 "Specify the filename to which the resulting pfm file will be written. "
94 "This is only valid when there is only one input pfm file on the command "
95 "line. If you want to process multiple files simultaneously, you must "
97 &PfmTrans::dispatch_filename, &_got_output_filename, &_output_filename);
101 "Specify the name of the directory in which to write the processed pfm "
102 "files. If you are processing only one pfm file, this may be omitted "
103 "in lieu of the -o option.",
104 &PfmTrans::dispatch_filename, &_got_output_dirname, &_output_dirname);
107 (
"vis",
"filename.bam", 60,
108 "Generates a bam file that represents a visualization of the pfm file "
109 "as a 3-D geometric mesh. If -vistex is specified, the mesh is "
111 &PfmTrans::dispatch_filename, &_got_vis_filename, &_vis_filename);
115 "Inverts the visualization, generating a uniform 2-d mesh with the "
116 "3-d depth values encoded in the texture coordinates.",
117 &PfmTrans::dispatch_none, &_got_vis_inverse);
121 "Respect only the first two components of each depth value, ignoring z.",
122 &PfmTrans::dispatch_none, &_got_vis_2d);
125 (
"vistex",
"texture.jpg", 60,
126 "Specifies the name of the texture to apply to the visualization.",
127 &PfmTrans::dispatch_filename, &_got_vistex_filename, &_vistex_filename);
130 (
"ls",
"filename.txt", 60,
131 "Lists the points in the file to the indicated text file.",
132 &PfmTrans::dispatch_filename, &_got_ls_filename, &_ls_filename);
143 if ((
int)(_rotate / 90) * 90 != _rotate) {
144 nout <<
"-rotate can only accept a multiple of 90 degrees.\n";
148 if (_got_vis_filename) {
152 Filenames::const_iterator fi;
153 for (fi = _input_filenames.begin(); fi != _input_filenames.end(); ++fi) {
155 if (!file.
read(*fi)) {
156 nout <<
"Cannot read " << *fi <<
"\n";
164 if (_got_vis_filename) {
177 if (_got_no_data_nan) {
179 }
else if (_got_zero_special) {
186 _got_crop = file.
calc_autocrop(_crop[0], _crop[1], _crop[2], _crop[3]);
190 file.
apply_crop(_crop[0], _crop[1], _crop[2], _crop[3]);
194 file.
resize(_resize[0], _resize[1]);
198 int r = (_rotate / 90) % 4;
207 file.
flip(
true,
false,
true);
215 file.
flip(
true,
false,
false);
216 file.
flip(
false,
true,
false);
220 file.
flip(
false,
true,
true);
223 nassertr(
false,
false);
228 file.
flip(
true,
false,
false);
232 file.
flip(
false,
true,
false);
235 if (_got_transform) {
236 file.
xform(LCAST(PN_float32, _transform));
239 if (_got_vis_filename) {
241 if (_got_vistex_filename) {
244 nout <<
"Couldn't find " << _vistex_filename <<
"\n";
246 tex->set_minfilter(SamplerState::FT_linear_mipmap_linear);
248 if (tex->has_alpha(tex->get_format())) {
257 if (_got_ls_filename) {
261 for (
int yi = 0; yi < file.
get_y_size(); ++yi) {
262 for (
int xi = 0; xi < file.
get_x_size(); ++xi) {
264 out <<
"(" << xi <<
", " << yi <<
"):";
276 if (_got_output_filename) {
277 output_filename = _output_filename;
278 }
else if (_got_output_dirname) {
282 if (!output_filename.empty()) {
283 return file.
write(output_filename);
300 (
"TS",
"sx[,sy,sz]", 49,
301 "Scale the model uniformly by the given factor (if only one number "
302 "is given) or in each axis by sx, sy, sz (if three numbers are given).",
303 &PfmTrans::dispatch_scale, &_got_transform, &_transform);
307 "Rotate the model x degrees about the x axis, then y degrees about the "
308 "y axis, and then z degrees about the z axis.",
309 &PfmTrans::dispatch_rotate_xyz, &_got_transform, &_transform);
312 (
"TA",
"angle,x,y,z", 49,
313 "Rotate the model angle degrees counterclockwise about the given "
315 &PfmTrans::dispatch_rotate_axis, &_got_transform, &_transform);
319 "Translate the model by the indicated amount.\n\n"
320 "All transformation options (-TS, -TR, -TA, -TT) are cumulative and are "
321 "applied in the order they are encountered on the command line.",
322 &PfmTrans::dispatch_translate, &_got_transform, &_transform);
336 nout <<
"You must specify the pfm file(s) to read on the command line.\n";
340 if (_got_output_filename && args.size() == 1) {
341 if (_got_output_dirname) {
342 nout <<
"Cannot specify both -o and -d.\n";
347 if (_got_output_filename) {
348 nout <<
"Cannot use -o when multiple pfm files are specified.\n";
353 Args::const_iterator ai;
354 for (ai = args.begin(); ai != args.end(); ++ai) {
368 dispatch_scale(
const string &opt,
const string &arg,
void *var) {
372 tokenize(arg, words,
",");
374 PN_stdfloat sx, sy, sz;
377 if (words.size() == 3) {
379 string_to_stdfloat(words[0], sx) &&
380 string_to_stdfloat(words[1], sy) &&
381 string_to_stdfloat(words[2], sz);
383 }
else if (words.size() == 1) {
385 string_to_stdfloat(words[0], sx);
391 <<
" requires one or three numbers separated by commas.\n";
407 dispatch_rotate_xyz(
ProgramBase *
self,
const string &opt,
const string &arg,
void *var) {
409 return base->ns_dispatch_rotate_xyz(opt, arg, var);
419 ns_dispatch_rotate_xyz(
const string &opt,
const string &arg,
void *var) {
423 tokenize(arg, words,
",");
428 if (words.size() == 3) {
430 string_to_stdfloat(words[0], xyz[0]) &&
431 string_to_stdfloat(words[1], xyz[1]) &&
432 string_to_stdfloat(words[2], xyz[2]);
437 <<
" requires three numbers separated by commas.\n";
446 *transform = (*transform) * mat;
458 dispatch_rotate_axis(
ProgramBase *
self,
const string &opt,
const string &arg,
void *var) {
460 return base->ns_dispatch_rotate_axis(opt, arg, var);
470 ns_dispatch_rotate_axis(
const string &opt,
const string &arg,
void *var) {
474 tokenize(arg, words,
",");
480 if (words.size() == 4) {
482 string_to_stdfloat(words[0], angle) &&
483 string_to_stdfloat(words[1], axis[0]) &&
484 string_to_stdfloat(words[2], axis[1]) &&
485 string_to_stdfloat(words[3], axis[2]);
490 <<
" requires four numbers separated by commas.\n";
506 dispatch_translate(
const string &opt,
const string &arg,
void *var) {
510 tokenize(arg, words,
",");
515 if (words.size() == 3) {
517 string_to_stdfloat(words[0], trans[0]) &&
518 string_to_stdfloat(words[1], trans[1]) &&
519 string_to_stdfloat(words[2], trans[2]);
524 <<
" requires three numbers separated by commas.\n";
534 int main(
int argc,
char *argv[]) {
This is intended to be the base class for most general-purpose utility programs in the PANDATOOL tree...
static const LMatrix4f & ident_mat()
Returns an identity matrix.
This is the base class for all three-component vectors and points.
void set_vis_inverse(bool vis_inverse)
Sets the vis_inverse flag.
static LMatrix4f scale_mat(const LVecBase3f &scale)
Returns a matrix that applies the indicated scale in each of the three axes.
static LMatrix4f translate_mat(const LVecBase3f &trans)
Returns a matrix that applies the indicated translation.
virtual void parse_command_line(int argc, char **argv)
Dispatches on each of the options on the command line, and passes the remaining parameters to handle_...
static LMatrix4f rotate_mat(float angle, const LVecBase3f &axis, CoordinateSystem cs=CS_default)
Returns a matrix that rotates by the given angle in degrees counterclockwise about the indicated vect...
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
PN_float32 get_channel(int x, int y, int c) const
Returns the cth channel of the point value at the indicated point.
void set_text()
Indicates that the filename represents a text file.
bool write_bam_file(const Filename &filename) const
Writes the contents of this node and below out to a bam file with the indicated filename.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
void set_vis_2d(bool vis_2d)
Sets the vis_2d flag.
void set_texture(Texture *tex, int priority=0)
Adds the indicated texture to the list of textures that will be rendered on the default texture stage...
void resize(int new_x_size, int new_y_size)
Applies a simple filter to resample the pfm file in-place to the indicated size.
bool read(const Filename &fullpath)
Reads the PFM data from the indicated file, returning true on success, false on failure.
bool write(const Filename &fullpath)
Writes the PFM data to the indicated file, returning true on success, false on failure.
void reparent_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread())
Removes the referenced node of the NodePath from its current parent and attaches it to the referenced...
void apply_crop(int x_begin, int x_end, int y_begin, int y_end)
Reduces the PFM file to the cells in the rectangle bounded by (x_begin, x_end, y_begin, y_end), where the _end cells are not included.
The name of a file, such as a texture file or an Egg file.
Defines a pfm file, a 2-d table of floating-point numbers, either 3-component or 1-component, or with a special extension, 2- or 4-component.
This is a 4-by-4 transform matrix.
void set_name(const string &name)
Changes the name of the referenced node.
bool has_point(int x, int y) const
Returns true if there is a valid point at x, y.
static Texture * load_texture(const Filename &filename, int primary_file_num_channels=0, bool read_mipmaps=false, const LoaderOptions &options=LoaderOptions())
Loads the given filename up into a texture, if it has not already been loaded, and returns the new te...
void flip(bool flip_x, bool flip_y, bool transpose)
Reverses, transposes, and/or rotates the table in-place according to the specified parameters...
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
string get_basename() const
Returns the basename part of the filename.
void xform(const LMatrix4f &transform)
Applies the indicated transform matrix to all points in-place.
void set_zero_special(bool zero_special)
Sets the zero_special flag.
bool process_pfm(const Filename &input_filename, PfmFile &file)
Handles a single pfm file.
void set_transparency(TransparencyAttrib::Mode mode, int priority=0)
Specifically sets or disables transparent rendering mode on this particular node. ...
bool open_write(ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
void add_transform_options()
Adds -TS, -TT, etc.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
void set_no_data_nan(int num_channels)
Sets the no_data_nan flag.
bool calc_autocrop(int &x_begin, int &x_end, int &y_begin, int &y_end) const
Computes the minimum range of x and y across the PFM file that include all points.
NodePath generate_vis_mesh(MeshFace face=MF_front) const
Creates a triangle mesh with the points of the pfm as 3-d coordinates in space, and texture coordinat...
This class aids in the visualization and manipulation of PfmFile objects.
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).