Skip to content

Commit 5c66cf8

Browse files
committed
feat(oiiotool): allow easy splitting of subimages by name (#4874)
Say you need to take a multi-part exr file and split it into separate files for each part. (Note: what OpenEXR calls "parts", OIIO calls "subimages.") You could do this oiiotool multipart.exr --sisplit -o:all=1 "part.%04d.exr" But this would name the parts part.0001.exr, part.0002.exr, etc. Maybe you would prefer to split them into files that contain the subimage name rather than just the inscrutible index number (which may also not be consistent across files)? You could try this dance to loop over the subimages and write each one with a name extracted from its metadata: oiiotool multipart.exr --for i {TOP.SUBIMAGES} --dup --subimage {i} -o "subimage_{TOP.'oiio:subimagename'}.exr That works, but that's a little awkward and hard to remember off the top of your head. Perhaps instead we would prefer a simpler version: oiiotool multipart.exr --sisplit -o:all=1 "part.{TOP.'oiio:subimagename'}.exr" This PR makes that last command work. It actually only required a small change, which is that the function that handles the `-o` command needs to defer the evaluation of the expression subsitution in the filename to occur separately for each subimage being output, rather than just once for the whole `-o:all=1` (which would have baked the FIRST subimage name into all the output file names). Docs are updated to give examples of how to do this. Also fixed a silly typo in the test script. Signed-off-by: Larry Gritz <[email protected]>
1 parent 605504c commit 5c66cf8

File tree

4 files changed

+39
-12
lines changed

4 files changed

+39
-12
lines changed

src/doc/oiiotool.rst

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -862,11 +862,17 @@ Split a multi-image file into separate files
862862
--------------------------------------------
863863

864864
Take a multi-image TIFF file, split into its constituent subimages and
865-
output each one to a different file, with names `sub0001.tif`,
866-
`sub0002.tif`, etc.::
865+
output each one to a different file, with names `sub.0001.tif`,
866+
`sub.0002.tif`, etc.::
867867

868-
oiiotool multi.tif -sisplit -o:all=1 sub%04d.tif
868+
oiiotool multi.tif -sisplit -o:all=1 sub.%04d.tif
869869

870+
Take a multi-image OpenEXR file (called "multi-part" in OpenEXR parlance),
871+
split into its constituent subimages and output each one to a different file,
872+
with names `sub.beauty.exr`, `sub.albedo.exr`, etc., using the name of each
873+
subimage according to its metadata::
874+
875+
oiiotool multi.exr -sisplit -o:all=1 "sub.{TOP.'oiio:subimagename'}.exr"
870876

871877

872878
|
@@ -1492,17 +1498,25 @@ Writing images
14921498
Output all images currently on the stack using a pattern.
14931499
See further explanation below.
14941500

1495-
The `all=n` option causes *all* images on the image stack to be output,
1496-
with the filename argument used as a pattern assumed to contain a `%d`,
1497-
which will be substituted with the index of the image (beginning with
1498-
*n*). For example, to take a multi-image TIFF and extract all the
1499-
subimages and save them as separate files::
1501+
The `all=n` option causes *all* images on the image stack to be output. If
1502+
the *filename* argument contains expression substitution notation, the
1503+
substitution will be re-evaluated for each image output. Also, if the
1504+
*filename* argument contains a `%d`, that will be substituted with the
1505+
index of the image (beginning with *n*). For example, to take a
1506+
multi-image TIFF and extract all the subimages and save them as separate
1507+
files::
15001508
15011509
oiiotool multi.tif -sisplit -o:all=1 sub%04d.tif
15021510
15031511
This will output the subimges as separate files `sub0001.tif`,
15041512
`sub0002.tif`, and so on.
15051513

1514+
Expression substitution can be used to insert the subimage name
1515+
into each filename::
1516+
1517+
oiiotool multi.tif -sisplit -o:all=1 "sub.{TOP.'oiio:subimagename'}.tif"
1518+
1519+
15061520

15071521
.. option:: -otex <filename>
15081522
-oenv <filename>

src/oiiotool/oiiotool.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5555,6 +5555,9 @@ output_file(Oiiotool& ot, cspan<const char*> argv)
55555555
remove_all_cmd(newcmd);
55565556
new_argv[0] = newcmd.c_str();
55575557
ImageRecRef saved_curimg = ot.curimg; // because we'll overwrite it
5558+
// Revert back to the UN-expression-substituted filename. It will get
5559+
// expression substitution in the subsequent call to output_file.
5560+
filename = argv[1];
55585561
for (int i = 0; i < nimages; ++i) {
55595562
if (i < nimages - 1)
55605563
ot.curimg = ot.image_stack[i];

testsuite/oiiotool-subimage/ref/out.txt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1-
Reading gpgr.exr
2-
gpgr.exr : 64 x 64, 3 channel, half openexr
1+
subimage.layerA.exr : 64 x 64, 3 channel, half openexr
2+
SHA-1: 0C27059220A256F197900FB4EB8C7CF63349A26B
3+
subimage.layerB.exr : 64 x 64, 3 channel, half openexr
4+
SHA-1: 0E19BEFEF868E356A6A4C6450DA9A7B17DD11E12
5+
subimage.layerC.exr : 64 x 64, 3 channel, half openexr
6+
SHA-1: CFAF4AFC253320AC35B8E9014C6D750768354059
7+
subimage.layerD.exr : 64 x 64, 3 channel, half openexr
8+
SHA-1: 5FFA4616F46509627873D2C53744E47E2F492719
9+
Reading jpgr.exr
10+
jpgr.exr : 64 x 64, 3 channel, half openexr
311
4 subimages: 64x64 [h,h,h], 64x64 [h,h,h], 64x64 [h,h,h], 64x64 [h,h,h]
412
subimage 0: 64 x 64, 3 channel, half openexr
513
SHA-1: 0C27059220A256F197900FB4EB8C7CF63349A26B

testsuite/oiiotool-subimage/run.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
command += oiiotool ("subimages-4.exr --subimage 3 -o subimageD3.exr")
2525
command += oiiotool ("subimages-4.exr --subimage layerB -o subimageB1.exr")
2626
command += oiiotool ("subimages-2.exr --sisplit -o:all=1 subimage%d.exr")
27+
command += oiiotool ("subimages-4.exr --sisplit -o:all=1 \"subimage.{TOP.'oiio:subimagename'}.exr\"")
28+
command += info_command ("subimage.layerA.exr subimage.layerB.exr subimage.layerC.exr subimage.layerD.exr", verbose=False)
2729

2830
# test that we can set attributes on individual subimages
29-
command += oiiotool ("subimages-4.exr --attrib:subimages=0 Beatle John --attrib:subimages=1 Beatle Paul --attrib:subimages=2 Beatle George --attrib:subimages=3 Beatle Ringo -o gpgr.exr")
30-
command += info_command ("-a -v gpgr.exr", safematch=1)
31+
command += oiiotool ("subimages-4.exr --attrib:subimages=0 Beatle John --attrib:subimages=1 Beatle Paul --attrib:subimages=2 Beatle George --attrib:subimages=3 Beatle Ringo -o jpgr.exr")
32+
command += info_command ("-a -v jpgr.exr", safematch=1)
3133

3234
# Test extraction of MIP levels
3335
command += oiiotool ("../common/textures/grid.tx --selectmip 4 -o mip4.tif")

0 commit comments

Comments
 (0)