I had some free time this evening so I coded up the following quick patch
(on our OIIO 1.5). It needs some massage to put it in the OIIO coding
format (indentation is off, etc...) and I duplicated some functions which I
bet with some refactoring could be much improved. It also doesn't handle
checking for user-specified attributes (I have no idea what those are).
For my purposes, this is good enough, but I suspect you'll want to clean it
up if you end up committing it into OIIO.
In argparse.cpp, there is a memory leak if a user called parse(string), and
then parse(xargc, xargv). I don't know what your rules are on c++11 for
OIIO 1.5, but this code would be way simpler if you could use
std::unique_ptr. If you can use an alternative such as from boost, that
would work too.
Here's how it looks in action:
8:13% maketx ~/Desktop/IMG_1067.JPG --checknan --tile 32 128 -o "out of\
file.tx" -u
maketx: no update required for "out of\ file.tx"
8:13% maketx ~/Desktop/IMG_1067.JPG --checknan --tile 32 32 -o "out of\
file.tx" -u
8:13% maketx ~/Desktop/IMG_1067.JPG --checknan -o "out of\ file.tx" -u
8:13% maketx ~/Desktop/IMG_1067.JPG --checknan -o "out file.tx" -u
8:13% maketx ~/Desktop/IMG_1067.JPG --checknan -o "out file.tx" -u
maketx: no update required for "out file.tx"
8:14% maketx ~/Desktop/IMG_1067.JPG -o "out file.tx" -u
8:14% maketx ~/Desktop/IMG_1067.JPG -o "out file.tx" -u
maketx: no update required for "out file.tx"
8:14% maketx ~/Desktop/IMG_1067.JPG -u
8:14% maketx ~/Desktop/IMG_1067.JPG -u
maketx: no update required for "/Users/thiago/Desktop/IMG_1067.tx"
8:14% maketx -u ~/Desktop/IMG_1067.JPG
maketx: no update required for "/Users/thiago/Desktop/IMG_1067.tx"
8:14% maketx -u ~/Desktop/IMG_1067.JPG -v
maketx: no update required for "/Users/thiago/Desktop/IMG_1067.tx"
Thiago
On Tue, Dec 1, 2015 at 9:09 PM, Thiago Ize <[email protected]> wrote:
> deal :)
>
> On Tue, Dec 1, 2015 at 6:06 PM, Larry Gritz <[email protected]> wrote:
>
>> I'm busy but it also sounds pretty simple. Mainly I didn't want us both
>> to do it.
>>
>> How about this: whichever one of us gets around to starting it first,
>> send the other an email so they know not to redundantly do it.
>>
>>
>>
>> On Dec 1, 2015, at 4:28 PM, Thiago Ize <[email protected]> wrote:
>>
>> I haven't gotten around yet to fixing this. Of course I won't complain
>> if you (or someone else) wants to tackle this. If you're busy, just let me
>> know and I'll give it a shot.
>>
>> On Tue, Dec 1, 2015 at 5:17 PM, Larry Gritz <[email protected]> wrote:
>>
>>> I think this totally makes sense. The dumb -u behavior is probably just
>>> an artifact of having predated our current use of the metadata and the
>>> growing richness of command-line options.
>>>
>>> So are you proposing to do it, or are you requesting that I do it?
>>>
>>>
>>>
>>> On Dec 1, 2015, at 4:11 PM, Thiago Ize <[email protected]> wrote:
>>>
>>> That's exactly the solution I was imagining.
>>>
>>> I think it's less surprising to rebuild the .tx file if the arguments
>>> are different. Right now users might be confused why their changes aren't
>>> taking effect. After this, if users are trying to create the same file it
>>> will likely early exit and if they are trying something new, it will
>>> rebuild. The wrong case (what surprises users) shifts from the image
>>> incorrectly still being outdated to the correct image being used through
>>> extra redundant work. So trade incorrect image for correct but slower
>>> images.
>>>
>>> On Tue, Dec 1, 2015 at 5:01 PM, Larry Gritz <[email protected]> wrote:
>>>
>>>> The original meaning of -u is "skip the work if the source image is
>>>> older than the existing texture output." Dumb and simple! Also, easy to
>>>> understand and not prone to people wondering why it did or didn't succeed.
>>>> But yes, I totally see your point.
>>>>
>>>> You are proposing to try to make it much smarter: "skip the work if you
>>>> are reasonably certain that you'll get the same image as last time."
>>>>
>>>> I think this should be possible. The command line arguments are stored
>>>> in the metadata of the texture file! So I suppose it could parse that and
>>>> compare to the present command line arguments.
>>>>
>>>> The question is, will this produce a more subtle behavior that
>>>> inadvertently causes people to be frequently surprised or not understand
>>>> what it's doing?
>>>>
>>>>
>>>> On Dec 1, 2015, at 3:07 PM, Thiago Ize <[email protected]> wrote:
>>>>
>>>> I think my question is best explained through an example:
>>>>
>>>> $ maketx --colorconvert linear sRGB foo.png -o foo.tx
>>>> ... creates a foo.tx
>>>> $ maketx -colorconvert linear linear foo.png -o foo.tx -u
>>>> ... does nothing since timestamps are the same
>>>> $ maketx -colorconvert linear linear foo.png -o foo.tx -u
>>>> ... does nothing since timestamps are the same
>>>> $ maketx foo.png -o foo.tx -u
>>>> ... does nothing since timestamps are the same
>>>>
>>>> Wouldn't it be better if instead of just checking timestamps, it also
>>>> checked if the arguments used to create the .tx file are different? Then
>>>> you'd get something like:
>>>>
>>>> $ maketx --colorconvert linear sRGB foo.png -o foo.tx
>>>> ... creates a foo.tx
>>>> $ maketx -colorconvert linear linear foo.png -o foo.tx -u
>>>> ... updates foo.tx
>>>> $ maketx -colorconvert linear linear foo.png -o foo.tx -u
>>>> ... does nothing since the resulting file would be the same
>>>> $ maketx foo.png -o foo.tx -u
>>>> ... updates file since arguments are different (let's not try to think
>>>> too hard about whether linear to linear would have done the same thing or
>>>> not).
>>>> $ maketx foo.png -o foo.tx -u
>>>> ... does nothing since the resulting file would be the same
>>>> $ maketx foo.png -u
>>>> ... ideally would do nothing, but I wouldn't be too upset if it updated.
>>>> $ maketx -u foo.png
>>>> ... do nothing. We should ignore ordering differences when applicable
>>>>
>>>> I can imagine trying to handle all cases is rather complicated (such as
>>>> different arguments that produce the same image), but if we can at least
>>>> get the easy cases, and if in doubt, always do an update, I imagine that
>>>> would handle 99% of the use cases and would only have the drawback that
>>>> very rarely maketx would end up doing redundant work, which is annoying but
>>>> at least results in a correct file.
>>>>
>>>> Thiago
>>>> _______________________________________________
>>>> Oiio-dev mailing list
>>>> [email protected]
>>>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>>>
>>>>
>>>> --
>>>> Larry Gritz
>>>> [email protected]
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> Oiio-dev mailing list
>>>> [email protected]
>>>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>>>
>>>>
>>> _______________________________________________
>>> Oiio-dev mailing list
>>> [email protected]
>>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>>
>>>
>>> --
>>> Larry Gritz
>>> [email protected]
>>>
>>>
>>>
>>> _______________________________________________
>>> Oiio-dev mailing list
>>> [email protected]
>>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>>
>>>
>> _______________________________________________
>> Oiio-dev mailing list
>> [email protected]
>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>
>>
>> --
>> Larry Gritz
>> [email protected]
>>
>>
>>
>> _______________________________________________
>> Oiio-dev mailing list
>> [email protected]
>> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
>>
>>
>
diff --git a/src/include/OpenImageIO/argparse.h
b/src/include/OpenImageIO/argparse.h
index 3bfc1dd..03230f8 100644
--- a/src/include/OpenImageIO/argparse.h
+++ b/src/include/OpenImageIO/argparse.h
@@ -160,6 +160,7 @@ public:
/// With the options already set up, parse the command line.
/// Return 0 if ok, -1 if it's a malformed command line.
int parse (int argc, const char **argv);
+ int parse (std::string command_line);
/// Return any error messages generated during the course of parse()
/// (and clear any error flags). If no error has occurred since the
@@ -174,6 +175,7 @@ public:
/// Return the entire command-line as one string.
///
std::string command_line () const;
+ const char** command_line (const std::string& s, int& argc) const;
private:
int m_argc; // a copy of the command line argc
@@ -182,6 +184,7 @@ private:
ArgOption *m_global; // option for extra cmd line
arguments
std::string m_intro;
std::vector<ArgOption *> m_option;
+ bool need_to_delete;
ArgOption *find_option(const char *name);
// void error (const char *format, ...)
diff --git a/src/libOpenImageIO/maketexture.cpp
b/src/libOpenImageIO/maketexture.cpp
index d36fe3e..6003b5d 100644
--- a/src/libOpenImageIO/maketexture.cpp
+++ b/src/libOpenImageIO/maketexture.cpp
@@ -788,9 +788,327 @@ write_mipmap (ImageBufAlgo::MakeTextureMode mode,
return true;
}
+static std::vector<std::string> filenames;
+static int
+parse_files (int argc, const char *argv[])
+{
+ for (int i = 0; i < argc; i++)
+ filenames.push_back (argv[i]);
+ return 0;
+}
static bool
+getmaketxargs (const std::string &commandline, ImageSpec &configspec)
+{
+ bool help = false;
+ // Basic runtime options
+ std::string dataformatname = "";
+ std::string fileformatname = "";
+ std::vector<std::string> mipimages;
+ int tile[3] = { 64, 64, 1 }; // FIXME if we ever support volume MIPmaps
+ std::string compression = "zip";
+ bool updatemode = false;
+ bool checknan = false;
+ std::string fixnan; // none, black, box3
+ bool set_full_to_pixels = false;
+ bool do_highlight_compensation = false;
+ std::string filtername;
+ // Options controlling file metadata or mipmap creation
+ float fovcot = 0.0f;
+ std::string wrap = "black";
+ std::string swrap;
+ std::string twrap;
+ bool doresize = false;
+ Imath::M44f Mcam(0.0f), Mscr(0.0f); // Initialize to 0
+ bool separate = false;
+ bool nomipmap = false;
+ bool prman_metadata = false;
+ bool constant_color_detect = false;
+ bool monochrome_detect = false;
+ bool opaque_detect = false;
+ bool compute_average = true;
+ int nchannels = -1;
+ bool prman = false;
+ bool oiio = false;
+ bool ignore_unassoc = false; // ignore unassociated alpha tags
+ bool unpremult = false;
+ bool sansattrib = false;
+ float sharpen = 0.0f;
+ std::string incolorspace;
+ std::string outcolorspace;
+ std::string channelnames;
+ std::vector<std::string> string_attrib_names, string_attrib_values;
+ std::vector<std::string> any_attrib_names, any_attrib_values;
+ filenames.clear();
+
+ bool verbose;
+ std::string outputfilename;
+ bool stats = false;
+ int nthreads = 0; // default: use #cores threads if available
+ bool mipmapmode = false;
+ bool shadowmode = false;
+ bool envlatlmode = false;
+ bool envcubemode = false;
+ bool lightprobemode = false;
+
+
+ ArgParse ap;
+ ap.options ("maketx -- convert images to tiled, MIP-mapped textures\n"
+ OIIO_INTRO_STRING "\n"
+ "Usage: maketx [options] file...",
+ "%*", parse_files, "",
+ "--help", &help, "Print help message",
+ "-v", &verbose, "Verbose status messages",
+ "-o %s", &outputfilename, "Output filename",
+ "--new", NULL, "",
+ "--old", NULL, "Old mode",
+ "--threads %d", &nthreads, "Number of threads (default:
#cores)",
+ "-u", &updatemode, "Update mode",
+ "--format %s", &fileformatname, "Specify output file format
(default: guess from extension)",
+ "--nchannels %d", &nchannels, "Specify the number of output
image channels.",
+ "--chnames %s", &channelnames, "Rename channels
(comma-separated)",
+ "-d %s", &dataformatname, "Set the output data format to one
of: "
+ "uint8, sint8, uint16, sint16, half, float",
+ "--tile %d %d", &tile[0], &tile[1], "Specify tile size",
+ "--separate", &separate, "Use planarconfig separate
(default: contiguous)",
+ "--compression %s", &compression, "Set the compression
method (default = zip, if possible)",
+ "--fovcot %f", &fovcot, "Override the frame aspect ratio.
Default is width/height.",
+ "--wrap %s", &wrap, "Specify wrap mode (black, clamp,
periodic, mirror)",
+ "--swrap %s", &swrap, "Specific s wrap mode separately",
+ "--twrap %s", &twrap, "Specific t wrap mode separately",
+ "--resize", &doresize, "Resize textures to power of 2
(default: no)",
+ "--noresize %!", &doresize, "Do not resize textures to power
of 2 (deprecated)",
+ "--filter %s", &filtername, "",
+ "--hicomp", &do_highlight_compensation,
+ "Compress HDR range before resize, expand after.",
+ "--sharpen %f", &sharpen, "Sharpen MIP levels (default = 0.0
= no)",
+ "--nomipmap", &nomipmap, "Do not make multiple MIP-map
levels",
+ "--checknan", &checknan, "Check for NaN/Inf values (abort if
found)",
+ "--fixnan %s", &fixnan, "Attempt to fix NaN/Inf values in
the image (options: none, black, box3)",
+ "--fullpixels", &set_full_to_pixels, "Set the 'full' image
range to be the pixel data window",
+ "--Mcamera %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
+ &Mcam[0][0], &Mcam[0][1], &Mcam[0][2], &Mcam[0][3],
+ &Mcam[1][0], &Mcam[1][1], &Mcam[1][2], &Mcam[1][3],
+ &Mcam[2][0], &Mcam[2][1], &Mcam[2][2], &Mcam[2][3],
+ &Mcam[3][0], &Mcam[3][1], &Mcam[3][2], &Mcam[3][3],
+ "Set the camera matrix",
+ "--Mscreen %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
+ &Mscr[0][0], &Mscr[0][1], &Mscr[0][2], &Mscr[0][3],
+ &Mscr[1][0], &Mscr[1][1], &Mscr[1][2], &Mscr[1][3],
+ &Mscr[2][0], &Mscr[2][1], &Mscr[2][2], &Mscr[2][3],
+ &Mscr[3][0], &Mscr[3][1], &Mscr[3][2], &Mscr[3][3],
+ "Set the screen matrix",
+ "--hash", NULL, "",
+ "--prman-metadata", &prman_metadata, "Add prman specific
metadata",
+ "--attrib %L %L", &any_attrib_names, &any_attrib_values,
"Sets metadata attribute (name, value)",
+ "--sattrib %L %L", &string_attrib_names,
&string_attrib_values, "Sets string metadata attribute (name, value)",
+ "--sansattrib", &sansattrib, "Write command line into
Software & ImageHistory but remove --sattrib and --attrib options",
+ "--constant-color-detect", &constant_color_detect, "Create
1-tile textures from constant color inputs",
+ "--monochrome-detect", &monochrome_detect, "Create 1-channel
textures from monochrome inputs",
+ "--opaque-detect", &opaque_detect, "Drop alpha channel that
is always 1.0",
+ "--no-compute-average %!", &compute_average, "Don't compute
and store average color",
+ "--ignore-unassoc", &ignore_unassoc, "Ignore unassociated
alpha tags in input (don't autoconvert)",
+ "--stats", &stats, "Print runtime statistics",
+ "--mipimage %L", &mipimages, "Specify an individual MIP
level",
+ "<SEPARATOR>", "Basic modes (default is plain texture):",
+ "--shadow", &shadowmode, "Create shadow map",
+ "--envlatl", &envlatlmode, "Create lat/long environment map",
+ "--lightprobe", &lightprobemode, "Create lat/long
environment map from a light probe",
+// "--envcube", &envcubemode, "Create cubic env map (file
order: px, nx, py, ny, pz, nz) (UNIMP)",
+ "<SEPARATOR>", "",
+ "--colorconvert %s %s", &incolorspace, &outcolorspace,
+ "",
+ "--unpremult", &unpremult, "Unpremultiply before color
conversion, then premultiply "
+ "after the color conversion. You'll probably want
to use this flag "
+ "if your image contains an alpha channel.",
+ "<SEPARATOR>", "Configuration Presets",
+ "--prman", &prman, "Use PRMan-safe settings for tile size,
planarconfig, and metadata.",
+ "--oiio", &oiio, "Use OIIO-optimized settings for tile size,
planarconfig, metadata.",
+ NULL);
+ if (ap.parse (commandline) < 0) {
+ std::cerr << ap.geterror() << std::endl;
+ ap.usage ();
+ return false;
+ }
+
+ int optionsum = ((int)shadowmode + (int)envlatlmode + (int)envcubemode +
+ (int)lightprobemode);
+ if (optionsum > 1) {
+ std::cerr << "maketx ERROR: At most one of the following options may
be set:\n"
+ << "\t--shadow --envlatl --envcube --lightprobe\n";
+ ap.usage ();
+ return false;
+ }
+ if (optionsum == 0)
+ mipmapmode = true;
+
+ if (prman && oiio) {
+ std::cerr << "maketx ERROR: '--prman' compatibility, and '--oiio'
optimizations are mutually exclusive.\n";
+ std::cerr << "\tIf you'd like both prman and oiio compatibility, you
should choose --prman\n";
+ std::cerr << "\t(at the expense of oiio-specific optimizations)\n";
+ ap.usage ();
+ return false;
+ }
+
+ // Figure out which data format we want for output
+ if (! dataformatname.empty()) {
+ if (dataformatname == "uint8")
+ configspec.format = TypeDesc::UINT8;
+ else if (dataformatname == "int8" || dataformatname == "sint8")
+ configspec.format = TypeDesc::INT8;
+ else if (dataformatname == "uint16")
+ configspec.format = TypeDesc::UINT16;
+ else if (dataformatname == "int16" || dataformatname == "sint16")
+ configspec.format = TypeDesc::INT16;
+ else if (dataformatname == "half")
+ configspec.format = TypeDesc::HALF;
+ else if (dataformatname == "float")
+ configspec.format = TypeDesc::FLOAT;
+ else if (dataformatname == "double")
+ configspec.format = TypeDesc::DOUBLE;
+ else {
+ std::cerr << "maketx ERROR: unknown data format \"" <<
dataformatname << "\"\n";
+ return false;
+ }
+ }
+
+ configspec.tile_width = tile[0];
+ configspec.tile_height = tile[1];
+ configspec.tile_depth = tile[2];
+ configspec.attribute ("compression", compression);
+ if (fovcot != 0.0f)
+ configspec.attribute ("fovcot", fovcot);
+ configspec.attribute ("planarconfig", separate ? "separate" : "contig");
+ if (Mcam != Imath::M44f(0.0f))
+ configspec.attribute ("worldtocamera", TypeDesc::TypeMatrix, &Mcam);
+ if (Mscr != Imath::M44f(0.0f))
+ configspec.attribute ("worldtoscreen", TypeDesc::TypeMatrix, &Mscr);
+ std::string wrapmodes = (swrap.size() ? swrap : wrap) + ',' +
+ (twrap.size() ? twrap : wrap);
+ configspec.attribute ("wrapmodes", wrapmodes);
+
+ configspec.attribute ("maketx:verbose", verbose);
+ configspec.attribute ("maketx:stats", stats);
+ configspec.attribute ("maketx:resize", doresize);
+ configspec.attribute ("maketx:nomipmap", nomipmap);
+ configspec.attribute ("maketx:updatemode", updatemode);
+ configspec.attribute ("maketx:constant_color_detect",
constant_color_detect);
+ configspec.attribute ("maketx:monochrome_detect", monochrome_detect);
+ configspec.attribute ("maketx:opaque_detect", opaque_detect);
+ configspec.attribute ("maketx:compute_average", compute_average);
+ configspec.attribute ("maketx:unpremult", unpremult);
+ configspec.attribute ("maketx:incolorspace", incolorspace);
+ configspec.attribute ("maketx:outcolorspace", outcolorspace);
+ configspec.attribute ("maketx:checknan", checknan);
+ configspec.attribute ("maketx:fixnan", fixnan);
+ configspec.attribute ("maketx:set_full_to_pixels", set_full_to_pixels);
+ configspec.attribute ("maketx:highlightcomp",
(int)do_highlight_compensation);
+ configspec.attribute ("maketx:sharpen", sharpen);
+ if (filtername.size())
+ configspec.attribute ("maketx:filtername", filtername);
+ configspec.attribute ("maketx:nchannels", nchannels);
+ configspec.attribute ("maketx:channelnames", channelnames);
+ if (fileformatname.size())
+ configspec.attribute ("maketx:fileformatname", fileformatname);
+ configspec.attribute ("maketx:prman_metadata", prman_metadata);
+ configspec.attribute ("maketx:oiio_options", oiio);
+ configspec.attribute ("maketx:prman_options", prman);
+ if (mipimages.size())
+ configspec.attribute ("maketx:mipimages",
Strutil::join(mipimages,";"));
+
+ // Add user-specified string attributes
+ for (size_t i = 0; i < string_attrib_names.size(); ++i) {
+ configspec.attribute (string_attrib_names[i], string_attrib_values[i]);
+ }
+
+ // Add user-specified "any" attributes -- try to deduce the type
+ for (size_t i = 0; i < any_attrib_names.size(); ++i) {
+ string_view s = any_attrib_values[i];
+ // Does it parse as an int (and nothing more?)
+ int ival;
+ if (Strutil::parse_int(s,ival)) {
+ Strutil::skip_whitespace(s);
+ if (! s.size()) {
+ configspec.attribute (any_attrib_names[i], ival);
+ continue;
+ }
+ }
+ s = any_attrib_values[i];
+ // Does it parse as a float (and nothing more?)
+ float fval;
+ if (Strutil::parse_float(s,fval)) {
+ Strutil::skip_whitespace(s);
+ if (! s.size()) {
+ configspec.attribute (any_attrib_names[i], fval);
+ continue;
+ }
+ }
+ // OK, treat it like a string
+ configspec.attribute (any_attrib_names[i], any_attrib_values[i]);
+ }
+
+ if (ignore_unassoc) {
+ configspec.attribute ("maketx:ignore_unassoc", (int)ignore_unassoc);
+ ImageCache *ic = ImageCache::create (); // get the shared one
+ ic->attribute ("unassociatedalpha", (int)ignore_unassoc);
+ }
+ return true;
+}
+
+static bool attrib_int_equal(const char* name, const ImageSpec& src, const
ImageSpec& dst)
+{
+ return src.get_int_attribute(name) == dst.get_int_attribute(name);
+}
+static bool attrib_flt_equal(const char* name, const ImageSpec& src, const
ImageSpec& dst)
+{
+ return src.get_float_attribute(name) == dst.get_float_attribute(name);
+}
+static bool attrib_str_equal(const char* name, const ImageSpec& src, const
ImageSpec& dst)
+{
+ return src.get_string_attribute(name) == dst.get_string_attribute(name);
+}
+static bool compare_maketx_flags(const ImageSpec& src, const ImageSpec& dst)
+{
+ return
+ src.tile_width == dst.tile_width &&
+ src.tile_height == dst.tile_height &&
+ src.tile_depth == dst.tile_depth &&
+ src.format == dst.format &&
+ attrib_str_equal("compression", src, dst) &&
+ attrib_int_equal("fovcot", src, dst) &&
+ attrib_str_equal("planarconfig", src, dst) &&
+ attrib_int_equal("worldtocamera", src, dst) &&
+ attrib_int_equal("worldtoscreen", src, dst) &&
+ attrib_str_equal("wrapmodes", src, dst) &&
+ attrib_int_equal("maketx:resize", src, dst) &&
+ attrib_int_equal("maketx:nomipmap", src, dst) &&
+ attrib_int_equal("maketx:constant_color_detect", src, dst) &&
+ attrib_int_equal("maketx:monochrome_detect", src, dst) &&
+ attrib_int_equal("maketx:opaque_detect", src, dst) &&
+ attrib_int_equal("maketx:compute_average", src, dst) &&
+ attrib_int_equal("maketx:unpremult", src, dst) &&
+ attrib_str_equal("maketx:incolorspace", src, dst) &&
+ attrib_str_equal("maketx:outcolorspace", src, dst) &&
+ attrib_int_equal("maketx:checknan", src, dst) &&
+ attrib_int_equal("maketx:fixnan", src, dst) &&
+ attrib_int_equal("maketx:set_full_to_pixels", src, dst) &&
+ attrib_int_equal("maketx:highlightcomp", src, dst) &&
+ attrib_flt_equal("maketx:sharpen", src, dst) &&
+ attrib_str_equal("maketx:filtername", src, dst) &&
+ attrib_int_equal("maketx:nchannels", src, dst) &&
+ attrib_str_equal("maketx:channelnames", src, dst) &&
+ attrib_str_equal("maketx:fileformatname", src, dst) &&
+ attrib_int_equal("maketx:prman_metadata", src, dst) &&
+ attrib_int_equal("maketx:oiio_options", src, dst) &&
+ attrib_int_equal("maketx:prman_options", src, dst) &&
+ attrib_str_equal("maketx:mipimages", src, dst) &&
+ attrib_int_equal("maketx:ignore_unassoc", src, dst);
+
+ // TODO: need to handle user-specified attributes
+}
+
+static bool
make_texture_impl (ImageBufAlgo::MakeTextureMode mode,
const ImageBuf *input,
std::string filename,
@@ -877,9 +1195,30 @@ make_texture_impl (ImageBufAlgo::MakeTextureMode mode,
in_time = Filesystem::last_write_time (src->name());
if (updatemode && Filesystem::exists (outputfilename) &&
(in_time == Filesystem::last_write_time (outputfilename))) {
- outstream << "maketx: no update required for \""
- << outputfilename << "\"\n";
- return true;
+
+ // We have same timestamps, but what if we want to make the texture
+ // with different settings from last time?
+ ImageSpec out_spec;
+ ImageInput *input = ImageInput::open(outputfilename);
+ std::string history = input->spec().get_string_attribute
("Software");
+ input->close();
+
+ size_t maketx_start = history.find("maketx ");
+ if (maketx_start != std::string::npos) {
+ history = history.substr(maketx_start);
+
+ ImageSpec out_configspec;
+ bool success = getmaketxargs(history, out_configspec);
+
+ if (success) {
+ success = compare_maketx_flags(configspec, out_configspec);
+ if (success) {
+ outstream << "maketx: no update required for \""
+ << outputfilename << "\"\n";
+ return true;
+ }
+ }
+ }
}
}
diff --git a/src/libutil/argparse.cpp b/src/libutil/argparse.cpp
index dcf35bc..a3c5d3b 100644
--- a/src/libutil/argparse.cpp
+++ b/src/libutil/argparse.cpp
@@ -320,7 +320,7 @@ ArgOption::add_argument (const char *argv)
ArgParse::ArgParse (int argc, const char **argv)
- : m_argc(argc), m_argv(argv), m_global(NULL)
+ : m_argc(argc), m_argv(argv), m_global(NULL), need_to_delete(false)
{
}
@@ -332,8 +332,27 @@ ArgParse::~ArgParse()
ArgOption *opt = m_option[i];
delete opt;
}
+ if (need_to_delete) {
+ for (int i=0; i < m_argc; ++i)
+ delete[] m_argv[i];
+ delete[] m_argv;
+ }
}
+int
+ArgParse::parse (std::string s)
+{
+ if (need_to_delete) {
+ for (int i=0; i < m_argc; ++i)
+ delete[] m_argv[i];
+ delete[] m_argv;
+ m_argc = 0;
+ m_argv = NULL;
+ }
+ need_to_delete = true;
+ m_argv = command_line(s, m_argc);
+ return parse(m_argc, m_argv);
+}
// Top level command line parsing function called after all options
@@ -555,7 +574,46 @@ ArgParse::command_line () const
return s;
}
-
+// The caller must delete the returned char**. Would be much better to instead
+// use std::unique_ptr
+const char** ArgParse::command_line (const std::string& s, int& argc) const
+{
+ // the command_line that returns a std::string will wrap all multiple word
+ // arguments in quotation marks, so we can assume that is all we need to
+ // handle here. We will also assume simple args, so no escaped quotation
+ // marks, tabs, or other weirdness.
+ std::vector<std::string> args;
+ std::string arg;
+ for (size_t i=0; i < s.size(); ++i) {
+ for (; s[i] == ' '; ++i); // consume spaces
+
+ // was the end all white space?
+ if (i >= s.size())
+ break;
+
+ size_t end;
+
+ if (s[i] == '\"') // quoted arg?
+ end = s.find_first_of('\"', i+1);
+ else
+ end = s.find_first_of(' ', i);
+
+ if (end == std::string::npos)
+ end = s.size();
+ arg = s.substr(i, end-i);
+ args.push_back(arg);
+ i = end;
+ }
+
+ argc = static_cast<int>(args.size());
+ char** argv = new char*[argc];
+ for (int i=0; i < argc; ++i)
+ {
+ argv[i] = new char[args[i].size()+1];
+ memcpy(argv[i], args[i].c_str(), args[i].size()+1);
+ }
+ return const_cast<const char**>(argv);
+}
}
OIIO_NAMESPACE_EXIT
_______________________________________________
Oiio-dev mailing list
[email protected]
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org