-
Notifications
You must be signed in to change notification settings - Fork 703
iv: tolerate partially-written EXR files #5463
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,13 @@ | |
| #ifndef OPENIMAGEIO_IV_UTILS_H | ||
| #define OPENIMAGEIO_IV_UTILS_H | ||
|
|
||
| #include <algorithm> | ||
| #include <cstring> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include <OpenImageIO/imagebuf.h> | ||
| #include <OpenImageIO/imageio.h> | ||
| #include <OpenImageIO/oiioversion.h> | ||
|
|
||
| OIIO_NAMESPACE_BEGIN | ||
|
|
@@ -33,6 +40,56 @@ floor2f(float f) | |
| return powf(2.0f, floorf(logval)); | ||
| } | ||
|
|
||
|
|
||
| /// Probe whether all of the pixel data of the image named `filename` is | ||
| /// readable, without reading the whole image: attempt to read only the | ||
| /// last scanline (for scanline files) or the last tile (for tiled files), | ||
| /// which is the most likely region to be missing from a file that was | ||
| /// only partially written. This is cheap enough to use as a check on | ||
| /// files that were read through an ImageCache, where the pixel data is | ||
| /// not touched until it is needed for display, at which point read | ||
| /// failures are much less gracefully handled. | ||
| /// | ||
| /// Returns true if the last scanline/tile could be read (and therefore it | ||
| /// is likely that the entire pixel data block is intact), false if it | ||
| /// could not (meaning that the file is probably truncated or otherwise | ||
| /// partially written). | ||
| inline bool | ||
| image_data_readable(string_view filename, const ImageSpec* config, int subimage, | ||
| int miplevel) | ||
| { | ||
|
Comment on lines
+56
to
+60
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this still needed? I understand the strategy of "read normally, and only if there's an error, try again using the missingcolor option." But why not make the "try again" step go through ImageBuf like the first one, instead of needing all this code that drops down to the ImageInput level API? Also, we should consider the merits of three approaches for iv:
|
||
| auto in = ImageInput::open(filename, config); | ||
| if (!in) | ||
| return false; | ||
| if (!in->seek_subimage(subimage, miplevel)) { | ||
| in->close(); | ||
| return false; | ||
| } | ||
| ImageSpec spec = in->spec(subimage, miplevel); | ||
| bool ok = false; | ||
| if (spec.tile_width > 0) { | ||
| // Try to read the bottom-most, right-most tile. | ||
| int tx = spec.x | ||
| + ((spec.width - 1) / spec.tile_width) * spec.tile_width; | ||
| int ty = spec.y | ||
| + ((spec.height - 1) / spec.tile_height) * spec.tile_height; | ||
| int tz = spec.z | ||
| + ((std::max(spec.depth - 1, 0)) | ||
| / std::max(spec.tile_depth, 1)) | ||
| * std::max(spec.tile_depth, 1); | ||
| std::vector<char> buf(spec.tile_bytes()); | ||
| ok = in->read_tile(tx, ty, tz, spec.format, buf.data()); | ||
| } else { | ||
| // Try to read the last scanline. | ||
| int y = spec.y + spec.height - 1; | ||
| std::vector<char> buf(spec.scanline_bytes()); | ||
| ok = in->read_scanlines(subimage, miplevel, y, y + 1, spec.z, 0, | ||
| spec.nchannels, TypeDesc::UNKNOWN, buf.data()); | ||
| } | ||
| in->close(); | ||
| return ok; | ||
| } | ||
|
|
||
| OIIO_NAMESPACE_END | ||
|
|
||
| #endif // OPENIMAGEIO_IV_UTILS_H | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not asking you to change this, because you have merely matched the style of the surrounding code, so this is more about me just talking as a note to myself: These
///doxygen-style comments should never have been in this file, since it's not a public header and we don't automatically extract any documentation from this class.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely do not want you to change the comment style on any lines you are not already altering in this PR for its primary purpose.
But if you are adding NEW lines, or it is necessary to change existing lines, then if it's not too much trouble, I would like you to use the
//regular comments, just so we aren't increasing the number of lines that we might need to come back and fix later.