Skip to content

Commit

Permalink
oiiotool --dumpdata:C=name (AcademySoftwareFoundation#3136)
Browse files Browse the repository at this point in the history
New ":C=name" modifier for --dumpdata will cause the dumped image data
to be formatted with the syntax of a C array, that can be dropped right
into source code.

    $ oiiotool --dumpdata:C=foo image.exr
    // image.exr       :  256 x  256, 4 channel, float openexr
    float foo[256][256][4] =
    {
      { /* (0, 0): */ { 0.517036676, 0.261921108, 0.017822538, 0.912108004 },
        /* (1, 0): */ { 0.653315008, 0.527794302, 0.359594107, 0.277836263 },
        ...
    };

Without this modifier, --dumpdata will keep the same formatting it
always had.

This works pretty well for ordinary boring flat, single subimage,
non-MIPmap images.  The option should probably not be used (or at
least is very unpolished) for multi-subimage, MIP-mapped, deep, or
other oddball cases (but you probably don't want to shove those into
a single C array anyway).
  • Loading branch information
lgritz committed Oct 22, 2021
1 parent d258477 commit 3fee6a7
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 15 deletions.
24 changes: 22 additions & 2 deletions src/doc/oiiotool.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1110,14 +1110,34 @@ These are all non-positional flags that affect how all images are read in the

.. option:: --dumpdata

Print the numerical values of every pixel, for each input image as it is
read.
Print to the console the numerical values of every pixel, for each input
image as it is read.

Optional appended modifiers include:

- `C=` *name* : If present, will cause the output of the data to be
in the correct syntax of declaring a C array with the given name.
(This was added in OpenImageIO v2.3.9.)

- `empty=` *verbose* : If 0, will cause deep images to skip printing of
information about pixels with no samples.

Examples::

$ oiiotool --dumpdata image.exr
image.exr : 256 x 256, 4 channel, float openexr
Pixel (0, 0): 0.517036676 0.261921108 0.017822538 0.912108004
Pixel (1, 0): 0.653315008 0.527794302 0.359594107 0.277836263
...

$ oiiotool --dumpdata:C=foo image.exr
// image.exr : 256 x 256, 4 channel, float openexr
float foo[256][256][4] =
{
/* (0, 0): */ { 0.517036676, 0.261921108, 0.017822538, 0.912108004 },
/* (1, 0): */ { 0.653315008, 0.527794302, 0.359594107, 0.277836263 },
...
};

.. _sec-oiiotool-o:

Expand Down
5 changes: 4 additions & 1 deletion src/oiiotool/oiiotool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Oiiotool::clear_options()
printstats = false;
dumpdata = false;
dumpdata_showempty = true;
dumpdata_C = false;
hash = false;
updatemode = false;
autoorient = false;
Expand Down Expand Up @@ -517,6 +518,8 @@ set_dumpdata(cspan<const char*> argv)
auto options = ot.extract_options(command);
ot.dumpdata = true;
ot.dumpdata_showempty = options.get_int("empty", 1);
ot.dumpdata_C_name = options.get_string("C");
ot.dumpdata_C = ot.dumpdata_C_name.size();
}


Expand Down Expand Up @@ -5510,7 +5513,7 @@ getargs(int argc, char* argv[])
ap.arg("--stats", &ot.printstats)
.help("Print pixel statistics of all inputs files");
ap.arg("--dumpdata")
.help("Print all pixel data values of input files (options: empty=0)")
.help("Print all pixel data values of input files (options: empty=1, C=arrayname)")
.action(set_dumpdata);
ap.arg("--hash", &ot.hash)
.help("Print SHA-1 hash of each input image");
Expand Down
6 changes: 6 additions & 0 deletions src/oiiotool/oiiotool.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct print_info_options {
bool compute_stats = false;
bool dumpdata = false;
bool dumpdata_showempty = true;
bool dumpdata_C = false;
std::string dumpdata_C_name;
std::string metamatch;
std::string nometamatch;
std::string infoformat;
Expand All @@ -76,6 +78,7 @@ class Oiiotool {
bool printstats;
bool dumpdata;
bool dumpdata_showempty;
bool dumpdata_C;
bool hash;
bool updatemode;
bool autoorient;
Expand All @@ -91,6 +94,7 @@ class Oiiotool {
bool eval_enable; // Enable evaluation of expressions
bool skip_bad_frames = false; // Just skip a bad frame, don't exit
bool nostderr = false; // If true, use stdout for errors
std::string dumpdata_C_name;
std::string full_command_line;
std::string printinfo_metamatch;
std::string printinfo_nometamatch;
Expand Down Expand Up @@ -583,6 +587,8 @@ inline print_info_options::print_info_options(const Oiiotool& ot)
, compute_stats(ot.printstats)
, dumpdata(ot.dumpdata)
, dumpdata_showempty(ot.dumpdata_showempty)
, dumpdata_C(ot.dumpdata_C)
, dumpdata_C_name(ot.dumpdata_C_name)
, metamatch(ot.printinfo_metamatch)
, nometamatch(ot.printinfo_nometamatch)
{
Expand Down
58 changes: 46 additions & 12 deletions src/oiiotool/printinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ compute_sha1(Oiiotool& ot, ImageInput* input, int subimage)

template<typename T>
static void
print_nums(std::ostream& out, int n, const T* val, string_view sep = " ")
print_nums(std::ostream& out, int n, const T* val, string_view sep = " ",
bool C_formatting = false)
{
if (std::is_floating_point<T>::value || std::is_same<T, half>::value) {
// Ensure uniform printing of NaN and Inf on all platforms
Expand All @@ -95,11 +96,11 @@ print_nums(std::ostream& out, int n, const T* val, string_view sep = " ")
// not floating point -- print the int values, then float equivalents
for (int i = 0; i < n; ++i)
Strutil::print(out, "{}{}", i ? sep : "", val[i]);
Strutil::print(out, " (");
Strutil::print(out, " {}(", C_formatting ? "/* " : "");
for (int i = 0; i < n; ++i)
Strutil::print(out, "{}{}", i ? sep : "",
convert_type<T, float>(val[i]));
Strutil::print(out, ")");
Strutil::print(out, "){}", C_formatting ? " */" : "");
}
}

Expand All @@ -117,8 +118,22 @@ dump_flat_data(std::ostream& out, ImageInput* input,
input->geterror());
return false;
}
if (opt.dumpdata_C) {
if (spec.depth == 1 && spec.z == 0)
Strutil::print(out, "{}{} {}[{}][{}][{}] =\n{{\n", spec.format,
spec.format.is_floating_point() ? "" : "_t",
opt.dumpdata_C_name, spec.height, spec.width,
spec.nchannels);
else
Strutil::print(out, "{}{} {}[{}][{}][{}][{}] =\n{{\n", spec.format,
spec.format.is_floating_point() ? "" : "_t",
opt.dumpdata_C_name, spec.depth, spec.height,
spec.width, spec.nchannels);
}
const T* ptr = &buf[0];
for (int z = 0; z < spec.depth; ++z) {
if (opt.dumpdata_C && (spec.depth > 1 || spec.z != 0) && z == 0)
Strutil::print(out, " }} /* slice {} */\n", z);
for (int y = 0; y < spec.height; ++y) {
for (int x = 0; x < spec.width; ++x, ptr += spec.nchannels) {
if (!opt.dumpdata_showempty) {
Expand All @@ -129,15 +144,30 @@ dump_flat_data(std::ostream& out, ImageInput* input,
continue;
}
if (spec.depth > 1 || spec.z != 0)
Strutil::print(out, " Pixel ({}, {}, {}): ", x + spec.x,
y + spec.y, z + spec.z);
Strutil::print(out, " {}{} ({}, {}, {}): {}",
opt.dumpdata_C && x == 0 ? "{ " : " ",
opt.dumpdata_C ? "/*" : "Pixel", x + spec.x,
y + spec.y, z + spec.z,
opt.dumpdata_C ? "*/ " : "");
else
Strutil::print(out, " Pixel ({}, {}): ", x + spec.x,
y + spec.y);
print_nums(out, spec.nchannels, ptr);
Strutil::print(out, "\n");
Strutil::print(out, " {}{} ({}, {}): {}",
opt.dumpdata_C && x == 0 ? "{ " : " ",
opt.dumpdata_C ? "/*" : "Pixel", x + spec.x,
y + spec.y, opt.dumpdata_C ? "*/ { " : "");
print_nums(out, spec.nchannels, ptr,
opt.dumpdata_C ? ", " : " ", opt.dumpdata_C);
Strutil::print(out, "{}{}\n",
opt.dumpdata_C && x == (spec.width - 1) ? " }"
: "",
opt.dumpdata_C ? " }," : "");
}
}
if (opt.dumpdata_C && (spec.depth > 1 || spec.z != 0)
&& z == spec.depth - 1)
Strutil::print(out, " }}{}\n", z < spec.depth - 1 ? "," : "");
}
if (opt.dumpdata_C) {
Strutil::print(out, "}};\n");
}
return true;
}
Expand Down Expand Up @@ -608,7 +638,9 @@ print_info_subimage(std::ostream& out, Oiiotool& ot, int current_subimage,
std::string orig_line0 = lines[0];
if (current_subimage == 0) {
if (filename.size())
lines[0] = format("{}{} : {}", filename, padding, lines[0]);
lines[0] = format("{}{}{} : {}",
opt.dumpdata_C ? "// " : "", filename,
padding, lines[0]);
} else
lines[0] = format(" subimage {:2}: {}", current_subimage,
lines[0]);
Expand Down Expand Up @@ -719,9 +751,11 @@ print_info_subimage(std::ostream& out, Oiiotool& ot, int current_subimage,
else if (img)
mipspec = *img->spec(current_subimage, m);
if (opt.filenameprefix)
Strutil::print(out, "{} : ", filename);
Strutil::print(out, "{}{} : ", opt.dumpdata_C ? "// " : "",
filename);
if (nmip > 1 && opt.subimages) {
Strutil::print(out, " MIP {} of {} ({} x {}):\n", m, nmip,
Strutil::print(out, "{} MIP {} of {} ({} x {}):\n",
opt.dumpdata_C ? "// " : "", m, nmip,
mipspec.width, mipspec.height);
}
if (input)
Expand Down
15 changes: 15 additions & 0 deletions testsuite/oiiotool/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,21 @@ add_rgb_rgba.exr : 64 x 64, 4 channel, float openexr
screenWindowWidth: 1
oiio:ColorSpace: "Linear"
oiio:subimages: 1
dumpdata:
dump.exr : 2 x 2, 3 channel, half openexr
Pixel (0, 0): 0.000000000 0.000000000 0.000000000
Pixel (1, 0): 1.000000000 1.000000000 0.000000000
Pixel (0, 1): 0.000000000 0.000000000 0.000000000
Pixel (1, 1): 1.000000000 1.000000000 0.000000000
dumpdata:C
// dump.exr : 2 x 2, 3 channel, half openexr
half data[2][2][3] =
{
{ /* (0, 0): */ { 0.000000000, 0.000000000, 0.000000000 },
/* (1, 0): */ { 1.000000000, 1.000000000, 0.000000000 } },
{ /* (0, 1): */ { 0.000000000, 0.000000000, 0.000000000 },
/* (1, 1): */ { 1.000000000, 1.000000000, 0.000000000 } },
};
Comparing "filled.tif" and "ref/filled.tif"
PASS
Comparing "autotrim.tif" and "ref/autotrim.tif"
Expand Down
4 changes: 4 additions & 0 deletions testsuite/oiiotool/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@
# Test again using --missingfile checker
command += oiiotool ("--missingfile checker box.tif missing.tif --over -o box_over_missing3.tif || true")

# Test --dumpdata
command += oiiotool ("--pattern fill:left=0,0,0:right=1,1,0 2x2 3 -d half -o dump.exr")
command += oiiotool ("-echo dumpdata: --dumpdata dump.exr")
command += oiiotool ("-echo dumpdata:C --dumpdata:C=data dump.exr")

# To add more tests, just append more lines like the above and also add
# the new 'feature.tif' (or whatever you call it) to the outputs list,
Expand Down

0 comments on commit 3fee6a7

Please sign in to comment.