Skip to content

Commit caa665d

Browse files
authored
feat(oiiotool): --eraseattrib:fromfile=1 (#4763)
Extended eraseattrib to be able to read regex patterns from a file, one per line, with `--eraseattrib:fromfile=1 filename`. Erases all metadata attribute fields that match. Added a new test to `oiiotool-attribs` which has been verified painstakenly to be working! Also tried running the command directly from dist/bin and verified with `oiiotool --info -v`. More detail on the motivation: It's common in a studio to have tools insert all sorts of metadata into files as they're rendered, etc. But a lot of that are things that SHOULD NOT leave the facility -- like security issues from internal pathnames or network info, or secrets like plot details revealed by sequence or character names. So generally you want to scrub the metadata from the final images before they are shipped to the client or to marketing or whatever. oiiotool's --eraseattrib is handy for this, but it takes a single regex. But we were thinking that: - You may have several patterns to fully describe the metadata you want to be sure not to ship. This could be an unwieldy regex or a cluttered series of multiple --eraseattrib commands. - That list of patterns may change over time, and it would be error prone to have to change it in every script that calls oiiotool. - That list of patterns may need to be different per show. We thought a solution to facilitate this might be a version of --eraseattrib that takes a filename that contains a list of regexes, one per line of the text file. So that master list of things to scrub could be maintained in a central place and not need to update every oiiotool-calling script in order to update it. Furthermore, you could have the command say something like $ oiiotool ready_to_ship.exr --eraseattrib:fromfile=1 /blah/$SHOW/nometadata.txt -o clean.exr to make a single command that allows per-show customization. --------- Signed-off-by: Lydia Zheng <[email protected]>
1 parent c4f01e7 commit caa665d

File tree

6 files changed

+88
-8
lines changed

6 files changed

+88
-8
lines changed

src/doc/oiiotool.rst

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,13 @@ current top image.
20362036
Only included subimages will have the attribute changed. If subimages
20372037
are not set, only the first subimage will be changed, or all subimages
20382038
if the `-a` command line flag was used.
2039+
2040+
`:fromfile=` *int*
2041+
When set to 1, the next argument will be interpreted as
2042+
the name of a file containing a list of patterns to erase, for example:
2043+
`--eraseattrib:fromfile=1 patterns.txt`,
2044+
The patterns will be case insensitive and one pattern per line of the file.
2045+
Default value is 0 (False).
20392046

20402047
Examples::
20412048

@@ -2048,6 +2055,13 @@ current top image.
20482055
# Remove all metadata
20492056
oiiotool in.exr --eraseattrib:subimages=all ".*" -o no_metadata.exr
20502057

2058+
# Remove all attribute that match any regex in text file
2059+
oiiotool in.exr --eraseattrib:fromfile=1 no_gps_make.txt -o no_gps_make_metadata.exr
2060+
2061+
Example contents of file no_gps_make.txt:
2062+
Make
2063+
GPS:.*
2064+
20512065

20522066
.. option:: --orientation <orient>
20532067

@@ -4770,7 +4784,3 @@ General commands that also work for deep images
47704784
`NaN` or `Inf` values (hereafter referred to collectively as
47714785
"nonfinite") are repaired. The *strategy* may be either `black` or
47724786
`error`.
4773-
4774-
4775-
4776-

src/oiiotool/oiiotool.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,14 @@ set_oiio_attribute(Oiiotool& ot, cspan<const char*> argv)
14941494
OIIO::attribute(p.name(), p.type(), p.data());
14951495
}
14961496

1497+
static std::vector<std::string>
1498+
get_regex_list_from_file(string_view filename)
1499+
{
1500+
// helper function that takes a text file and return all regex attribname entries as a list
1501+
std::string contents;
1502+
Filesystem::read_text_file(filename, contents);
1503+
return Strutil::splits(contents, "\n");
1504+
}
14971505

14981506

14991507
// Special OiiotoolOp whose purpose is to set attributes on the top image.
@@ -1503,8 +1511,16 @@ class OpAttribSetter final : public OiiotoolOp {
15031511
: OiiotoolOp(ot, opname, argv, 1)
15041512
{
15051513
inplace(true); // This action operates in-place
1506-
attribname = args(1);
1507-
value = (nargs() > 2 ? args(2) : "");
1514+
auto options = ot.extract_options(opname);
1515+
bool fromfile = options.get_int("fromfile", 0);
1516+
if (!fromfile) {
1517+
attribname = args(1);
1518+
} else {
1519+
// handle erase attribute using regex text file case
1520+
regex_file = args(1);
1521+
attribname_list = get_regex_list_from_file(regex_file);
1522+
}
1523+
value = (nargs() > 2 ? args(2) : "");
15081524
}
15091525
bool setup() override
15101526
{
@@ -1516,7 +1532,15 @@ class OpAttribSetter final : public OiiotoolOp {
15161532
// Because this is an in-place operation, img[0] is the same as
15171533
// img[1].
15181534
if (value.empty()) {
1519-
img[0]->specmod().erase_attribute(attribname);
1535+
if (attribname_list.empty()) {
1536+
img[0]->specmod().erase_attribute(attribname);
1537+
} else {
1538+
for (string_view attr : attribname_list) {
1539+
//std::cout << "list element:" << attr << std::endl;
1540+
img[0]->specmod().erase_attribute(attr);
1541+
}
1542+
}
1543+
15201544
} else {
15211545
TypeDesc type(options()["type"].as_string());
15221546
set_attribute_helper(img[0]->specmod(), attribname, value, type);
@@ -1527,6 +1551,8 @@ class OpAttribSetter final : public OiiotoolOp {
15271551
private:
15281552
string_view attribname;
15291553
string_view value;
1554+
string_view regex_file;
1555+
std::vector<std::string> attribname_list;
15301556
};
15311557

15321558

@@ -6663,7 +6689,7 @@ Oiiotool::getargs(int argc, char* argv[])
66636689
.help("Sets string metadata attribute")
66646690
.OTACTION(action_sattrib);
66656691
ap.arg("--eraseattrib %s:REGEX")
6666-
.help("Erase attributes matching regex")
6692+
.help("Erase attributes matching regex (options: fromfile=1 filename-containing-patterns")
66676693
.OTACTION(erase_attribute);
66686694
ap.arg("--caption %s:TEXT")
66696695
.help("Sets caption (ImageDescription metadata)")

testsuite/oiiotool-attribs/ref/out-jpeg9d.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
Reading nomakegps.jpg
2+
nomakegps.jpg : 2048 x 1536, 3 channel, uint8 jpeg
3+
SHA-1: A74C7DF2B01825DCB6881407AE77C11DC56AB741
4+
channel list: R, G, B
5+
Model: "T-Mobile G1"
6+
Orientation: 1 (normal)
7+
ResolutionUnit: "none"
8+
XResolution: 72
9+
YResolution: 72
10+
Exif:ColorSpace: 1
11+
Exif:ExifVersion: "0230"
12+
Exif:FlashPixVersion: "0100"
13+
Exif:PixelXDimension: 2048
14+
Exif:PixelYDimension: 1536
15+
Exif:WhiteBalance: 0 (auto)
16+
Exif:YCbCrPositioning: 1
17+
jpeg:subsampling: "4:2:0"
18+
oiio:ColorSpace: "sRGB"
119
Reading nomake.jpg
220
nomake.jpg : 2048 x 1536, 3 channel, uint8 jpeg
321
SHA-1: A74C7DF2B01825DCB6881407AE77C11DC56AB741

testsuite/oiiotool-attribs/ref/out.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
Reading nomakegps.jpg
2+
nomakegps.jpg : 2048 x 1536, 3 channel, uint8 jpeg
3+
SHA-1: 2623446988E34395C6B0A4AA4FC75107C708BF18
4+
channel list: R, G, B
5+
Model: "T-Mobile G1"
6+
Orientation: 1 (normal)
7+
ResolutionUnit: "none"
8+
XResolution: 72
9+
YResolution: 72
10+
Exif:ColorSpace: 1
11+
Exif:ExifVersion: "0230"
12+
Exif:FlashPixVersion: "0100"
13+
Exif:PixelXDimension: 2048
14+
Exif:PixelYDimension: 1536
15+
Exif:WhiteBalance: 0 (auto)
16+
Exif:YCbCrPositioning: 1
17+
jpeg:subsampling: "4:2:0"
18+
oiio:ColorSpace: "sRGB"
119
Reading nomake.jpg
220
nomake.jpg : 2048 x 1536, 3 channel, uint8 jpeg
321
SHA-1: 2623446988E34395C6B0A4AA4FC75107C708BF18

testsuite/oiiotool-attribs/run.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
# Test oiiotool's ability to add and delete attributes
88

99

10+
# Test --eraseattrib:fromfile=1 to erase from a list of regex matching attributes
11+
12+
command += oiiotool (OIIO_TESTSUITE_IMAGEDIR+"/tahoe-gps.jpg --eraseattrib:fromfile=1 src/regex_list.txt -o nomakegps.jpg")
13+
command += info_command ("nomakegps.jpg", safematch=True)
14+
15+
1016
# Test --eraseattrib ability to erase one specific attribute
1117
# The result should not have "Make"
1218
command += oiiotool (OIIO_TESTSUITE_IMAGEDIR+"/tahoe-gps.jpg --eraseattrib Make -o nomake.jpg")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make
2+
GPS:.*

0 commit comments

Comments
 (0)