Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
236d9a5801 | ||
|
|
412093fe64 | ||
|
|
c664dfccab | ||
|
|
9bdfee17d3 | ||
|
|
c2ff5c2734 | ||
|
|
58153cd995 | ||
|
|
95b7d9a263 |
+1
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
cmake_minimum_required (VERSION 3.12)
|
||||
|
||||
set (OpenImageIO_VERSION "2.5.0.2")
|
||||
set (OpenImageIO_VERSION "2.5.0.3")
|
||||
set (OpenImageIO_VERSION_OVERRIDE "" CACHE STRING
|
||||
"Version override (use with caution)!")
|
||||
mark_as_advanced (OpenImageIO_VERSION_OVERRIDE)
|
||||
|
||||
@@ -98,11 +98,13 @@ public:
|
||||
/// attribute/getattribute:
|
||||
///
|
||||
/// - `int max_open_files` :
|
||||
/// The maximum number of file handles that the image cache
|
||||
/// will hold open simultaneously. (Default = 100)
|
||||
/// The approximate maximum number of file handles that the
|
||||
/// image cache will hold open simultaneously. This is not an
|
||||
/// iron-clad guarantee; the number of handles may momentarily
|
||||
/// exceed this by a small percentage. (Default = 100)
|
||||
/// - `float max_memory_MB` :
|
||||
/// The maximum amount of memory (measured in MB) used for the
|
||||
/// internal "tile cache." (Default: 256.0 MB)
|
||||
/// The approximate maximum amount of memory (measured in MB)
|
||||
/// used for the internal "tile cache." (Default: 256.0 MB)
|
||||
/// - `string searchpath` :
|
||||
/// The search path for images: a colon-separated list of
|
||||
/// directories that will be searched in order for any image
|
||||
@@ -190,6 +192,10 @@ public:
|
||||
/// reads. The default is 1 (de-duplication turned on). The
|
||||
/// only reason to set it to 0 is if you specifically want to
|
||||
/// disable the de-duplication optimization.
|
||||
/// - `int max_open_files_strict` :
|
||||
/// If nonzero, work harder to make sure that we have
|
||||
/// smaller possible overages to the max open files limit.
|
||||
/// (Default: 0)
|
||||
/// - `string substitute_image` :
|
||||
/// When set to anything other than the empty string, the
|
||||
/// ImageCache will use the named image in place of *all*
|
||||
|
||||
@@ -545,6 +545,9 @@ public:
|
||||
/// How many times to retry a read failure.
|
||||
/// - `int deduplicate` :
|
||||
/// If nonzero, detect duplicate textures (default=1).
|
||||
/// - `int max_open_files_strict` :
|
||||
/// If nonzero, work harder to make sure that we have
|
||||
/// smaller possible overages to the max open files limit.
|
||||
/// - `string substitute_image` :
|
||||
/// If supplied, an image to substatute for all texture
|
||||
/// references.
|
||||
|
||||
@@ -84,6 +84,7 @@ using std::recursive_mutex;
|
||||
using std::thread;
|
||||
typedef std::lock_guard<mutex> lock_guard;
|
||||
typedef std::lock_guard<recursive_mutex> recursive_lock_guard;
|
||||
typedef std::lock_guard<std::recursive_timed_mutex> recursive_timed_lock_guard;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -837,6 +837,13 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Construct from a raw hash value. Beware: results are undefined if it's
|
||||
/// not the valid hash of a ustring.
|
||||
OIIO_HOSTDEVICE explicit constexpr ustringhash(hash_t hash) noexcept
|
||||
: m_hash(hash)
|
||||
{
|
||||
}
|
||||
|
||||
/// Conversion to an OIIO::string_view.
|
||||
operator string_view() const noexcept { return ustring::from_hash(m_hash); }
|
||||
|
||||
@@ -965,7 +972,7 @@ public:
|
||||
#endif
|
||||
|
||||
/// Return the ustringhash corresponding to the given hash. Caveat emptor:
|
||||
/// results are undefined if it's not the valud hash of a ustring.
|
||||
/// results are undefined if it's not the valid hash of a ustring.
|
||||
OIIO_NODISCARD static constexpr ustringhash from_hash(hash_t hash)
|
||||
{
|
||||
ustringhash u;
|
||||
@@ -977,13 +984,6 @@ private:
|
||||
// Individual ustringhash internal representation -- the hash value.
|
||||
rep_t m_hash;
|
||||
|
||||
// Construct from a raw hash value. It's protected so that it's only
|
||||
// callable by its friend, ustring.
|
||||
OIIO_HOSTDEVICE ustringhash(hash_t hashval)
|
||||
: m_hash(hashval)
|
||||
{
|
||||
}
|
||||
|
||||
friend class ustring;
|
||||
};
|
||||
|
||||
|
||||
+49
-21
@@ -105,22 +105,30 @@ struct ICCTag {
|
||||
static const char*
|
||||
icc_device_class_name(const std::string& device_class)
|
||||
{
|
||||
static std::unordered_map<std::string, const char*> device_class_names = {
|
||||
{ "scnr", "Input device profile" },
|
||||
{ "mntr", "Display device profile" },
|
||||
{ "prtr", "Output device profile" },
|
||||
{ "link", "DeviceLink profile" },
|
||||
{ "spac", "ColorSpace profile" },
|
||||
{ "abst", "Abstract profile" },
|
||||
{ "nmcl", "NamedColor profile" },
|
||||
};
|
||||
return device_class_names[device_class];
|
||||
static const std::unordered_map<std::string, const char*> device_class_names
|
||||
= {
|
||||
{ "scnr", "Input device profile" },
|
||||
{ "mntr", "Display device profile" },
|
||||
{ "prtr", "Output device profile" },
|
||||
{ "link", "DeviceLink profile" },
|
||||
{ "spac", "ColorSpace profile" },
|
||||
{ "abst", "Abstract profile" },
|
||||
{ "nmcl", "NamedColor profile" },
|
||||
};
|
||||
// std::unordered_map::operator[](const Key& key) will add the key to the map if
|
||||
// it doesn't exist. This isn't what is intended and isn't thread safe.
|
||||
// Instead, just do the lookup and return the value or a nullptr.
|
||||
//
|
||||
// return device_class_names[device_class];
|
||||
auto it = device_class_names.find(device_class);
|
||||
return (it != device_class_names.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
static const char*
|
||||
icc_color_space_name(string_view color_space)
|
||||
{
|
||||
static std::unordered_map<std::string, const char*> color_space_names = {
|
||||
// clang-format off
|
||||
static const std::unordered_map<std::string, const char*> color_space_names = {
|
||||
{ "XYZ ", "XYZ" }, { "Lab ", "CIELAB" }, { "Luv ", "CIELUV" },
|
||||
{ "YCbr", "YCbCr" }, { "Yxy ", "CIEYxy" }, { "RGB ", "RGB" },
|
||||
{ "GRAY", "Gray" }, { "HSV ", "HSV" }, { "HLS ", "HLS" },
|
||||
@@ -131,19 +139,33 @@ icc_color_space_name(string_view color_space)
|
||||
{ "BCLR", "12 color" }, { "CCLR", "13 color" }, { "DCLR", "14 color" },
|
||||
{ "ECLR", "15 color" }, { "FCLR", "16 color" },
|
||||
};
|
||||
return color_space_names[color_space];
|
||||
// clang-format on
|
||||
// std::unordered_map::operator[](const Key& key) will add the key to the map if
|
||||
// it doesn't exist. This isn't what is intended and isn't thread safe.
|
||||
// Instead, just do the lookup and return the value or a nullptr.
|
||||
//
|
||||
// return color_space_names[color_space];
|
||||
auto it = color_space_names.find(color_space);
|
||||
return (it != color_space_names.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
static const char*
|
||||
icc_primary_platform_name(const std::string& platform)
|
||||
{
|
||||
static std::unordered_map<std::string, const char*> primary_platforms = {
|
||||
{ "APPL", "Apple Computer, Inc." },
|
||||
{ "MSFT", "Microsoft Corporation" },
|
||||
{ "SGI ", "Silicon Graphics, Inc." },
|
||||
{ "SUNW", "Sun Microsystems, Inc." },
|
||||
};
|
||||
return primary_platforms[platform];
|
||||
static const std::unordered_map<std::string, const char*> primary_platforms
|
||||
= {
|
||||
{ "APPL", "Apple Computer, Inc." },
|
||||
{ "MSFT", "Microsoft Corporation" },
|
||||
{ "SGI ", "Silicon Graphics, Inc." },
|
||||
{ "SUNW", "Sun Microsystems, Inc." },
|
||||
};
|
||||
// std::unordered_map::operator[](const Key& key) will add the key to the map if
|
||||
// it doesn't exist. This isn't what is intended and isn't thread safe.
|
||||
// Instead, just do the lookup and return the value or a nullptr.
|
||||
//
|
||||
// return primary_platforms[platform];
|
||||
auto it = primary_platforms.find(platform);
|
||||
return (it != primary_platforms.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
static const char*
|
||||
@@ -158,7 +180,7 @@ icc_rendering_intent_name(uint32_t intent)
|
||||
static std::string
|
||||
icc_tag_name(const std::string& tag)
|
||||
{
|
||||
static std::unordered_map<std::string, std::string> tagnames = {
|
||||
static const std::unordered_map<std::string, std::string> tagnames = {
|
||||
{ "targ", "characterization_target" },
|
||||
{ "cprt", "copyright" },
|
||||
{ "desc", "profile_description" },
|
||||
@@ -166,7 +188,13 @@ icc_tag_name(const std::string& tag)
|
||||
{ "dmnd", "device_manufacturer_description" },
|
||||
{ "vued", "viewing_conditions_description" },
|
||||
};
|
||||
return tagnames[tag];
|
||||
// std::unordered_map::operator[](const Key& key) will add the key to the map if
|
||||
// it doesn't exist. This isn't what is intended and isn't thread safe.
|
||||
// Instead, just do the lookup and return the value or an empty string.
|
||||
//
|
||||
//return tagnames[tag];
|
||||
auto it = tagnames.find(tag);
|
||||
return (it != tagnames.end()) ? it->second : std::string();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -962,19 +962,19 @@ ImageOutput::check_open(OpenMode mode, const ImageSpec& userspec, ROI range,
|
||||
m_spec.z = 0;
|
||||
}
|
||||
}
|
||||
if (m_spec.x < range.xbegin || m_spec.x + m_spec.width >= range.xend
|
||||
|| m_spec.y < range.ybegin || m_spec.y + m_spec.height >= range.yend
|
||||
if (m_spec.x < range.xbegin || m_spec.x + m_spec.width > range.xend
|
||||
|| m_spec.y < range.ybegin || m_spec.y + m_spec.height > range.yend
|
||||
|| m_spec.z < range.zbegin
|
||||
|| m_spec.z + m_spec.depth >= range.zend) {
|
||||
|| m_spec.z + m_spec.depth > range.zend) {
|
||||
if (m_spec.depth == 1)
|
||||
errorfmt(
|
||||
"{} requested pixel data window ({}, {}] x ({}, {}] exceeds the allowable range of ({}, {}] x ({}, {}]",
|
||||
"{} requested pixel data window [{}, {}) x [{}, {}) exceeds the allowable range of [{}, {}) x [{}, {})",
|
||||
format_name(), m_spec.x, m_spec.x + m_spec.width, m_spec.y,
|
||||
m_spec.y + m_spec.height, range.xbegin, range.xend,
|
||||
range.ybegin, range.yend);
|
||||
else
|
||||
errorfmt(
|
||||
"{} requested pixel data window ({}, {}] x ({}, {}] x ({}, {}] exceeds the allowable range of ({}, {}] x ({}, {}] x ({}, {}]",
|
||||
"{} requested pixel data window [{}, {}) x [{}, {}) x [{}, {}) exceeds the allowable range of [{}, {}) x [{}, {}) x [{}, {})\n{} vs {}\n",
|
||||
format_name(), m_spec.x, m_spec.x + m_spec.width, m_spec.y,
|
||||
m_spec.y + m_spec.height, m_spec.z, m_spec.z + m_spec.depth,
|
||||
range.xbegin, range.xend, range.ybegin, range.yend,
|
||||
|
||||
@@ -329,7 +329,7 @@ ImageCacheFile::get_imageinput(ImageCachePerThreadInfo* /*thread_info*/)
|
||||
// Older gcc libstdc++ does not properly support std::atomic
|
||||
// operations on std::shared_ptr, despite it being a C++11
|
||||
// feature. No choice but to lock.
|
||||
recursive_lock_guard guard(m_input_mutex);
|
||||
recursive_timed_lock_guard guard(m_input_mutex);
|
||||
return m_input;
|
||||
#else
|
||||
// True C++11: can atomically load a shared_ptr safely.
|
||||
@@ -350,7 +350,7 @@ ImageCacheFile::set_imageinput(std::shared_ptr<ImageInput> newval)
|
||||
// feature. No choice but to lock.
|
||||
std::shared_ptr<ImageInput> oldval;
|
||||
{
|
||||
recursive_lock_guard guard(m_input_mutex);
|
||||
recursive_timed_lock_guard guard(m_input_mutex);
|
||||
oldval = m_input;
|
||||
m_input = newval;
|
||||
}
|
||||
@@ -463,7 +463,7 @@ ImageCacheFile::open(ImageCachePerThreadInfo* thread_info)
|
||||
// Now we do a lock and open it for real, to keep anybody else from
|
||||
// going through the whole opening process simultaneously.
|
||||
Timer input_mutex_timer;
|
||||
recursive_lock_guard guard(m_input_mutex);
|
||||
recursive_timed_lock_guard guard(m_input_mutex);
|
||||
m_mutex_wait_time += input_mutex_timer();
|
||||
|
||||
// JUST IN CASE somebody else opened the file we want, between when we
|
||||
@@ -840,6 +840,7 @@ ImageCacheFile::read_tile(ImageCachePerThreadInfo* thread_info, int subimage,
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
m_broken = true;
|
||||
std::string err = inp->geterror();
|
||||
if (errors_should_issue()) {
|
||||
imagecache().error("{}",
|
||||
@@ -1071,13 +1072,23 @@ ImageCacheFile::close()
|
||||
void
|
||||
ImageCacheFile::release()
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
Timer input_mutex_timer;
|
||||
recursive_lock_guard guard(m_input_mutex);
|
||||
bool locked = m_input_mutex.try_lock_for(100ms);
|
||||
m_mutex_wait_time += input_mutex_timer();
|
||||
if (!locked) {
|
||||
// Oh boy, somebody is holding this lock. Rather than sit here even
|
||||
// longer (or even worse -- deadlock), just punt and return. The worst
|
||||
// that can happen is that a file that should have had its handle
|
||||
// reclaimed might get held open a little longer. If there's lots of
|
||||
// pressure on the cache, it'll get freed next time around.
|
||||
return;
|
||||
}
|
||||
if (m_used)
|
||||
m_used = false;
|
||||
else if (m_allow_release)
|
||||
close();
|
||||
m_input_mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -1086,7 +1097,7 @@ void
|
||||
ImageCacheFile::invalidate()
|
||||
{
|
||||
Timer input_mutex_timer;
|
||||
recursive_lock_guard guard(m_input_mutex);
|
||||
recursive_timed_lock_guard guard(m_input_mutex);
|
||||
m_mutex_wait_time += input_mutex_timer();
|
||||
close();
|
||||
invalidate_spec();
|
||||
@@ -1213,7 +1224,10 @@ ImageCacheImpl::find_file(ustring filename,
|
||||
}
|
||||
|
||||
if (newfile) {
|
||||
check_max_files(thread_info);
|
||||
// We don't need to check_max_files here, because open() already
|
||||
// does it, and we're only trying to limit the number of open
|
||||
// files, not the number of entries in the cache.
|
||||
// check_max_files(thread_info);
|
||||
if (!tf->duplicate())
|
||||
++thread_info->m_stats.unique_files;
|
||||
}
|
||||
@@ -1251,7 +1265,7 @@ ImageCacheImpl::verify_file(ImageCacheFile* tf,
|
||||
if (!thread_info)
|
||||
thread_info = get_perthread_info();
|
||||
Timer input_mutex_timer;
|
||||
recursive_lock_guard guard(tf->m_input_mutex);
|
||||
recursive_timed_lock_guard guard(tf->m_input_mutex);
|
||||
tf->m_mutex_wait_time += input_mutex_timer();
|
||||
if (!tf->validspec()) {
|
||||
tf->open(thread_info);
|
||||
@@ -1355,11 +1369,13 @@ ImageCacheImpl::check_max_files(ImageCachePerThreadInfo* /*thread_info*/)
|
||||
if (open_files < m_max_open_files) {
|
||||
// Early out if we aren't exceeding the open file handle limit
|
||||
return;
|
||||
} else if (open_files < m_max_open_files + 16) {
|
||||
// If we're only exceeding the open files limit by a little bit, try
|
||||
// to grab the file_sweep_mutex lock. If we get it, we do the cleanup.
|
||||
// But if somebody else holds it, just return rather than blocking,
|
||||
// leaving the handle limit enforcement to whomever is already in this
|
||||
}
|
||||
if (!m_max_open_files_strict || open_files < m_max_open_files + 16) {
|
||||
// If we're only exceeding the open files limit by a little bit (or by
|
||||
// any amount if we aren't trying to be strict about), try to grab the
|
||||
// file_sweep_mutex lock. If we get it, we do the cleanup. But if
|
||||
// somebody else holds it, just return rather than blocking, leaving
|
||||
// the handle limit enforcement to whomever is already in this
|
||||
// function or gets here next. No need for two threads to do it at
|
||||
// once or to block. If this means we may ephemerally be over the
|
||||
// handle limit, so be it.
|
||||
@@ -1645,6 +1661,7 @@ ImageCacheImpl::init()
|
||||
m_stat_open_files_created = 0;
|
||||
m_stat_open_files_current = 0;
|
||||
m_stat_open_files_peak = 0;
|
||||
m_max_open_files_strict = false;
|
||||
|
||||
// Allow environment variable to override default options
|
||||
const char* options = getenv("OPENIMAGEIO_IMAGECACHE_OPTIONS");
|
||||
@@ -1833,6 +1850,7 @@ ImageCacheImpl::getstats(int level) const
|
||||
opt += Strutil::fmt::format("max_memory_MB={:0.1f} ",
|
||||
m_max_memory_bytes / (1024.0 * 1024.0));
|
||||
INTOPT(max_open_files);
|
||||
BOOLOPT(max_open_files_strict);
|
||||
INTOPT(autotile);
|
||||
INTOPT(autoscanline);
|
||||
INTOPT(automip);
|
||||
@@ -2194,6 +2212,8 @@ ImageCacheImpl::attribute(string_view name, TypeDesc type, const void* val)
|
||||
m_failure_retries = *(const int*)val;
|
||||
} else if (name == "trust_file_extensions" && type == TypeDesc::INT) {
|
||||
m_trust_file_extensions = *(const int*)val;
|
||||
} else if (name == "max_open_files_strict" && type == TypeDesc::INT) {
|
||||
m_max_open_files_strict = *(const int*)val;
|
||||
} else if (name == "latlong_up" && type == TypeDesc::STRING) {
|
||||
bool y_up = !strcmp("y", *(const char**)val);
|
||||
if (y_up != m_latlong_y_up_default) {
|
||||
@@ -2313,6 +2333,7 @@ ImageCacheImpl::getattribute(string_view name, TypeDesc type, void* val) const
|
||||
ATTR_DECODE("deduplicate", int, m_deduplicate);
|
||||
ATTR_DECODE("unassociatedalpha", int, m_unassociatedalpha);
|
||||
ATTR_DECODE("trust_file_extensions", int, m_trust_file_extensions);
|
||||
ATTR_DECODE("max_open_files_strict", int, m_max_open_files_strict);
|
||||
ATTR_DECODE("failure_retries", int, m_failure_retries);
|
||||
ATTR_DECODE("total_files", int, m_files.size());
|
||||
ATTR_DECODE("max_mip_res", int, m_max_mip_res);
|
||||
@@ -3399,7 +3420,7 @@ ImageCacheImpl::invalidate(ImageHandle* handle, bool force)
|
||||
if (!force) {
|
||||
// If not in force mode, we don't do anything if the modification
|
||||
// time of the file has not changed since we opened it.
|
||||
recursive_lock_guard guard(file->m_input_mutex);
|
||||
recursive_timed_lock_guard guard(file->m_input_mutex);
|
||||
if (file->mod_time() == Filesystem::last_write_time(file->filename())
|
||||
&& !file->broken())
|
||||
return;
|
||||
@@ -3471,7 +3492,7 @@ ImageCacheImpl::invalidate_all(bool force)
|
||||
const ImageCacheFileRef& f(fileit->second);
|
||||
ustring name = f->filename();
|
||||
Timer input_mutex_timer;
|
||||
recursive_lock_guard guard(f->m_input_mutex);
|
||||
recursive_timed_lock_guard guard(f->m_input_mutex);
|
||||
f->m_mutex_wait_time += input_mutex_timer();
|
||||
// If the file was broken when we opened it, or if it no longer
|
||||
// exists, definitely invalidate it.
|
||||
|
||||
@@ -396,8 +396,9 @@ private:
|
||||
mutable int m_errors_issued; ///< Errors issued for this file
|
||||
std::vector<size_t> m_mipreadcount; ///< Tile reads per mip level
|
||||
ImageCacheImpl& m_imagecache; ///< Back pointer for ImageCache
|
||||
mutable recursive_mutex m_input_mutex; ///< Mutex protecting the ImageInput
|
||||
std::time_t m_mod_time; ///< Time file was last updated
|
||||
mutable std::recursive_timed_mutex
|
||||
m_input_mutex; ///< Mutex protecting the ImageInput
|
||||
std::time_t m_mod_time; ///< Time file was last updated
|
||||
ustring m_fingerprint; ///< Optional cryptographic fingerprint
|
||||
ImageCacheFile* m_duplicate; ///< Is this a duplicate?
|
||||
imagesize_t m_total_imagesize; ///< Total size, uncompressed
|
||||
@@ -1173,6 +1174,7 @@ private:
|
||||
bool m_unassociatedalpha; ///< Keep unassociated alpha files as they are?
|
||||
bool m_latlong_y_up_default; ///< Is +y the default "up" for latlong?
|
||||
bool m_trust_file_extensions = false; ///< Assume file extensions don't lie?
|
||||
bool m_max_open_files_strict = false; ///< Be strict about open files limit?
|
||||
int m_failure_retries; ///< Times to re-try disk failures
|
||||
int m_max_mip_res = 1 << 30; ///< Don't use MIP levels higher than this
|
||||
Imath::M44f m_Mw2c; ///< world-to-"common" matrix
|
||||
|
||||
@@ -914,7 +914,7 @@ RawInput::open_raw(bool unpack, const std::string& name,
|
||||
add("Exif", "Pressure", common.exifPressure, false, 0.0f);
|
||||
add("Exif", "WaterDepth", common.exifWaterDepth, false, 0.0f);
|
||||
add("Exif", "Acceleration", common.exifAcceleration, false, 0.0f);
|
||||
add("Exif", "CameraElevactionAngle", common.exifCameraElevationAngle, false,
|
||||
add("Exif", "CameraElevationAngle", common.exifCameraElevationAngle, false,
|
||||
0.0f);
|
||||
// float real_ISO;
|
||||
#elif LIBRAW_VERSION >= LIBRAW_MAKE_VERSION(0, 19, 0)
|
||||
@@ -931,7 +931,7 @@ RawInput::open_raw(bool unpack, const std::string& name,
|
||||
add("Exif", "Pressure", other.exifPressure, false, 0.0f);
|
||||
add("Exif", "WaterDepth", other.exifWaterDepth, false, 0.0f);
|
||||
add("Exif", "Acceleration", other.exifAcceleration, false, 0.0f);
|
||||
add("Exif", "CameraElevactionAngle", other.exifCameraElevationAngle, false,
|
||||
add("Exif", "CameraElevationAngle", other.exifCameraElevationAngle, false,
|
||||
0.0f);
|
||||
// float real_ISO;
|
||||
#endif
|
||||
|
||||
@@ -2253,8 +2253,9 @@ TIFFInput::read_native_tiles(int subimage, int miplevel, int xbegin, int xend,
|
||||
// xbegin, xend, ybegin, yend, zbegin, zend);
|
||||
size_t tileidx = 0;
|
||||
for (int z = zbegin; z < zend; z += m_spec.tile_depth) {
|
||||
for (int y = ybegin; y < yend; y += m_spec.tile_height) {
|
||||
for (int x = xbegin; x < xend; x += m_spec.tile_width, ++tileidx) {
|
||||
for (int y = ybegin; ok && y < yend; y += m_spec.tile_height) {
|
||||
for (int x = xbegin; ok && x < xend;
|
||||
x += m_spec.tile_width, ++tileidx) {
|
||||
char* cbuf = compressed_scratch.get() + tileidx * cbound;
|
||||
char* ubuf = scratch.get() + tileidx * tile_bytes;
|
||||
auto csize = TIFFReadRawTile(m_tif, tile_index(x, y, z), cbuf,
|
||||
@@ -2264,7 +2265,8 @@ TIFFInput::read_native_tiles(int subimage, int miplevel, int xbegin, int xend,
|
||||
errorfmt(
|
||||
"TIFFReadRawTile failed reading tile x={},y={},z={}: {}",
|
||||
x, y, z, err.size() ? err.c_str() : "unknown error");
|
||||
return false;
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
// Push the rest of the work onto the thread pool queue
|
||||
auto out = this;
|
||||
@@ -2289,6 +2291,7 @@ TIFFInput::read_native_tiles(int subimage, int miplevel, int xbegin, int xend,
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks.wait();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info -v src/crash-1633.tif
|
||||
oiiotool ERROR: read : File does not exist: "src/crash-1643.tif"
|
||||
Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info -v src/crash-1643.tif
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info src/crash-1643.tif -o out.exr
|
||||
iconvert ERROR copying "src/crash-1709.tif" to "crash-1709.exr" :
|
||||
Decoding error at scanline 0, incorrect header check
|
||||
Comparing "check1.tif" and "ref/check1.tif"
|
||||
PASS
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
Reading src/separate.tif
|
||||
src/separate.tif : 128 x 128, 3 channel, uint8 tiff
|
||||
SHA-1: 486088DECAE711C444FDCAB009C378F7783AD9C5
|
||||
channel list: R, G, B
|
||||
compression: "zip"
|
||||
DateTime: "2020:10:25 15:32:04"
|
||||
Orientation: 1 (normal)
|
||||
planarconfig: "separate"
|
||||
Software: "OpenImageIO 2.3.0dev : oiiotool --pattern fill:topleft=0,0,0:topright=1,0,0:bottomleft=0,1,0:bottomright=1,1,1 128x128 3 --planarconfig separate -scanline -attrib tiff:rowsperstrip 17 -d uint8 -o separate.tif"
|
||||
oiio:BitsPerSample: 8
|
||||
tiff:Compression: 8
|
||||
tiff:PhotometricInterpretation: 2
|
||||
tiff:PlanarConfiguration: 2
|
||||
tiff:RowsPerStrip: 7
|
||||
Comparing "src/separate.tif" and "separate.tif"
|
||||
PASS
|
||||
oiiotool ERROR: read : No support for data format of "src/corrupt1.tif"
|
||||
Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info -v src/corrupt1.tif
|
||||
oiiotool ERROR: read : File does not exist: "src/crash-1633.tif"
|
||||
Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info -v src/crash-1633.tif
|
||||
oiiotool ERROR: read : File does not exist: "src/crash-1643.tif"
|
||||
Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info src/crash-1643.tif -o out.exr
|
||||
iconvert ERROR copying "src/crash-1709.tif" to "crash-1709.exr" :
|
||||
Decoding error at scanline 0, incorrect header check
|
||||
Comparing "check1.tif" and "ref/check1.tif"
|
||||
PASS
|
||||
@@ -22,6 +22,8 @@ Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info -v src/crash-1633.tif
|
||||
oiiotool ERROR: read : File does not exist: "src/crash-1643.tif"
|
||||
Full command line was:
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info -v src/crash-1643.tif
|
||||
> oiiotool --oiioattrib try_all_readers 0 --info src/crash-1643.tif -o out.exr
|
||||
iconvert ERROR copying "src/crash-1709.tif" to "crash-1709.exr" :
|
||||
|
||||
Comparing "check1.tif" and "ref/check1.tif"
|
||||
PASS
|
||||
|
||||
@@ -17,6 +17,7 @@ command += rw_command ("src", "separate.tif")
|
||||
# Test bugs we had until OIIO 2.4 for these corrupt file
|
||||
command += oiiotool ("--oiioattrib try_all_readers 0 --info -v src/corrupt1.tif", failureok = True)
|
||||
command += oiiotool ("--oiioattrib try_all_readers 0 --info -v src/crash-1633.tif", failureok = True)
|
||||
command += oiiotool ("--oiioattrib try_all_readers 0 --info -v src/crash-1643.tif", failureok = True)
|
||||
command += oiiotool ("--oiioattrib try_all_readers 0 --info src/crash-1643.tif -o out.exr", failureok = True)
|
||||
command += iconvert ("src/crash-1709.tif crash-1709.exr", failureok=True)
|
||||
|
||||
outputs = [ "check1.tif", "out.txt" ]
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user