Compare commits

...
621 Commits
Author SHA1 Message Date
Larry Gritz 236d9a5801 Bump version to 2.5.0.3 2023-03-08 13:55:14 -08:00
Larry Gritz 412093fe64 fix(IC/TS): Avoid deadlock situations with file handle cache (3784)
There turns out to be a way to get wedged into a mutual deadlock on
the file handle cache, with how get_texture_info on a udim pattern
checks to see if the attribute requested is present and equally valued
in all constituent files of the udim set. This hits the handle set
pretty hard, and if multiple threads are hammering the same sets and
rapidly cycling textures out of the cache, there can be trouble, it
seems.

Remedies in this patch:

* When it's trying to close files because the number of handles is too
  high, we already had it so that if we only exceeded the max_files
  limit by a little bit, we would simply try to get the lock, and
  abandon the attempt if somebody else is holding it, but if we are
  quite a bit over, then stay and wait for the lock to be released.

  In this patch, we make the that default behavior -- if we are over
  the limit and need to free some handles, simply try to get the lock,
  and if somebody else is holding it, leave it all up to them and
  return immediately. The pros of this are (a) snappier response by
  never waiting at this point, and (b) removing the possibility of a
  deadlock, because if you can't acquire the lock, you just move
  on. But the con is that lots of threads adding new files may run
  faster than the one thread who has the file and is trying to release
  files, so it's possible that the number of handles will exceed the
  limit by a wider margin now, but hopefully only momentarily.  (But
  note that this can be overridden with a new ImageCache attribute
  "max_open_files_strict", which if set to nonzero revert to the old
  behavior. At least for now, in case I am neglecting to understand
  some bad consequence of this change.)

* The recursive_mutex controlling access to the ImageInput in each
  tile cache record is changed to a recursive_timed_mutex, and when
  closing a handle by calling release(), instead of an unconditional
  lock, try acquiring a lock for 100ms. If it fails to do so, it may
  be in a possible deadlock, so just give up and move on. The only
  consequence is that maybe that handle isn't freed after all. It will
  then move on to the next one, not the end of the world, but at least
  it can't get stuck there.

* In find_file, eliminate the call to check_max_files -- it's not
  needed here, since it's also called by open(), which is the only
  time that new file handles might be opened. We just don't also need
  it again simply because we're adding a file to the cache.
2023-03-08 11:22:48 -08:00
Fabien Castan c664dfccab rawinput: fix typo on CameraElevationAngle (#3783) 2023-03-08 11:11:15 -08:00
Larry Gritz 9bdfee17d3 api(ustringhash): make a public explicit ustringhash ctr from hash value (#3778) 2023-03-08 11:11:14 -08:00
Larry Gritz c2ff5c2734 fix: race condition in TIFF reader (#3772)
* test: Add a corrupted test file

* fix(IC): upon tile read error, mark the file as broken

The idea is to keep fruitlessly reading from a corrupted file.

* fix: race condition in TIFF reader

TIFFInput::read_native_tiles had a very subtle race condition.  There
is a section where it has a task_set of decompression tasks that are
sent to the thread queue.  When the method ends, the task_set goes out
of scope, and its destructor will wait for all the remaining tasks to
finish. All fine, right? Except that other variables in the function
include unique_ptr's with allocated memory that the tasks need.  So
what can happen is that if the compiler generates the code such that
the destructor of the unique_ptr happens before the destructor of the
task_set, the memory that the unique_ptr held may be deallocated
before some of the tasks still running in threads have finished.

In practice, we seem only to hit this race condition for particular
cases involving corrupted files, because the early `return` seems
quite likely to run those destructors before all the threads are done,
but it was possible to encounter it for valid files as well, if the
timing is just right. Shocking that we never had it reported.

The solution is just to have an explitit tasks.wait(), which will
block until all the tasks have finished before hitting the actual end
of the method and letting the other destructors to run. And for the
"early return" case, change it to a break so that we go through the
wait call at the end.

I believe that this fix addresses TALOS-2023-1709 / CVE-2023-24472.
2023-03-08 11:11:14 -08:00
angusdavisadobeandLarry Gritz 58153cd995 improve thread safety for concurrent tiff loads (#3767)
* Make lookups of const unordered_maps thread-safe

* added back deleted end brace

* clang-format

---------

Co-authored-by: Larry Gritz <lg@larrygritz.com>
2023-03-08 11:11:14 -08:00
Larry Gritz 95b7d9a263 fix: ImageOutput::check_open error conditions (#3769)
For non-0-origin images, we were checking the resolution range
incorrectly (`>=` vs `>`).

Also were printing the error message with the wrong notation, should
have shown a half-open range as `[beg,end)` and not `(beg,end]`.
2023-03-08 11:11:14 -08:00
Larry Gritz f2a10108b3 fix(ImageCache): Avoid bad IC stats when no files were read (#3765) 2023-02-04 14:51:48 -08:00
jreichel-nvidiaandJoachim Reichel a8b93f0ccc Initialize OpenEXROutput::m_levelmode() in init(). (#3764)
Avoids conditional jump on uninitialised values in close().

Co-authored-by: Joachim Reichel <joachim.reichel@posteo.de>
2023-02-04 14:51:17 -08:00
Latios96 3b34231a3a Fix unresolved external symbol for MSVS 2017 (#3762) (#3763)
If char16_t is used as template argument, this leads to an unresolved symbol for MSVS 2017.
Use int16_t instead of char16_t in this case
2023-02-02 15:22:33 -08:00
Larry Gritz e2e5eba95d Update ref image 2023-01-26 15:09:48 -08:00
Larry Gritz 963b46a3d9 iff: Temporarily address breakage with optional IOProxy revert (#3760)
When we recently added IOProxy support to the Maya iff file reader in
PR 3647, something broke for certain (but not all) iff files, and I
have productions stumbling over this.

It's proving tricky to track down and I have shows needing a fix
immediatly, so this change sets up a CMake variable
ENABLE_RLA_IOPROXY, default to ON, but when set to OFF, it switches
back to the old "no proxy" versions of the iff reader.

Disabling this will get me out of my current emergency -- at the cost
of not having IOProxy for iff, which I don't need at this moment
anyway -- and give me some breathing room to fix the problem for real,
at which point I will re-remove the old code.
2023-01-26 13:52:26 -08:00
Larry Gritz e59397ad7c Add ColorConfig::getColorSpaceIndex -- look up index by name (#3758) 2023-01-22 23:33:00 -08:00
Larry Gritz 91a2bc4814 Minor IBA python binding internal refactor: vecresize utility (#3757)
There's a recurring idiom spread all over the python bindings for
ImageBufAlgo, which I encapsulate in a new local helper template
vecresize(). This ensures that the logic is identical in all the
places it's used, and also improves our coverage analysis (because it
was tricky to make tests that exercise the uninitialized-handling
cases separately for each of the many different places the idiom was
used).
2023-01-22 12:56:06 -08:00
Larry Gritz 4f180d13f8 Improve OCIO (especially 2.2) support and better testing (#3755)
Tweak the heuristics for trying to determine which arbitrary-named
color spaces are equivalent to certain known common names.

For OCIO 2.2+, some of this is easier and more reliable by using the
new built-in color spaces -- for example, we can transform a set of
sentinel colors from an arbitrary cs into the known built-in acescg,
or lin_srgb, etc., and if the values don't change, we know that cs
*is* the canonical one, even if named something weird.

But one problem is that for older OCIO, the built-in config is not
present, so if you have a color space named, I dunno, "linear", it's
hard to know what that is. Is it what we now call lin_srgb? Is it
ACEScg?  Something else? So the hack is: first, we try to identify a
space that we think is sRGB (almost all configs have something called
"srgb", because everybody needs it, and we take it at face value that
if they call a cs "srgb", it's the real "srgb", fools who use the name
for something else get what they deserve). We transform the sentinel
colors from the srgb into the cs we are interrogating, and if they
match what we expect to see from an srgb->lin_srgb transformation,
then guess what -- the unknown color space must be lin_srgb!

We may, in the future, expand this to deduce other spaces. But this is
a start.

There are other changes I made here to make this whole process much
less expensive than it had been getting, there was some redundant
work, and some work that only was useful for 2.2 or only useful for <=
2.1, so I only do those in the right circumstances now.

Also along for the ride: improve test coverage for maketx features of
colorconvert, unpremult, attrib, attrib.
2023-01-21 15:22:18 -08:00
Larry Gritz b311d51e3d Fix CHANGES typo 2023-01-20 09:10:32 -08:00
Larry Gritz 3fc4293a42 Update CVE designations in CHANGES 2023-01-19 13:38:38 -08:00
Larry Gritz 59f54c80b2 Spend less wasted time zeroing out ImageBuf (#3754)
Examining some timings and function call counts, I saw that a typical
oiiotool command was spending a surprising amount of time in
ImageBufAlgo::zero(), not just more runtime overall, but also calling
it many more times than I thought it should.  For example,

    oiiotool -create 4096x4096 3 -colorconvert srgb acescg

called ImageBufAlgo::zero()... 4 times, totaling as much time as the
colorconvert operation.

The idiom used in `IBA::op(dst, src, ...)` which initializes the `dst`
IB if it's not already initialized will call the IB constructor that
zeros out its contents (so you don't have every new IB full of garbage
pixel values). But for IBA functions, this is almost never necessary,
since the IBA function itself will tend to overwrite all pixel values.
Not always, of course -- since IBA functions let you restrict the
spatial area or channel range -- but in the cases where the
destination starts out uninitialized and is allocated to exactly mtch
the ROI, I *think* you can count on the calling IBA function filling
in all those values.

So I changed IBAPrep() to call the IB constructor that says not to
zero out the pixels.

Just in case we ever need the ability, I made a new flag value that
lets you call IBAPrep and tell it, yes, do zero out any newly
allocated buffers. But we pass the testsuite without needing that flag
anywhere, so I think we're ok.

Also, the --create command itself would make new buffers (with the
implied zeroing), and then explicitly zero it again!

So after these changes, the oiiotool example command line above only
calls IBA::zero() ONCE (correctly, in the initial new image --create
makes), eliminating three redundant calls.

I also hypothesized that each call to zero was taking too much time,
because underneath it was calling IBA::fill which laboriously walked
through the IB with iterators and copying a fixed pixel value that
happened to contain 0 values. So I rewrote a special case where if the
buffer had contiguous strides, it would just use memset instead.
Surprisingly, it was not appreciably faster, and I'm guessing that the
memory bandwidth necessary to touch every pixel in a 4k buffer is the
limiting factor, and the other pixel-by-pixel iterator diddling was
inconsequential compared to waiting for the memory bus. I'm still
going to leave this "optimization" in, even though it was barely
measurable for the case I was trying.
2023-01-17 23:26:37 -08:00
Larry Gritz 0a8311b885 Simplify oiiotool --resize recent changes (#3752)
No need for separate :offset= modifier, the :to= can already be
used for this purpose.
2023-01-17 23:26:04 -08:00
Larry Gritz 7e0ed37e97 Minor Timer and LoggedTimer class tweaks (#3753)
Timer:

* Fix goof where m_printdtr was a bool but was tested for equality to
  an enum. It happened to work like that, but only coincidentally.

* Add another enum value that allows a debugging message to be printed
  upon construction of the timer, in addition to its destruction.

* Switch from printf style to std::print style formatting of the
  debugging messages.

LoggedTimer:

* Modify to allow modifying the call count.  This turns out to be
  helpful for times when one logged function calls another logged
  function (like if a special case is broken out) and they both log to
  the same timer -- it makes it look like just one invocation instead
  of two.
2023-01-17 23:25:49 -08:00
Larry Gritz fd05534d44 Expanded functionality of oiiotool --resize (#3751)
Currently, --resize takes a single argument giving an "image geometry"
(like "640x480") that designates the size of the result image, and the
rescaling specifically maps the "full size" (a.k.a. display window) of
the input image to the output.

This experimental change extends --resize to accept additional new
optional modifiers:

- ":from=<geom>" Overrides the default of the full window of the
  source.

- ":to=<geom>" Overrides the default of the full window of the
  destination.

- ":offset=+x+y" Adds an additional offset transformation to the
  destination.

- ":edgeclamp=<0|1>" Turns on and off some special edge sample
  clamping to try to reduce certain ringing artifacts. (Experimental.)

Unlike the output resolution, which like all image sizes must be an
integer resolution, the overrides on the source and destination
windows and the offset is allowed to be floating point, that is,
allowing for fractional pixel sizes or offsets.

The from and to windows do not restrict the boundaries of pixels
computed, but rather, simply define the transformational mapping
between the two images: the transformation will be chosen such that
the float-valued coordinates of the source image correspond exactly to
the float-valued coordintes within the destination image. In both
cases, coordinates refer to the true continuous coordinates in the
image plane, with (0.0, 0.0) being the "upper left" corner, and pixel
centers being at half-unit positions such as (ipixel+0.5, jpixel+0.5).

For example,

    oiiotool in.exr -resize:from=100x50.3+50+20 1000x503 -o out.exr

creates a 1000x503 pixel image where the full output image is a
resized version of the 100x50.3 pixel window starting at coordinates
(50,20) in the input image.

This is mostly implemented (when it doesn't end up equivalent to the
old style resize) in terms of the existing IBA::warp() function. I needed
to add a new variety of warp() to avoid some artifacts, but I do this
tentatively and so currently do not expose it as part of the public API.
I want to gain some experience with the oiiotool usage by the users who
requested this, then will return later to exactly how it should be
exposed directly as IBA functions.
2023-01-12 15:57:35 -08:00
Larry Gritz c2781d7a8d TIFF: refine logic for setting PhotometricInterpretation on output (#3746)
Some background: TIFF allows for pixel values to be encoded in some
alternative color spaces, like YCbCr, CIELAB, etc., and this is
indicated by the TIFF PhotometricInterpretation tag. Since in practice
we almost never encounter these encodings in the wild, and they
require a lot of custom code to handle (for example, YCbCr also comes
along with the ability to subsample the chroma, and options for
different placements of the subsampled positions, yuck), for most of
these cases we just lean on libtiff's ability to convert the whole
thing to RGBA for us, and so in that case, we return to the user the
pixels as RGBA, and set the "tiff:ColorSpace" metadata just as an
advisory to indicate how it had been encoded in the file. But we don't
support writing any of those. (One exception is that we do allow
reading and writing of CMYK files.)

OK, but now what about a case where the app already has the data in
one of these spaces (such as YCrCb; and let's ignore the whole
subsampling miasma and assume we don't want to support that), and all
we want to do is write that data to a TIFF file -- without any kind of
data conversion -- but to set the TIFF tags properly to indicate that
the data in the file is what we know it to be?

A related special case of this is: what if we have a TIFF file that
has YCbCr data but neglected to mark it as such (I'm staring daggers
at a certain widely used compositing package right now), and to fix
this, we want to use OIIO to just copy the file and set the right tags?

It turns out that in the status quo, it is surprisingly difficult to
do this. There is just nothing in our existing TIFF output code that
will write any of those photometric tags for those spaces, and no way
to communicate that this is what we desire.

Whew. Now here's what this patch does:

* If the "oiio:ColorSpace" attribute (our usual way to indicate
  presumed color space of the pixel data) says that the pixels are
  already in one of those color spaces (specifically, "YCbCr",
  "CIELAB", "ICCLAB", "ITULAB", "LOGL", "LOGLUV"), then we set the
  PhotometricInterpretation tag as such in the TIFF file that we
  write.

* We still DO NOT interpret that as a request to convert pixel data
  from any other space into this one. In other words, the TIFF output
  does not convert color spaces (except for RGB <-> CMYK); this merely
  lets us output a file that correctly says the data are what the app
  thinks they are.

* A bunch of minor refactoring was necessary because of some unobvious
  coupling and order dependencies. For example, the sgilog compression
  techniques MUST be used with the LOGLUV color space, and vice versa.
  You have to know how both should be set before checking that they
  are compatible, and if they are not, adjust something that it's not
  too late to change.

So the punchline at the end is that if you had a TIFF file that has
YCbCr encoded pixels, but for some reason it's marked as ordinary RGB,
you can fix it as follows:

    oiiotool ycbcr_disguised_as_rgb.tif --iscolorspace YCbCb -o real_ycbcr.tif
2023-01-12 14:32:11 -08:00
Larry Gritz b6b6230a1b Bump version after recent developer preview tag 2023-01-12 14:29:27 -08:00
Brecht Van Lommel dfb086e130 Fix wrong oiio:UnassociatedAlpha spec for PSD files (#3750)
Refactoring in #1641 incorrectly caused this to be set on the last layer
rather than the composite image as before. Now set it on the composite
image and every layer, as all of them use unassociated alpha.
2023-01-09 11:18:33 -08:00
Larry Gritz 496b374e9c Testing: improve testing of maketx (#3748)
* Tests for maketx -u, --attrib, --sattrib, --cdf

* maketx was documeted to take --cdf as a simple flag, but was
  incorrectly implemented as requiring a (pointless) nonzero argument.
  Fix it and hope nobody was depending on the undocumented behavior.

* maketx -v arg never had any effect. Add it back.
2023-01-08 19:19:00 -08:00
Larry Gritz 1f2e6b9990 Comment out parts of libcineon that are not used by OIIO (#3747) 2023-01-08 18:34:06 -08:00
Larry Gritz 1026d7b18d Clarify comments in documentation of IBA::make_texture 2023-01-08 14:22:23 -08:00
Larry Gritz b4dad279a9 Additional testing and improved code coverage (and minor fixes) (#3745)
* Better Typedesc testing of 'tostring' with fmt style formatting
  commands, and fix a bug that uncovered.

* Refine 'make CODECOV=1' behavior

* Beef up python-imagecache test to test getpixels, more attribute,
  invalidate.

* Better testing of python IB construction from numpy array.

* testtex: Use correct guard to avoid compiling unused code for
  coverage analysis testtex: get rid of unused 3d warp code.

* Add texture-threadtimes test

* Eliminate redundant code in exroutput.c by implementing
  write_scanline using write_scanlines.
2023-01-08 14:17:43 -08:00
Joris NijsandJoris Nijs 8cfa5f90b5 Add EXIF write support to PNG output. (#3736)
* Add Exif write support to PNG output.

Stores any Exif data from the given ImageSpec into the PNG eXIf chunk.

* add test for writing Exif data in png

* add test reference output for libpng versions not supporting the eXIf chunk.

* Update testsuite/png/ref/out-libpng15.txt

Co-authored-by: Joris Nijs <joris.nijs@esko.com>
2023-01-08 11:46:12 -08:00
Larry Gritz 6acaac4d08 Docs: minor improvments in description of ociodisplay and others 2023-01-08 10:16:59 -08:00
Larry Gritz ff1f577c08 ImageSpec:set_colorspace() (#3734)
Sets color space metadata. While conceptually, the main job is to call
`attribute("oiio:ColorSpace",name)`, this is a central spot to add
logic that adjusts or removes other contradictory metadata.
2023-01-07 23:49:18 -08:00
Larry Gritz 43c13ae9c8 Docs: for rtd, upgrade sphinx/breathe versions, use furo theme (#3737)
I think this looks better.

Also a few minor tweaks to typos and misquotes.
2023-01-07 23:46:29 -08:00
Larry Gritz da51cd9167 Revert #3728, that was ill advised (#3740)
Note that these intrinsics don't seem to be available for gcc.
They are available on clang, but are defined in terms of the memcpy
trick. But in Intel, they seem to actually help.
2023-01-07 23:45:21 -08:00
Larry Gritz 89c5802990 CI: Lock down to older icc so it's not broken (#3744)
The new 2023 one on the Intel site seems to require a glibc too new to
be compatible with the one on the ASWF CentOS-7 based containers, so
has been breaking our CI for a couple weeks.
2023-01-07 17:41:43 -08:00
Larry Gritz a3843e2597 CHANGES 2023-01-04 19:01:07 -08:00
Larry Gritz 16948f64a2 Testing: get rid of testtex's datatime query, for test consistency (#3741) 2023-01-04 19:00:25 -08:00
Larry Gritz 1b9ce86821 Update ref image 2023-01-04 14:51:38 -08:00
Larry Gritz d5be2d16cb CMake config should not include a find of fmt if it's internalized (#3739) 2023-01-03 18:11:47 -08:00
Larry Gritz dad63699ed CI: Temporarily lock fmt to 9.1.0 because its master seems broken (#3738)
Investigate later. For now, this is necessary for us to pass CI.
2023-01-03 17:06:04 -08:00
Larry Gritz c023ec6004 Update ref output 2023-01-03 14:34:36 -08:00
Larry Gritz d5670ff858 Move ARM_NEON definition and fix possible double define (#3735)
It should not have been set in platform.h (inside the cpuid function!)
in the first place. And apparently, though this was ok for Windows ARM,
on Mac ARM it's an error because that symbol is already defined.
So only redefine it if it's currently undefined. And move the whole
check and definition into simd.h where all the other ARM_NEON stuff
lives.
2023-01-03 11:36:35 -08:00
Larry Gritz 3b8807df85 Fix date 2023-01-01 09:51:26 -08:00
Larry Gritz c3a15ed84e CHANGES 2023-01-01 00:01:26 -08:00
Larry Gritz 0b9e9d7ed7 Add testing for maketx --lightprobe, fix bugs (#3732)
We never had a test for `maketx --lightprobe`, so add it to
testsuite/maketx.

Immediately discovered that it only worked correctly for float images,
fails for half or other types. Fix.
2022-12-30 09:51:20 -08:00
Larry Gritz f70834521c Fix long-broken ref images for texture-icwrite test (#3733) 2022-12-30 09:50:43 -08:00
Larry Gritz edaa7a2ac1 pbm: Fix for incorrect inverting (#3731)
We didn't have thorough tests of pbm/pgm/ppm files, add some.
That immediately uncovered a problem with pbp files.

By spec, pbm (1 bit) files use 1 to mean black, 0 for white.
Confusing, because pgm (grey) and ppm (rgb) use 0 for black.
2022-12-30 09:50:09 -08:00
Larry Gritz 9aabd4366d CI/Testing: many improvements for testing and code coverage (#3730)
* When checking code coverage, don't abort for failed tests
* Rejigger imagebufalgo_test a bit for better IBA test coverage
* Test zover
* Have testsuite/oiiotool-fixnan test with deep images
* Add to the extisting --fixnan tests a test for 'error' mode.
* Make testsuite/oiiotool-color test all colormap names
* Test 2D filters in filter_test
* Exclude python scripts in src/doc from coverage analysis
* Remove redundant attribute-seting code from the python internals
* Remove unused python_array_code function
* Exclude some imported code from coverage testing
* Re-enable and improve coverage testing from 'make CODECOV=1'
* Exclude unused/unexposed parts of xxhash.cpp from compilation
2022-12-28 11:44:56 -08:00
Larry Gritz ec2fb0005a Remove useless bitcast specializations (#3728)
Turns out the clang/gcc intrinsics themselves compile to the same
memcpy idiom that I was using for the general case. So there is no
need for the clutter of the specialization.
2022-12-28 11:44:37 -08:00
Larry Gritz e1db762b58 platform.h: set up macros for detecting MSVS 2019 and 2022 (#3727) 2022-12-28 11:44:02 -08:00
Larry Gritz 93727ff83b typedesc.h: Extend TypeDescFromC template to the full set of pixel types (#3726) 2022-12-28 11:43:44 -08:00
Larry Gritz 46f31d5a53 tiff updates for libtiff 4.5 (#3719)
libtiff 4.5 was just released, so confirm that we build against it,
update the "latest versions" CI test to use 4.5.

More careful sorting out of libtiff version numbers for conditional
compilation.

Get rid of some ancient tiff version guards that are related to
libtiff versions that are older than we currently support.

When building against libiff 4.5, use the new open calls that allow
per-file error handlers, which is better than the old global error
handlers for thread safety of multiple threads reading from the same
ImageInput if there are errors.

Convert error messages to std::format form.
2022-12-27 21:28:34 -08:00
Larry Gritz 070790ef73 Fix typos 2022-12-26 15:27:58 -08:00
Larry Gritz 003a1f15ae Retroactively fix release notes to document TALOS-2022-1631/CVE-2022-41649 2022-12-24 15:45:17 -08:00
Larry Gritz 5c43dfebe4 IBAprep should not zero out deep images when creating dst (#3724) 2022-12-24 14:27:34 -08:00
Larry Gritz 8f6de9b512 CHANGES 2022-12-24 14:24:22 -08:00
Larry Gritz 5518be34c0 Fix static analysis warning about array extent 2022-12-24 12:13:43 -08:00
Larry Gritz 188efa55af oiiotool --pdiff: test, be sure to count it as making output (#3723)
We had no testsuite exercise of --pdiff, add it.

Along the way, I saw tha we were getting the "you didn't have any
output" warning when using pdiff, so fix that.

And some other minor changes: formatted output update, some other
tightening up of things.

A little bit of jiggling the contents of XYZtoLAB_color to work around
what I think is a compiler error with icx -- it was generating NaNs
for reasons I was unable to understand or fix, but not if I rearranged
the code slightly. All the other compilers and versions had correct
behavior.
2022-12-23 19:38:32 -08:00
Larry Gritz 726c51181a ARM: Fix signed/unsigned simd mismatch in vbool4::load (#3722)
Fixes #3721

Please read the comments in #3721. This is the "local" fix for the
build break due to the type mismatch. It is a band-aid. And it may be
the best solution for the 2.4 branch if we don't want to potentially
break ABIs by changing the definition of any public types.

Still pending is to examine the issue of whether it was a mistake to
define vbool4 storage for neon as uint32x4_t or if we should change it
to int32x4_t to better match the non-simd reference implementation.
After debating that (and identifying somebody with access to an
ARM-based machine to test the solution for us), we may return to
tackle this more fundamental change.
2022-12-22 16:30:52 -08:00
Larry Gritz 48f2b1bf92 ustring.h: cuda guards (#3718)
Hide from Cuda some things that can't possibly work in Cuda.
2022-12-20 15:09:07 -08:00
Larry Gritz 2317a6b681 Add testsuite coverage of igrep utility (#3715)
Add exception safety in igrep test.
2022-12-18 15:34:19 -08:00
Larry Gritz 109164e012 Add a test of the 'term' pseudo-output (#3714)
A few minor fixe to the term code, add a "term:filename" optional hint
to redirect output rather than go to stdout, and also change to the
new std::format notation for output.
2022-12-18 14:45:57 -08:00
Larry Gritz 9c910144aa OpenColorIO improvements, especially for 2.2 (#3707)
* OpenColorIO improvements, especially for 2.2

* When OIIO builds against OCIO >= 2.2, in the event that there is no
  config supplied (e.g., specified by env `$OCIO`), use he new
  build-in "cg" config to supply a basic set of color spaces and
  transformations. Yay for OCIO 2.2 and its built-in configs!

* New OIIO-understood aliases (regardless of whether they were in the
  config or not): "scene_linear", "srgb", "lin_srgb", and "ACEScg".
  It will do its best to know which, if any, supported color spaces
  are equivalent to these, even if arbitrarily named. For OCIO >= 2.2,
  some trickery is employed to use the new features that can convert
  to built-in config color spaces, transforming several colors in this
  manner and seeing if it gets what would be expected for various
  canonical color spaces.

* `oiiotool --help` now a much abbreviated set of color information
  (just the OCIO version, and the config, and a hint about how to get
  more info).

* A new command `oiiotool --colorconfiginfo` prints the FULL
  inventory of color management information, which now has been
  expanded to reveal the aliases of each color space, print the roles,
  and generally spruce up the output to be much more readable (though
  longer) for large configs.

* New methods for our ColorConfig class:

  - `resolve(name)` turns the name, which could be a color space, an
    alias, a role, or an OIIO-understood universal name (like "sRGB")
    into a canonical color space name.
  - `equivalent(name1,name2)` returns whether or not the two names
    refer, ultimately, to equivalent color spaces (to the best of its
    ability to figure out).

* Some minor changes (including additional `const` qualifiers)
  on the ColorConfig class.

* Make testsuite tests use the built-in OCIO config if OCIO 2.2+ is
  found.

* Build sonar against ocio2.2 so we are primarily testing the new
  code paths.

* For OCIO >= 2.2, because we can count on the built-in configs,
  conditionally compile a bunch of hard-coded color transforms.  These
  will eventually disappear completely, someday, when OCIO 2.2 is the
  minimum supported version.

I think the behavior should all be largely unchanged when running
OIIO in a facility that has a proper OCIO config pointed to by the
`$OCIO` env variable and using color space names contained therein. So
studio users will (I hope) see no changes. For users that have no
OCIO config, or that are writing software that they want to work
reasonably well for common cases no matter what config they encounter
at runtime, this should give more helpful and consistent behavior when
OCIO 2.2+ is used (which I now strongly recommend for anybody not
constrained to 2.1 for compatibility reasons.

But because of the risk and the possible behavioral changes, this is
all currently envisioned as OIIO 2.5 features, and I am not planning
to backport it to the 2.4 release branch. Additionally, a lot has
changed and I expect some additional tweaking and identification of
edge cases I may have missed.

* docs, etc
2022-12-18 11:53:40 -08:00
Larry Gritz 82a4b089c7 IOProxy read/write error handling improvements (#3712)
IOMemReader::pread catch out-of-range read positions.

Fixes #3711

Along the way, I noticed that the system pread & pwrite return a
ssize_t rather than a size_t as our IOProxy methods do, so I need to
catch the negative value returns that they use to indicate errors.
2022-12-18 11:52:58 -08:00
Larry Gritz c59529a9a1 hashes.cpp: remove or exclude from compilation unused functions (#3713)
Remove the xxhash stuff from hashes.cpp -- it long ago moved to
xxhash.cpp. Also, comment out the bjhash implementations that OIIO
itself doesn't use or expose publicly, since there's no point
compiling it (or having it count against us in coverage analysis).
2022-12-18 11:52:37 -08:00
Larry Gritz 55fa36062d Build: Suppress warnings about deprecated std::codecvt_utf8_utf16 (#3710)
Another fix for the latest Apple clang, continuing #3709 (I missed
these other spots).
2022-12-16 11:14:52 -08:00
Larry Gritz 8efd666c21 Build: Suppress warnings about deprecated std::codecvt_utf8_utf16 on Apple clang (#3709) 2022-12-15 18:09:49 -08:00
Larry Gritz 1449b46500 CI: Fix iinfo test so it works on windows (#3706) 2022-12-11 15:57:18 -08:00
Larry Gritz ed3dc51c55 Excise the last instances of unsafe sprintf (#3705) 2022-12-11 12:05:52 -08:00
Larry Gritz 494236c1fc Remove useless test in hdrinput (#3704) 2022-12-11 12:05:24 -08:00
Larry Gritz 327eb03790 BMP: set colorspace to sRGB (#3701)
Seems like a reasonable assumption for BMP files.  It's not strictly
correct -- there are header fields on V4 and V5 BMP files that
communicate color primaries and gamma, but honestly, I do not have any
idea if anybody uses them or whether they're more misleading than
helpful. For now, assuming that a BMP file is meant for output on
an sRGB display seems like it's likely to be true.
2022-12-09 22:18:59 -08:00
Michael Oliver 4001c95ac7 build_openexr.bash: bump default version to 3.1.5 (#3703)
bump to 3.1.5 for vfxreferenceplatform cy2022
2022-12-09 22:18:20 -08:00
Larry Gritz 99b0f37ac6 CI: Fix broken Mac CI with proper numpy install (#3702)
Something changing in homebrew caused CI on the macos11 test case to
fail, starting a few days ago. This fixes.
2022-12-08 11:46:27 -08:00
Larry Gritz 78ee5e05ea texture3d testing, fixes, refactoring, coverage (#3699)
* More extensive testing of texture3d: handle vs filename, subimages,
  >4 channels, closest sample interpolation.

* Fixes for tex3d > 4 chan that turned out to be broken.

* Some rearrangement for the >4 channel case

* Refactor and simplify accum3d_sample_bilinear so multiple data types
  all use the same templated code path.

* This all reduces the amount of untested code in OIIO by another 0.4%.
2022-12-07 21:29:02 -08:00
Larry Gritz dc5bffcf3f Build: fmt external version flexibility (#3598)
* Build: fmt external version flexibility

The current default behavior is to
1. Check if there's already a copy of fmt found.
2. If not (or if BUILD_FMT_FORCE is ON), download it locally.
3. Copy the relevant fmt .h files as part of the OIIO install in
   OpenImageIO_ROOT/include/OpenImageIO/detail/fmt

This patch adds a new INTERNALIZE_FMT option, which defaults to ON,
whch is the old behavior. But if set to OFF at build time, the fmt
headers will NOT be copied into OIIO's install area (instead, it will
have dummy files that in turn include the real ones).

Set INTERNALIZE_FMT to OFF if you are really sure you want users of
OIIO to use the system install of fmt and not have OIIO install a new
copy.

When an externalized fmt is used, also make sure our exported cmake
config files cause the downstream user to find fmt and pass on the
dependency properly (necessary because strutil.h actually requires
properly including fmt headers).

Eliminate extraneous include_directories of fmt

Bump the auto-download version of fmtlib to 9.1
2022-12-04 12:50:23 -08:00
Larry Gritz 3641834a11 Centralize ImageOutput validity checks (#3686)
Many ImageOutput::open implementations start out with various validity
checks -- such as whether the ImageSpec requests a resolution, number
of channels, or other features simply not allowed by that file format.
This is not only repetitive, but which checks are done by each file
type is somewhat haphazard, error-prone, hard to get full test
coverage (must we separately test each possible failure case for every
file format?), and the error messages are not always consistent across
formats. Frankly, most of the format writers assume that the caller
has a full understanding of supports() and will never send requests
for features that are unsupported.

This PR proposes adding a utility method ImageOutput::check_open(),
which performs all validity checks on the ImageSpec that can be
deduced from supports(). The various ImageOutput::open()
implementations may call this function and avoid having to replicate
(or forget) all the checks done in other output formats.  This is a
protected method that is used by ImageOutput implementations
internally, but has no use for client-side code.

I've implemented check_open, and also used it here for all the output
formats. If this seems ok to everyone, I also plan to do an analogous
helper for ImageInput common validity checks (which will be an even
bigger reduction of redundant code and greatly increase the safety
against corrupted or nonsensical input files).

Along the way I also instituted a new supports() query: "noimage".
That is to indicate a file for which it is permitted to have a pixel
data window consisting of 0 pixels (i.e. an "image" that is only a
container for metadata). Currently, FITS is the only format we support
that allows this, though it's something we occasionally talk about for
OpenEXR. Allowing an explicit way for formats to say they allow no
pixels is what allows check_open to issue error messages for all the
other formats if it is passed zero-sized width, height, depth, or
nchannels.
2022-12-04 09:59:20 -08:00
Larry Gritz 92e488a3b7 Testing; better tests of environment mapping, minor fixes (#3694)
Would you believe we never had a testsuite test for environment
mapping?  Well, it wasn't totally untested, in the sense that OSL
testsuite had one, and obviously it's used in production all the
time. But OIIO's testsuite didn't have any tests of
TextureSystem::environmemt(). We now remedy that.

* Add testsuite/texture-env, contains several environment tests,
  including handles vs filenames, subimage selection, different interp
  and mip modes, ask for >4 channels.

* New CMake build option OIIO_TEX_IMPLEMENT_VARYINGREF can be used for
  testing to disable implementation of the old 1.x style of batch
  texture calls.  We don't use them, they are deprecated. This option
  give us a way to exclude them from code analysis, because we really
  don't care.

* Fix bug with >4 channels for environment batch shading!

* Avoid unnecessary spec lookup in TileID constructor.

* Avoid building testtex test_hash during code coverage -- it is an
  extremely specialized test, not run in the testsuite, it shouldn't
  really count againt good code coverage.
2022-12-04 09:55:23 -08:00
Larry Gritz fabce2ac33 Fix broken version designation in docs (#3698) 2022-12-03 21:51:11 -08:00
Larry Gritz a707c2a534 Fix docs typo 2022-12-02 16:43:31 -08:00
Larry Gritz ecb807262e CI: test against latest webp, and deal with its master->main repo change (#3695)
Also be more robust to the libheif and libde265 repos being
occasionally down.
2022-12-01 14:39:05 -08:00
Larry Gritz 8b5ace53a9 make_texture: allow existing DateTime to remain (#3692)
When creating a texture, the old logic was to set the file metadata
"DateTime" to the current time, unless update mode was used, in which
case it was set to the file's write timestamp of the input file.

But that made it impossible to explicitly set that metadata, and also
a big PITA for testing because it meant the metadata of any written
texture would be the time of its writing, and so appear different
every time.

This change alters the logic: update mode still sets DateTime to the
last update time of the input file, as before; other cases will only
set DateTime if it isn't already set, but not alter it if the input
carries that metadata already.
2022-11-29 22:49:02 -08:00
Larry Gritz 4037671a31 Refactor common parts out of iinfo and oiiotool printinfo, testing (#3688)
* There was lots of duplicated code between iinfo and `oiiotool -info`.
  Refactor much of that into a new src/libOpenImageIO/printinfo.cpp.
  These are internal functions, no change to public API.
* Test iinfo --hash, --stats, and with nonzero origin and full size
* Test iinfo and oiiotool --dumpdata of deep image
* Test iinfo for subimages, mips, -f, -s
* Some conversion to new print instead of printf

There is probably more such refactoring to do later, I did the easy
parts for now and that's a start.
2022-11-25 18:48:05 -08:00
Gerdya 1aa2cf6edf Some fixes for compilation with MSVC for Windows ARM64 (#3690) 2022-11-25 16:31:12 -08:00
Larry Gritz 6aac5b182a span minor improvements (#3685)
* Make sure the cspan alias also allows the Extent template argument.

* Add a custom formatter for {fmt} to print spans, like we did for
  Imath types.
2022-11-24 11:38:15 -08:00
Larry Gritz 44ff29deb7 oiiotool --dumpdata : fix channel name output (#3687)
We weren't copying the full spec, so didn't get the channel names.
2022-11-20 22:50:53 -08:00
Larry Gritz f782db69e3 oiiotool --point fix problem when there's no alpha (#3684)
We were over-allocating the color vector, and that was throwing off
the operation of IBA::render_point for cases where the image had no
alpha channel.
2022-11-20 22:50:26 -08:00
Larry Gritz c0bbf873f2 Catch possible exception, identified by static analysis (#3681) 2022-11-19 08:43:50 -08:00
Larry Gritz e4b5fa4ea7 DPXColorConverter.cpp: exclude unused portions (#3682)
Many parts of this imported file are unused by OIIO. `#if 0` them away,
so they aren't part of static analysis or code coverage.
2022-11-19 08:43:35 -08:00
Larry Gritz ce03d56d8e PSD reading: don't reject padded thumbnails (#3677)
When reading PSD file, if reading the thumbnail doesn't pass basic
sanity checks, we consider that a hard error reading the file.  One
check that we do is to make sure that our computation of the byte
width of the uncompressed thumbnail (`bpp/8 * width`) matches what the
file says the `widthbytes` is.

BUT... it seems that it might round up to an even (or maybe 4-multiple?)
of columns, presumably for scanline alignment reasons. And so we were
considering whole PDF files unreadable if they fell into this case.

This PR primarily loosens the test to allow some padding up to a
multiple of 4.

Fixes #3658
2022-11-18 07:30:49 -08:00
Larry Gritz 209c1bfd46 IFF output safety (#3676)
* Maya IFF documentation says IFF file has max resolution of 8192, and
  our implementation only allows writing RGB and RGBA, so check these
  limits when an IFF file is opened for output.

* Make sure scratch space allocates enough for tile padding.

* Check for non-zero image origin coordinates (which are not allowed
  in IFF files).

* Change some 16-bit loop variables to uint32_t to avoid possible
  overflow.

Fixes TALOS-2022-1654, TALOS-2022-1655, TALOS-2022-1656
2022-11-18 07:29:51 -08:00
Larry Gritz 9ccbc43f38 Try to squash warning in gcc 12.1 + C++20 (#3679) 2022-11-17 22:41:13 -08:00
wayne-arnold-adsk ae1031044f Avoid sanitizer warning unsigned integer overflow (#3678)
/Volumes/DATA/local/S/Maya_master_CI_sanitizer/build/RelWithDebInfo/src/Components/ExternalLibraries/OpenImageIO/install/include/OpenImageIO/string_view.h:252:43: runtime error: unsigned integer overflow: 0 - 17 cannot be represented in type 'unsigned long'
    #0 0x10d0adf61 in OpenImageIOMaya_v2_4::basic_string_view<char, std::__1::char_traits<char> >::compare(OpenImageIOMaya_v2_4::basic_string_view<char, std::__1::char_traits<char> >) const string_view.h:252
2022-11-17 15:08:51 -08:00
Larry Gritz 4b22cf4452 BMP output safety (#3673)
In open(), check for non-zero image offsets, which is not supported by
BMP, and issue an error if found. If the spec passed in has nonzero
spec.y, other code in the write functions would fail because they
assumed spec.y == 0 and could therefore access memory incorrectly.

More generally, also put checks in the write functions that issue
errors and take early outs if they find that they are called on a
BMPOutput that is not currently open, for example if open() fails but
the user doesn't check the return codes and proceeds to call the write
functions anyway.

This addresses TALOS-2022-1653 / CVE-2022-43594-CVE-2022-43595
2022-11-16 12:07:21 -08:00
Larry Gritz 32946e54e5 DPX output: fix write errors (#3672)
There was a subtle error where we had a reference to an ImageSpec for
one of the subimages, confusingly called m_spec, which we altered, but
then didn't make the same change to the this->m_spec, and in a later
spot we referenced the `m_spec` meaning the one in `this`. This could
lead to a crash.

Fix, but not only that, also rename to avoid the confusion. `spec0` is the
alias we us for the spec for subimage 0, and `spec_s` is the alias we
use when referencing subimage S, and we really never use m_spec
anymore to avoid any confusion. This should make it easier to reason
about this code in the future and avoid these kinds of mistakes.

A second error resulted from the situation where a failure in open()
would return before one or both of m_buf or m_tilebuf were allocated.
If the return status of open() were ignored and the caller
subsequently attempted calls to write_scanline or write_tile, invalid
memory could be accessed. Fix this with a variety of guards not only
based on the allocation status of these buffers, but also issuing
errors (and exiting early) from write_scanline or write_tile if they
are called on an ImageInput that is not in fact open.

Addresses TALOS-2022-1651 / CVE-2022-43592 and 
TALOS-2022-1652 / CVE-2022-43593
2022-11-16 10:53:23 -08:00
Larry Gritz 1605a4a961 Fix formatting 2022-11-16 10:39:52 -08:00
Fabien Servant @ TCS f7c4023487 [raw] update exif orientation with raw flip if user flip is set (#3669) 2022-11-16 10:38:05 -08:00
Larry Gritz d5d9146f32 PSD: Fix thumbnail extraction for PSD files (#3668)
Fixes #3660

In investigating this issue, I also noticed that now that IOProxy
support can be relied on, the old code that in the psd reader that
directly fumbles with libjpeg is not needed and can be replaced by
just a couple of lines to make an ImageBuf read from an IOProxy.

And it fixes the bug, too. So I'm not even going to try to figure
out what was going wrong with the old code.
2022-11-15 18:41:14 -08:00
Larry Gritz aba8470c91 DPX input: Comment out assertions (#3674)
We shouldn't abort here, we should return and handle the error better
(which we do).
2022-11-15 08:01:24 -08:00
Larry Gritz b48f0650a4 Zfile write safety (#3670)
When writing a zfile, anything that causes open() to fail will leave
m_tilebuffer at 0 size. Subsequent calls to write_tiles, and also
to close (which cleans up unwritten parts of the buffer at the end)
did not check for this condition and would access out of bounds memory.

While I was in there, I converted the zfile.cpp error messages to the
new formatting convention.

Fixes TALOS-2022-1657
2022-11-14 19:21:40 -08:00
Larry Gritz d7ecbbb100 ImageBuf+IOProxy vs ImageCache subtle fixes (#3666)
I uncovered a very subtle problem that can happen with the interaction
between ImageBuf, using an IOProxy, and the underlying ImageCache.
Remember that when using an IOProxy, it is critical that the lifetime
of the proxy outlasts any ImageInput, ImageBuf, or ImageCache that was
told about it.

Consider the following code:

    IOProxy proxy(...);   // temporary proxy in this local scope
    ImageBuf A ("foo.exr", 0, 0, proxy);

We've set up an ImageBuf that will read from an IOProxy.  Behind the
scenes, it made an ImageCache entry that remembers the IOProxy, as it
has to, since it needs to use that proxy for subsequent reads.
Now we read the image, and we use the `force=true` parameter to
force an immediate read of the file:

    A.read (0, 0, true);

It reads from the proxy. But the IB and the underlying entry in the IC
still know about the proxy. But in the user's mind, they have fully
read the image, will never read from it again, so of course (they
think) it is safe to close or destroy the proxy, knowing that they
made it last past its use:

    proxy.close();

But -- oops! -- the cache entry still has a pointer to the proxy, and
even though it won't need to read from it again, it still will access
it, close it, etc., but the user's proxy may by that point be out of
scope.

This is *technically* not a "bug" in the sense that it is the user who
violated the contract by closing or destroying the proxy before its
last use by anything they passed it to. But in context, it's very easy
to be confused by this -- the user thinks that the only observer of
the proxy is the ImageBuf, and they're done using the ImageBuf at that
point, but because they don't explicitly mention an ImageCache, they
don't realize that the ImageBuf passed the proxy reference along to
the underlying IC that could be backing any ImageBuf.

It's the user's fault in some sense, but let's just say that we have
given them an "attractive nuisance."

That's a long bit of background explanation, but I wanted to force
myself to explain it clearly and make sure it was spelled out in the
commit comments. Now here is the fix:

* When IB::read does an immediate forced read involving an IOProxy,
  after the read is complete, tell the cache to invalidate the entry
  for the file so that it no longer retains a pointer to the proxy.

* When an IB itself is destroyed or cleared, if it used an IOProxy,
  also invalidate the IC entry for that file.

* Unrelated cleanup: avoid a redundant invalidate call in init_spec().
2022-11-14 19:20:11 -08:00
Larry Gritz 04fc83edeb OpenColorIO 2.2 support -- preliminaries (#3662)
* Make it so that when we build against OCIO 2.2, it is possible to
  specify the built-in configs. The logic had previously precluded
  this, because at one point it checks to see if the passed config or
  contents of env $OCIO was an existing file. Now you can set OCIO to
  "ocio://default", for example, and it will be used by OIIO.

* Expose getAliases (I think that has been there for a while but we
  didn't expose in in our ColorConfig wrapper).

* Expose isColorSpaceLinear (new to OCIO 2.2)

* New OIIO global getattribute query: "opencolorio_version" returns the
  human-readable version string (such as "2.2.0").

* Some miscellaneous other cleanup in color_ocio.cpp

* Change in color methodology for test suite: Previously, for every
  call to oiiotool in the testsuite, we passed a `--colorconfig`
  argument to oiiotool pointing it to the sample colorconfig that we
  ship in the testsuite. Here, I'm changing it so that the cmake setup
  for tests sets the OCIO env variable for all tests, so no explicit
  --colorconfig is necessary, and thus you won't see a path to the
  config in any of the test output files if they need to echo the
  command line arguments (and you'll see several test outputs altered
  in this way). This is a prelude to later changes that will use the
  built-in configs themselves for tests, when available.

More interesting changes coming in subsequent PRs.
2022-11-14 19:19:40 -08:00
Larry Gritz c31b10007b CI: No longer add the ppa:ubuntu-toolchain-r/test repository (#3671)
Lately, it has been experiencing intermittent availability problems
that causes our CI to fail while setting up dependencies.

What happens if we don't use the problematic ubuntu-toolchain-r at all?

Nothing, it seems. So eliminate it.

I think that once upon a time, it was necessary to add this repo to
get certain new packages? But maybe they are mainstream enough now
that it's not necessary to add this repo? In any case, it doesn't seem
to hurt anything, it's one less moving part that can't fail if it's
not there.
2022-11-14 14:09:44 -08:00
Larry Gritz 30ea4ebdfa Expose OIIO::Strutil::print in the main OIIO namespace (#3667)
We use this all the time in our internals, and I'm tired of having to
write Strutil::print. Too verbose. By putting it in the main OIIO
namespace, OIIO internals can reference as simply print(), and
external users now have a choice of saying Strutil::print() or
OIIO::print().
2022-11-14 08:00:37 -08:00
Larry Gritz 72bc675885 IOMemReader ctr should take const buffer pointer (#3665)
The ctr is inline, so I don't think it breaks backwards link
compatibility to make this change, so I do intend to backport it.
2022-11-14 08:00:07 -08:00
Larry Gritz 6da2b6ef48 Fix type mismatch warning in JPEG code (#3664)
Fixes #3663
2022-11-12 08:33:42 -08:00
Larry Gritz d9f326f18e ociodisplay gets an inverse control (#3650)
Fixes #3648
2022-11-09 22:13:31 -08:00
Larry Gritz 1278f60e7a CMake: Adjust how version overrides work (#3653)
Kai Pastor (dg0yt) made an important observation that the way I
recently made OpenImageIO_VERSION be a cache variable might lead to
unexpeted behavior by inadvertently retaining a version number upon
recompiles if the cache itself was not cleared, and this can happen
unexpectedly even when the user isn't trying to override the version.

This patch changs the behavior as follows:

You must use the special `-DOpenImageIO_VERSION_OVERRIDE=...` to
override the version.

  * if you do so, you are playing with fire and get what you deserve
    if you misuse it or change branches and don't remember to clear
    the cache.

If you do a normal build (without _trying_ to override the version),

  * you will get the real version number because it IS NOT cached
  * if you switch branches, you'll always get the right version number
  * ...but switching branches without clearing the cache can still, as
    always, have other subtle behavior differences versus doing a
    truly fresh build from scratch.

So in short, it still allows a way to override the version if you
really want to, but if you are not trying to do that, you can no
longer get yourself inadvertently into unexpected trouble.
2022-11-09 22:12:49 -08:00
Larry Gritz e03b7b38b4 Testing; Imagecache better testing coverage and some stats improvements (#3654)
* testtex: better control over temp file creation

* Additional texture tests to improve coverage of udim generation,
  and deadling with cache limits.

* Better ImageCache unit tests for perthread create/destroy and
  individual tile retrieval. Fix a bug in get_tile for nonexistant
  subimage or miplevel.

* Dead code removal: ImageCacheFile::udim_to_concrete() and
  find_file_no_add(), which were no longer called anywhere.

* IC stats: fix messed up 'slowest' list ordering when there are broken files

* IC stats: when stats level is high, enable printing of some stats that
  we previously skipped over when they were "uninteresting" (e.g., too
  little time spent on something, no problematic files, etc).

* IC testing: test a variety of get_pixels error conditions

* IC testing: more tests of IC::imagespec() and get_imagespec(), incluing
  error conditions.

* More get_texture_info query testing

* Minor bug fix for int-to-float data conversion in get_image_info

* Test IC query for resolution[3]

* Test IC::reset_stats()

* Fix ImageCache::reset_stats in cases where threads ended
2022-11-06 14:16:11 -08:00
Larry Gritz 8b8952d964 Additional Strutil tests (#3655)
Better coverage of edge cases for escape_chars/unescape_chars, stoi
hex conversion, strtod, stod, freestanding c_str(), parse_nested
failure cases, base64_encode, debug.
2022-11-06 11:45:53 -08:00
Larry Gritz 989bf367ec IOProxy support for IFF files (#3647) 2022-11-04 20:00:56 -07:00
Larry Gritz ab93bfa6c0 Filesystem::is_executable and find_program (#3638)
Also cull some cruft that no longer is used for OIIO >= 2.4
2022-11-04 20:00:41 -07:00
Larry Gritz 404015ef26 Fix ColorConfig::getColorSpaceDataType null ptr deref when no OCIO config is found (#3652) 2022-11-04 20:00:16 -07:00
Larry Gritz efd27a9dfb CMake: use of ${PROJECT_NAME} must be after call to project() (#3651) 2022-11-04 16:43:30 -07:00
Larry Gritz 78aaf34d3a oiiotool testing and minor subimage/miplevel fixes (#3649)
* Add casual tests of oiiotool with no args (print brief usage message)
  and when an unknown command.

* Also changed the meaning of -q (quiet mode) to be more quiet -- in
  particular, not to print the full help message for errors when quiet
  mode is used, only print the error.

* oiiotool test sequence errors.

* Test (and fix) --selectmip and --subimage with out of range indices
2022-11-02 21:52:29 -07:00
Larry Gritz f099e19d94 RLA IOProxy support (#3642)
Also take the opportunity to do some std::format style conversion.
2022-11-01 22:01:58 -07:00
Larry Gritz 7d53464069 CI: Test against OpenColorIO 2.2 (#3644) 2022-11-01 22:01:09 -07:00
Larry Gritz 9c706409f1 IOProxy support for SGI files and fix important bug (#3641)
Add IOProxy support.
Fixes #3623

Along the way, noticed an important bug at line 209 of this change --
the header "imagename" field should be fully zeroed out even if there
is no ImageDescription metadata!
2022-11-01 18:31:48 -07:00
Larry Gritz 88152a6a10 CI: adjust when workflows are run to cut needless CI runs (#3645)
Changes:

* Scorecards and analysis -- allow newly launched job to cancel
  running old job from the same PR.

* Scorecard only runs on main repo, no need to run on forks.

* Nightly CI only runs on main repo, no need to run on forks.
2022-11-01 08:49:11 -07:00
Larry Gritz 1beeb27dae Analysis: more test related fixes to try to increase code coverage (#3643)
* Test oiiotool control flow syntax mistakes
* Test oiiotool --set with array of strings
* oiiotool: better adjust_geometry unit testing

Helper utility additions:

* oiiotool --no-error-exit

  `--no-error-exit` causes an error to not exit immediately, but
  rather to try its best to continue execuing command line
  operations. Use with caution! This is mainly for unit tests and
  debugging.

  `--unittest` also turns this on automatically, so that tests that
  are probing failures don't cause an exit.

* unittest.h: If OIIO_UNIT_TEST_QUIET_SUCCESS is defined, don't print
  anything extra for unit test success
2022-11-01 08:48:49 -07:00
Larry Gritz 52846a5253 Squash some alignment problems caught by ubsan (#3646) 2022-11-01 07:21:26 -07:00
Larry Gritz 76610138e9 oiiotool: --printinfo improvements to fix mem vs file ambiguities (#3639)
It surprised me a little to realize that --printinfo prints the
current spec of the top image (I mean, duh), but that may not match
what you'd get with `oiiotool -info -v`, which prints the data about
each file as it's read from disk, inasmuch as the "current" spec
reflects the in-memory representation. So, for example, it might say
the image is float, because oiiotool tends to store everything
in-memory as float, rather than uint8 of the disk file.

So these changes help fix this oddity and other ambiguities I realized
follow:

* Give --printinfo an optional modifier `:native=1` that will print
  the native (from the original file) info, if that's what you need,
  rather than the up-to-the-moment in-memory data.

* Also add --printinfo optional modifiers `:verbose=` and `:stats=`.

* Expression substitution gets some new names it knows: "nativeformat"
  is the data type in the file, versus "format" which I now see would
  return the in-memory version; METANATIVE and METANDATIVEBRIEF, which
  are the native versions of META and METABRIEF.
2022-10-31 21:46:03 -07:00
Larry Gritz ab694d0322 maketexture: Ensure proper setting of some metadata (#3634)
Make extra sure to clear the oiio:ConstantColor, oiio:AverageColor,
and oio:SHA-1 metadata when writing textures, if those things are not
going to be set.
2022-10-31 21:45:34 -07:00
Larry Gritz 0674f8de7b Refactor font searching and add font getattribute queries (#3633)
* Add OIIO::getattribute() queries for "font_list", "font_file_list",
  and "font_dir_list", which are, respectively, the lists of fonts
  that were found, the list of font files (full paths), and the list
  of directories it searched.  All return a single string that is a
  semicolon-separated list of the items.

* As a consequence of the new attributes, if you are curious to see
  the full inventory of fonts it can find, you can just query the
  attribute:

      oiiotool --echo "{getattribute(font_list)}"

* Some refactoring of the font inventory process (in
  imagebufalgo_draw.cpp) was necessary to achieve this.

* We now search for ".ttc" (TrueType collection) files, which we didn't
  notice before.

* We now search explicitly in share/fonts/OpenImageIO, which we
  neglected to do before, but found those fonts because we searched
  /share/fonts recursively.  In exchange, we now do not search the
  directories recursively, because that seems unwise for performance
  reasons.

* We pass the full testsuite, but it's possible that this
  change may fail to find fonts that were previously found because of
  the recusion. If that is the case, you should fix it by explicitly
  adding the deep directories with fonts to the search path specified
  in the environment variable `$OPENIMAGEIO_FONTS`.
2022-10-31 21:45:19 -07:00
Larry Gritz 53d2e5db1d Analysis: Add tests to improve code coverage of oiiotool (#3637)
* Unit test adjust_geometry
* Tests of --set for various implicit and explicit types not
  previously covered in the testsuite
* Comment out Oiiotool:get_position, which seems to be unused
* Exercise --iconfig for explicit types
* Add test for --origin and --originoffset
* Add test for --ociodisplay
* Add test for --unmip and --selectmip
2022-10-30 12:47:08 -07:00
Larry Gritz af4b6f1da6 Strutil: trimmed_whitespace (#3636)
It's similar to trim_whitespace, but returns the trimmed result, rather
than operating in-place on a `string_view&`.

Also add unit testing of trim_whitespace and trimmed_whitespace
2022-10-29 10:24:45 -07:00
Larry Gritz c5ef0f2e50 Strutil read_text_from_command, and limit size of read_text_file (#3635)
* Add an optional size parameter to read_text_file to limit the
  maximum size that will be allocated and read (default to a limit of
  16MB).

* New read_text_from_command, similar use to read_text_file, but reads
  from the console output of a shell command.
2022-10-29 10:24:26 -07:00
Larry Gritz 78441fa29a TIFF: guard against buffer overflow for certain CMYK files (#3632) 2022-10-23 19:11:41 -07:00
Larry Gritz 92db3f5d35 PSD: protect against corrupted embedded thumbnails (#3629) 2022-10-23 13:08:23 -07:00
Larry Gritz acfb6a9e28 TIFF: guard against corrupt files with buffer overflows (#3628)
Along the way, improve the runtest.py script by giving the
info_command() fuction the same silent, concat, and failureok
parameters that the oiiotool() function has. (This lets individual
tests assemble iinfo command lines with a little more flexibility.)
2022-10-23 13:08:12 -07:00
Larry Gritz e44400feac DDS: fix crashes and add tests (#3625)
* In the case of DDS cubemap files where a cube face was not present,
  we were filling m_buf with 0 bytes before allocating it.

* Add check for invalid bits per pixel.

* Add regression test for another bug that was perviously fixed in
  2.4.3.
2022-10-23 13:07:58 -07:00
Larry Gritz 884dfd6b7c Fix EXIF bugs where corrupted exif blocks could overrun memory (#3627)
In one case, we actually had a check for this, but an assignment to an
int made the nonsensical offset appear negative, and we only tested
whether the necessary offset it was bigger than the buffer size.
Keeping it as (unsigned) size_t makes the test work as intended.

In another case, there were several places where we never checked that
we were staying within the exif block, and here we address this by
changing the utility decode_ifd so instead of passing it a pointer to
the ifd, it passes the offset (the pointer turned out to always be
inside the buffer) so it can check the extent for subsequent accesses.

Also some fixes related to squashing undefined behavior sanitizer
cases.
2022-10-22 12:32:46 -07:00
Larry Gritz a37aa72f93 RLA: fix potential buffer overrun (#3624) 2022-10-22 12:32:21 -07:00
Larry Gritz 737b317394 Custom fmt formatter for ustringhash prints the string, not the hash (#3614)
Also, change `operator<<` to output the string, not the hash itself.
These changes help push us more toward the original intent of
ustringhash being a drop-in replacement for ustring, any time it's
more desirable to be using around the hashes rather than the pointers.
2022-10-22 09:02:15 -07:00
Larry Gritz 51705b7fba Improve oiiotool test coverage (#3626)
* oiiotool tests for expressions var() and getattribute()

* Make sure we test oiiotool IMG[] expressions and several specific
  special attributes to retrieve.

* Add coverage of oiiotool --keyword and --clear-keywords
2022-10-22 09:01:30 -07:00
Larry Gritz 19121dc4f0 Targa: String overflow safety (#3622)
Added utility functions safe_string_view and safe_string to strutil.h.
2022-10-21 08:15:40 -07:00
Larry Gritz 5fa8d996bd BMP: protect against corrupt pixel coordinates (#3620)
When reading the image (which can have signals to jump around in the
array), we checked for out-of-bounds x coordinate, but not y, and some
corrupted files could overrun buffers as a result.
2022-10-21 08:15:28 -07:00
Larry Gritz f6b2a13473 CI: eliminate xxhash and farmhash code from coverage analysis (#3621)
Because we're not the originators of the code and we use only a tiny
subset of what's in those files.
2022-10-21 00:17:42 -07:00
Larry Gritz 1196815fd1 oiiotool: New metadata expression syntax (#3619)
The existing syntax `TOP.name`, if the name wasn't found, produced
an error.

This PR adds another syntax: `TOP[name]` which is identical if the
named metadata is found. But if not found, this syntax just evaluates
to the empty string, with no error.
2022-10-21 00:10:25 -07:00
Aras Pranckevičius 3a9d3faab5 Docs: write Windows build instructions (#3602)
I recently wrote down how to build OIIO from source for myself (https://gist.github.com/aras-p/6497703c9b52f67761e6191343e43f7b), and maybe a slightly cleaned up version would be good to put into actual docs.
2022-10-20 08:20:33 -07:00
Larry Gritz 4be5ca093d Fix missing getattribute of limits:channels and limits:imagesize_MB (#3617)
I think it was just inadvertently left out when these were first added.
2022-10-20 08:20:00 -07:00
Larry Gritz c51349a0d6 Testing: optimize oiiotool-control test (#3618)
This test was taking almost 30 seconds to run, without a lot of images
being read or written. Turns out it was just a large number of separte
oiiotool invocations, and the overhead of all those shells and
programs launched adds up. Most of them were just firing up oiiotool
for the sake of doing an `--echo` to print things. A little bit of
restructuring to make fewer oiiotool invocations (each one doing a
bunch of echo commands, each testing a different thing) cuts the time
for the whole test by 50%.

I also made the runtest.py script allow certain test debugging by
letting a test set the `wrapper_cmd`, and if so, will prepend every
oiio utility launch with it. For example, a test could say
`wrapper_cmd='time'` to time every command.
2022-10-20 08:19:31 -07:00
Larry Gritz 90dfdb1720 oiiotool: Add unit tests, minor internals utility refactoring (#3616)
Add a hidden --unittest command to oiiotool, only functional for Debug
builds, which enables additional testing of internal utility funcions
and other things that are difficult to fully exercise in the testsuite
from normal oiiotool commands (could be done, but would take tons of
additional tests to get into particular deep edge cases).

Prototype by adding unit tests for scan_box. More will be added later
now that the mechanism exists.

Simplify string_to_dataformat

Make sure to use --list-formats and --runstats during testing.
2022-10-19 09:29:14 -07:00
Larry Gritz 71b4cffcaa Testing: eliminate redundant code in Python IBA bindings (#3615)
Also add a test for sub(imagebuf,tuple) that we didn't have before.
2022-10-19 07:43:23 -07:00
Larry Gritz 7f28d3f3f1 Ensure that ustring hashes are 64 bits (#3606)
ustring::hash() and the representation of ustringhash were size_t,
which might be 32 bits on some platforms. But we really would prefer
ustrings hash to 64 bits, to greatly reduce the chance of hash
collisions.

* Add strhash64() which is like strhash() but guaranteed to be a 64
  bit value (returning uint64_t instead of size_t -- though note that
  these are the same on 64 bit CPUs).

* ustring::hash() and ustringhash::rep_t are now uint64_t.

* Note that std::hash(ustring) and std::hash(ustringhash) are still
  size_t, per the C++ definition of std::hash. So ustring::hash() may
  have more bits than std::hash(ustring) on 32 bit platforms.

This will NOT be backported to the release branch, since it changes
ABI on 32 bit platforms.
2022-10-18 16:04:52 -07:00
Larry Gritz 2e663455ee Add a test that forces stats to be computed (#3612)
Increases code coverage for dynamic analysis and coverage metrics.
2022-10-18 00:26:16 -07:00
Larry Gritz a7d0346cb0 Testing: testsuite/iinfo -- make it compute stats, use MIPmaps (#3613)
Better coverage of the functionality of iinfo
2022-10-18 00:25:58 -07:00
Larry Gritz c5cd76a395 Testing: update cineon test image 2022-10-17 11:04:12 -07:00
Larry Gritz 575fcb3c13 Fix exr core test options (#3610) 2022-10-17 00:20:53 -07:00
Larry Gritz c653ab0052 CI: Sonar analysis should exclude stb_sprintf.h (#3609)
It's not really "our code", and we use very little of that file, so
it's not helpful to include it in coverage or other analysis.
2022-10-16 22:32:14 -07:00
Larry Gritz 5532d49387 Testing: make a test specifically for iinfo (#3605)
Believe it or not, iinfo was never run in the testsuite before this!
2022-10-16 21:37:31 -07:00
Larry Gritz 1875a9b884 Test fixes (#3608)
* We mis-named color_test, and that caused it to never get run!

* imagespeed_test is meant for benchmarking only, run by hand.
  We don't make a testsuite test, so don't even build the source
  (which would never be counted for code coverage because it doesn't
  run) during CI.
2022-10-16 20:58:20 -07:00
Larry Gritz a432a35e34 Improve cineon build and test (#3607)
* Add a test for cineon -- we never directly tested it before

* Don't compile code used only for writing. We don't supporting
  writing cineon, so there is no point compiling the cineon module
  used only for writing.

* And of course, once cineon was in the testsuite, we immediately
  found a problem via the sanitizers! So fix buffer overflows when
  reading FilmEdgeCode in Cineon.  (And clean up the equally sloppy,
  though not technically buggy, code in DPX as well.)
2022-10-16 19:26:50 -07:00
Larry Gritz 7a510254c6 Testing: test both openexr old and core versions (#3604)
On any one platform, our testsuite was only testing the old C++ and
the new C core exr implementations.

Rig it to run the openexr-oriented tests twice -- once in each state
(when using OpenEXR new enough to support the core library).

Doing this cleanly required adding SUFFIX and ENVIRONMENT optional
parameters to the oiio_add_tests utility macro. Once that was added,
the texture batch testing could be implemented that way as well,
removing a bunch of hackier special purpose code.
2022-10-16 19:21:36 -07:00
Larry Gritz e471c7ea49 Static analysis related fixes (#3603)
* Protect against 0-sized allocation
* Exception safety in IffOutput destructor
* Using sonar.coverage.exclusions as a better way to exclude files
  from coverage analysis
* Null pointer safety
2022-10-15 18:13:28 -07:00
Aras Pranckevičius 5320f79968 SIMD: extend NEON implementation coverage, and include neon in oiio_simd_caps (#3599)
* Use hardware float<->half conversion (similar to F16C on Intel)
* Use hardware sqrt
* Use horizontal adds in more places ("reduce_add")
* Equivalents of _mm_movemask_ps for NEON in vbool4
* Other smaller bits & bobs

Testing on Apple M1 Max, Release build, notable simd_test Mvals/sec
changes:

vfloat4
* load from half[]: 2457 -> 5890
* store to half[]: 1041 -> 6074
* simd sqrt: 2151 -> 6075

vfloat8
* load from half[]: 2433 -> 10367
* store to half[]: 1235 -> 11192
* reduce_add: 7377 -> 11971

vfloat16
* load from half[]: 2672 -> 14505
* store to half[]: 1322 -> 12558
* reduce_add: 7123 -> 11858
* operator<:  3345 -> 7500 (similar with other compare ops)

vint4
* blend: 4403 -> 5007
* blend0: 5187 -> 6076
* rotl: 1775 -> 2932

vint8
* load from int[]: 9415 -> 12152

vint16
* operator<<: 4656 -> 5865 (similar for >>, srl)
* rotl : 4042 -> 5137

vbool4
* reduce_and: 875 -> 1361
* reduce_or: 985 -> 1373
2022-10-12 17:35:27 -07:00
Larry Gritz bbd48ca172 ustring hashing improvements (#3577)
I realized that the recently added ustringhash class is confusingly
similar to the (obscure, barely used, mostly forgotten) ustringHash
functor. But also ustringHash doesn't need to exist, because it's
equivalent to `std::hash<ustring>`, if we define it. So now we do define
it, and also `std::hash<ustringhash>`, and deprecate ustringHash, to
be removed entirely for 3.0.

Also, add a ustring ctr from ustringhash (explicit only for now),
and `operator<` for ustringhash.

And add from_hash(size_t) method to ustringhash, analogous to
ustring::from_hash().

Modernize a few places we still used `(void)` to just `()`.

Give ustring and ustringhash a `using rep_t =`
rep_t is the type of the underlying representation (const char* for
ustring, size_t for ustringhash).

Modernize some typedef into using.

Make `==` and `!=(ustringhash, const char*)` be constexpr for C++ >= 17
2022-10-12 11:31:02 -07:00
Aras Pranckevičius c721423cdd Windows: stop including <windows.h> from public OIIO headers (#3597)
Including windows.h leads to a lot of possibly common names being
"taken", mostly by preprocessor defines. Some of these are possible
to turn off (like "max" and "min" by defining "NOMINMAX" before
including <windows.h>). But many others are not possible to turn off,
e.g. "near" and "far" just get defined to nothing, preventing from using
variables named like that.

Additionally, includes have a cost, and while <windows.h>, being a C
header does not have expensive language constructs that would slow down
compilation a lot, it's still something close to 100k lines of
preprocessed code to wade through.

Now, only the OIIO implementation .cpp files that actually need
<windows.h> include it (all of them under "libutil").

There were two exceptions:
1) thread.h pause() implementation uses YieldProcessor() macro when on
  a Windows system. Replaced it with manually "re-implemented"
  things that YieldProcessor expands to. Right now made the
  implementation for all 4 platforms that Windows normally supports
  (x64, x86, arm, arm64); the latter two OIIO does not support though
  when on Windows so it's untested.
2) timer.h Timer::now() inline function used QueryPerformanceCounter
  and LARGE_INTEGER. These are quite hard to somehow "forward-declare"
  or similar, without resulting in duplicate type definitions. So on
  Windows I moved the now() function to be non-inline.
2022-10-12 11:28:51 -07:00
Aras Pranckevičius babbd98081 Windows: fewer windows.h includes from platform.h (#3596)
In particular, defining NOGDI before including <windows.h> achieves
several things amongh others:
- No longer causes ERROR symbol to be defined to 0. ERROR being defined
  prevents using e.g. google/glog library, since it wants ERROR to mean
  something else.
- No longer defines some possibly widely used names e.g. GetObject.
2022-10-11 07:59:19 -07:00
Aras Pranckevičius afaaf6d10d BMP: fix reading 16bpp images (#2808) (#3592)
16 bit per pixel (e.g. 555, 565, 444) formats probably have never
worked. One part of the code was assuming 5 bits in the mask, another
was shifting by 4 bits, and the 16-bit pixel fetch code was reading just
one byte.
2022-10-07 20:55:16 -07:00
jreichel-nvidiaandJoachim Reichel 3e3fba67c0 Fix PSD import on ARM. (#3589)
The code assumes "char" is "signed char" (as on x86), but on ARM "char" is
"unsigned char".

Co-authored-by: Joachim Reichel <joachim.reichel@posteo.de>
2022-10-07 12:26:48 -07:00
Aras Pranckevičius f60205ab50 oiiotool: work around static destruction order issue (#3295) (#3591)
In some cases (at least on Windows, with static linking) the oiiotool
main returns zero, but the full process returns 3 error code due to
abort() being called. And that is called because a global shared
image cache is already destroyed, but the image references from another
global (Oiiotool itself) try to use it, get a call into a "pure virtual
function" stub that is put by MSVC C runtime into a destroyed object
vtable, and that ends up in an abort().

Work around that by making sure various member variables holding
ImageRecRef are cleared before main() finishes and global destructors
are called.
2022-10-07 12:15:23 -07:00
Aras Pranckevičius 4a4f50eda8 HDR: speed up reading by around 4x (#3590)
Most of the cost in HDR file reading was converting from RGBE to floats,
inside ldexpf(), which at least on Windows/VS2022 spends most of the
time inside _ctrlfp(). But we only have 256 possible exponents in total,
so just use a precomputed table.

On my PC (Windows 10, VS2022, Ryzen 5950X) this change gets file read
time for an 8x resolution .HDR image from 1.10s down to 0.27s
2022-10-07 09:08:00 -07:00
Aras Pranckevičius a285a5d1ed HDR: fix read performance regression (#3585) (#3588)
HDR code overhaul to support IOProxy (#3218) changed all reads into
a `pread()` with explicit file position tracking. Turns out, that is
quite a larger overhead compared to simple sequential reads; even more
so on Windows.

On my PC (Windows 10, VS2022, Ryzen 5950X) this change gets file read
time for an 8x resolution .HDR image (with RLE compression) from
8.28s back to 1.10s just like it was in OIIO 2.3.

On Windows the extra cost when using pread() is a bit more extra mutex
locks, but the real cost is in enventual ReadFile; looks like any seek
operations make it take some sort of "way slower" path with various
callbacks and whatnot inside the kernel.

---

Note repoduced from discussion #3588 from LG: 

Switching from IOProxy::pread to using IOProxy::seek + IOProxy::read makes the IOProxy stateful and not thread-safe without an external lock (which this HdrInput has, so it's not going to break anything), precluding any future removal of the locks from read_native_scanline to make the whole ImageInput able to read concurrently. That's probably not important for this file format, but for others (especially crucial those usable as texture), it would be desirable to rely on those stateless pread calls and remove the lock from the ImageInput.

I think this patch is fine. We don't expect a lot of concurrent reads from hdr like we do for tiff and openexr that we use extensively for highly threaded on-demand reading of texture. It fixes the recent performance regression, and it doesn't really cost us concurrency because we already had the lock in HdrInput. But in general, we want to prefer eschewing read/seek and using pread instead, so we can expect maximum concurrency from multiple threads using an ImageInput (as we do in ImageCache/TextureSystem).

So I believe that a revised and more complete diagnosis is that the problem isn't the pread vs read per se, but that for RLE-compressed images we were calling pread separately for every 4 bytes! The calls to read are faster simply because they are buffered (in FILE) and require fewer OS system calls. But the real sin is that we call it way too many times.

I think that the rle case could go back to pread if we want, but do just one pread per scanline (rather than one per pixel value run), asking for the maximum amount that will be needed to read the scanline for the worst case rle representation (it's ok if it's the end of the file, pread will just read up to the end and return the true number of bytes read). In other words, we'd be doing the buffering ourselves.

But anyway, the real misdesign of this HDR reader is ancient, and consists of doing many many tiny reads. Even the buffered fread would be sped up a lot by not doing it separately for every 2-4 bytes of the file. I don't know if it's worth fixing for this format. Depends on whether anybody really needs to maximize its performance or expects multiple threads reading the same hdr file to be fully concurrent.
2022-10-07 09:07:28 -07:00
Larry Gritz 3c32812296 CI/build: build_libtiff.bash should be sure to build shared library (#3586)
Something changed in libtiff master and it doesn't build shared libs
by default, breaking our "bleeding edge" CI test. So when we build it,
be sure to ask for it. It can be overridden in build_libtiff by
invoking it with env variable `LIBTIFF_BUILD_SHARED_LIBS=OFF`.
2022-10-06 13:39:26 -07:00
Larry Gritz b89fa9d0d6 DDS: honor ImageInput thread policy (#3584) 2022-10-05 23:57:14 -07:00
Aras Pranckevičius 60800746bf DDS: optimize loading of compressed images (3-5x) (#3583)
Comparing the time it takes to load DXT/BCn compressed DDS images via
OIIO, I noticed that it's several times slower than in another codebase
(Blender). So I started profiling, and fixing some low hanging fruit.

- After decoding a BCn block (always 4x4 pixels), it was written into
  destination image using quite many branches in the innermost loop.
  Now it still takes care of not writing outside of a destination image
  that might not be multiple-of-4 in size, just with way fewer branches.
- BCn decompression is multi-threaded via parallel_for_chunked, using
  at least 8 block rows per job (i.e. 32 pixel rows). This is
  similar to internal multi-threading done by EXR or TIF readers.
- Avoid one case of std::vector resize (which clears memory) followed
  by immediate overwriting of that buffer with bytes read from the file.
  Switched to using unique_ptr for that array, similar to how other
  input plugins do it.

Performance data: I'm timing how long it takes to do "iinfo --hash" on
24 DDS files, each 4096x4096 in size. Quite a lot of time there is taken
by just the SHA hash calculation which is not related to loading, so
also have timing info for just DDSInput::read_native_scanline where
all the actual DDS loading/decoding happens.

Timings on PC (Windows 10, VS2022 Release build), AMD Ryzen 5950X.
- BC1: total 3.68s -> 2.76s, read_native_scanline 1.54s -> 0.59s
- BC3: total 3.74s -> 2.84s, read_native_scanline 1.83s -> 0.66s
- BC4: total 1.26s -> 0.82s, read_native_scanline 0.74s -> 0.24s
- BC5: total 2.29s -> 1.57s, read_native_scanline 1.31s -> 0.46s
- BC6: total 7.50s -> 4.30s, read_native_scanline 4.67s -> 1.60s
- BC7: total 6.18s -> 3.09s, read_native_scanline 4.34s -> 0.84s

Possible future optimization: implement DDSInput::read_native_scanlines,
that could avoid one extra temporary memory buffer copy. This extra
buffer clear & eventual copy from it into final user destination pixels
is non-trivial cost from profiling. But it's also quite involved
to handle all the possible edge cases (e.g. user requests scanlines
not on 4-pixel row boundaries); the code would have to do similar
juggling as EXR reader does to handle "not on chunk boundaries" reads.
It could potentially also interplay with DDS cubemap/volume texture
reading ("tiled") code paths, for which there is no test coverage at all
right now. Maybe for some other day.
2022-10-05 21:00:49 -07:00
Larry Gritz fe48013d04 oiiotool protect against OpenEXR thread deadlock on Windows (#3582)
Suggested by SideFX: explicitly shut down the OpenEXR thread pool
before exiting oiiotool, because sometimes on Windows it seems to hang
otherwise. A better solution is probably possible on the OpenEXR side,
but I don't know what it would be. (And in any case, we'd still need
to do this be be well behaved when using OpenEXR versions earlier than
where a fix might land.)

Solution tracked down by Edward Lam.
2022-10-05 16:05:48 -07:00
Aras Pranckevičius 4ee35351f1 DDS: alpha/luminance format fixes, add & enable more tests (#3581)
* DDS: fixes for A8, L8, A8L8 formats

While developing #3573 at one time I had them working properly, but then
while fixing the address sanitizer failure for 3-channel formats I
botched them again. Note to self: never again do a "yeah I'll add tests
later", since if I had all of them running all the time this would
not have happened. 🤦

* DDS: extend test coverage for more formats & channel size cases

With more test images recently added (https://github.com/OpenImageIO/oiio/pull/3459),
start using them for DDS tests. This covers now:
- Alpha, Luminance and Alpha+Luminance formats,
- RGB formats with rarer channel sizes (rgb10 a2, r3g3b2),
- Several "broken" DDS file cases
- Removed usage of sample-DXT1 since it is well covered by others.
2022-10-05 16:03:39 -07:00
Larry Gritz caf15b6b73 Remove incorrect OIIO_API from inline method declaration (#3578)
This was causing build issues on MinGW.
2022-10-04 17:02:09 -07:00
Larry Gritz e64b2cb425 Revise RELEASING to explain updating oiio-images branch (#3580) 2022-10-04 17:00:58 -07:00
Larry Gritz 33c0181843 Build/security: Try FORTIFY_SOURCE (#3575)
Add a new build-time cmake cache variable: FORTIFY_SOURCE

Default to empty, but can be set to 1, 2, or 3, corresponding to
setting the _FORTIFY_SOURCE macro available in recent versions of
clang and gcc. (I'm not sure exactly which minimum compiler version is
needed for each fortification level, except that for level 3, gcc must
be 12+.)

Fortification involves replacing several "unsafe" memory-related
functions such as memcpy, memset, strcpy, etc, with special versions
that do bounds checking, aided by some compiler smarts for
understanding the likely bounds of different buffers. If I understand
correctly, at level 2 it can figure out bounds of constant-sized
arrays, and at level 3 it can figure out certain dynamic cases as
well.

There are two use cases for this:

1. For our own CI, this is yet another bit of static and dynamic
anslysis to enable (currently, just in the gcc12 test) to possibly
catch bugs.

2. Users who are building OIIO to deploy it in security-sensitive
environment may wish to build with some fortification level enabled to
help prevent certain memory errors or security issues, understanding
that it may slightly impact performance.
2022-10-03 21:08:26 -07:00
Aras Pranckevičius 5dd9feeade DDS: various improvements (#3573)
- If a DDS pixel format header contains "this is a normal map" flag
  set, then handle that properly (#3525):
  - For a DXT5, this means it's a "DXT5nm" format. Normal X & Y
    components are in green and alpha channel respectively. Compute Z
    component from those, and the result is a 3-channel tangent space
    normal map.
  - For ATI2/BC5 format that also has a "normal map" flag set, compute
    the Z component automatically too, and result is a 3-channel image.
    However a bunch of ATI2/BC5 normal maps out there in the wild do
    not have that bit set, so also have a global "dds:bc5normal"
    attribute to optionally turn this on.
- Fix support of R10G10B10A2 format - was producing garbage data due to
  code assumption that truncation down to 8 bits never needs to happen.
- Fix bit expansion ("too dark") of very low-bit formats, e.g. R3G3B2.
  Code was simply shifting the bits, instead of properly repeating
  the high bits into new low bit positions (i.e. a 3-bit "111" needs
  to become an 8-bit "11111111" and not a "11100000").
- Support "RXGB" (DXT5, with red & alpha swapped) as well as "BC4U"
  and "BC5U" formats (the latter two are just BC4 and BC5, produced by
  some older tools).
- Support alpha-only (e.g. A8) formats.

All this mostly prompted by doing DDS improvements in Blender, and
wanting to get Cycles renderer (which uses OIIO) to the same feature
parity. See https://developer.blender.org/T101405 and
https://developer.blender.org/D16087.
2022-10-02 09:21:46 -07:00
Larry Gritz 490d51bc96 CI: improvements and minor refactoring (#3570)
* Refactor the clang-format job to be part of the aswf batch of jobs
  rather than separate (reduces redundant logic in the workflow file).
* Give proper names to distinguish the two Mac jobs' artifacts for
  broken builds and their caches.
* Revise scorecard workflow triggers: no need to run weekly, and run
  on push only to the main repo, no reason to run on forks.
2022-09-29 17:56:57 -07:00
Aras Pranckevičius 3ffb4ae7e8 Build: enable parallel compilation when using visual studio (#3571)
Cmake-generated visual studio project files were using just one CPU core for all the compilation, which is not terribly fast. Add the `/MP` option so that it compiles separate .cpp files in parallel. On my (16 core, 32 thread) machine this makes a Release build of OpenImageIO.lib go from 136 sec down to 30 sec.
2022-09-28 12:25:47 -07:00
Larry Gritz 53aa8a1674 Update one more ref image after recent raw change (#3572)
Also remove three raw test reference output files that we apparently
no longer use (corresponding to platform + libraw combinations that
aren't in our current set of CI configurations).
2022-09-28 12:25:34 -07:00
Larry Gritz 09d3464c9d Remove long deprecated/nonfunctional C API headers (#3567)
This was an experiment that was added to master at one point but
removed before we branched for a release. But we forgot to remove a
few headers. Removing them now is not a compatibility break, since we
never shipped a supported release that contained the library that
implemented the functions declared in these headers.
2022-09-27 14:38:37 -07:00
Larry Gritz fcc45717fa Use undefined behavior sanitizer (ubsan) as part of CI (#3565)
In addition to address and leak sanitizers, also turn on the undefined
behavior sanitizer in our CI run. We can do it in the same job as
asan/lsan.

Some things that come along for the ride, including fixes for things
that ubsan uncovered:

* src/build-scripts/ubsan-suppressions.txt can hold suppression list
  (though we don't have any now, it just sets up the space for it for
  future needs).

* Split the "targa" test so that the parts that directly need the OIIO
  python module (which are all related to thumbnails) are now in
  "targa-thumbnails" test. That has to be disabled for the sanitizers,
  since we can't arrange for python to b linked to the sanitizer
  libraries.

* Found vint4::store has a potentially unaligned integer store.

* Found Strutil::concat is not necessarily safe if either of the
  strings are empty.
2022-09-27 12:11:47 -07:00
Larry GritzandVincent Demoulinv 893eead5a8 Update ref output after recent raw change and clang-format (#3569)
This is an addendum to #3561 to fix reference output

Co-authored-by: Vincent Demoulinv <vincent.demoulin@technicolor.com>
2022-09-27 12:09:03 -07:00
demoulinvanddemoulinv 9c6c9192f1 Add color metadata from libraw. (#3561)
2 vectors, pre_mul and cam_mul.
2 matrices, cam_xyz[4][3] and rgb_cam[3][4], delivered as 1D tab.

Co-authored-by: demoulinv <vincent.demoulin@technicolor.com>
2022-09-27 11:14:25 -07:00
Larry Gritz 03ee387c05 Reinstate missing (obsolete) parallel_for_chunked_2D variant (#3566)
This was part of a set of obsolete calls where we recently removed the
implementations, but for link compatibility, made matching shim calls
and wrap the modern versions. But I missed one case.
2022-09-26 22:09:35 -07:00
Larry Gritz d5973882d8 Add RELEASING.md to document our release procedures (#3564)
Adapted from the similar document I wrote for OSL.

This serves both as a checklist for me to make sure I don't miss any
steps during a release, but also so that other people could take over
release procedures if necessary or desired.

I also rearranged the order of some lines in CMakeLists.txt for
clarity (but did not change the logic).
2022-09-26 11:07:18 -07:00
Larry Gritz ebea33b0c2 CHANGES and docs fixes 2022-09-24 11:36:45 -07:00
Larry Gritz b085899021 Update ref output after recent python chage 2022-09-24 11:36:45 -07:00
Larry Gritz 9c45ba9cf1 Changes to take care of new clang 15 warnings (#3563) 2022-09-22 22:56:41 -07:00
Larry Gritz 9b41418941 IC and TS getattributetype() (#3559)
ImageSpec and ParamValueList have had (since 2.1) a getattributetype()
method, which simply returns the TypeDesc of the named attribute, or
TypeUnknown if no such attribute exits. This goes along well with the
related getattribute() and attribute() family of methods.

The getattribute() method was not present in ImageCache and
TextureSystem, despite their having very similar
getattribute()/attribute() interfaces.

A recent issue made me realize that in the Python bindings, the IC and
TS bindings for `getattribute(name)` did not work properly, always
returning None, and *required* you to use the full
`getattribute(name,type)` variety where you have to supply -- and
already know -- the type. This isn't especially Pythonic, where you
should just be able to ask by name and get a polymorphic result. And
when I went to look at how to repair this, it was going to be very
awkward without getattributetype(), but trivial with it.

So this patch sets up getattributetype() for both IC and TS, and
exposes them to both C++ and Python APIs, and also fully fixes the
getattribute() so that it works properly with the name only.

Unfortunately, because getattributename is a new virtual method, it
changes the vtable, breaking the ABI, and thus cannot be backported to
any supported release that makes ABI compatibility promises.
2022-09-22 22:56:11 -07:00
Povilas Kanapickas b22260bd19 Fix build on iOS by not using std::system() (#3562)
iOS and similar Apple platforms only support executing single process
per app. Calling std::system() there fails at compile time.
2022-09-22 22:52:48 -07:00
Povilas Kanapickas d779a32814 Build: Fix cross-compiling on Android failing due to -latomic check (#3560)
Currently when cross-compiling for Android build fails due to usage of
TRY_RUN(). In the particular case it tries to figure out whether atomics
can be used without the libatomic library.

Fortunately we don't need this check because on Android NDK atomics are
built-in and libatomic.so is not present. Only static dummy libatomic.a
exists for compatibility with -latomic flag.
2022-09-19 18:02:42 -07:00
Larry Gritz 80374c0128 Python internals: support int8[] metadata and ICCProfile, refactor (#3556)
This patch allows ParamValue, ParamValueList, and ImageSpec to support
attribute/getattribute of metadata consisting of uint8[] arrays, which
is how we store certain binary blobs or raw byte arrays.  We translate
this to Python as a numpy array of type uint8 (dtype='B').

This fixes a limitation where it was not possible to directly retrieve
or set the "ICCProfile" metadata (which is stored as a uint8 array)
from the Python APIs, as you could easily do from the C++ APIs.

In the process, I found similar bits of code in several different
places, in various states of incompleteness. I refactored to make a
single make_pyobject() utility and then used that call in place of
several other redundant pieces of functionality.
2022-09-19 10:56:07 -07:00
Povilas Kanapickas 96f420b26d cmake: Find TBB dependency in Config.cmake.in when building static (#3557)
TBB::tbb is added as a library dependency via TARGET_NAME_IF_EXISTS.
Therefore if an executable links OpenImageIO static library without the
executable itself depending on TBB, then TBB will not be linked in and
result in link time errors.
2022-09-17 22:41:56 -07:00
Larry Gritz a2e7ec714f Python: add ability to getattribute of int64 and uint64 data (#3555)
Just a couple missing pieces were preventing getattribute() from
retrieving attributes that were stored as int64 or uint64. That
doesn't come up very often, but one place is retrieving certain
statistics that use 64 bit counters. (This comes up in ImageCache,
among other places.)

While we're at it, there was no existing test dedicated to the python
binding of ImageCache. So to add these getattribute calls, I made one.

There is an important caveat about ImageCache.getattribute(): In this
process, I discovered that the flavor of IC.getattribute(name) where
you only pass the name is BROKEN, and will always return None. You
MUST use the form where you pass the type, like

    x = ic.getattribute("foo", "int")

This is unfortunate and not very Pythonic, but it is the workaround
for now. I will addess getting the name-only form working in a
separate PR.

Closes #3537
2022-09-16 15:23:36 -07:00
Larry Gritz acbd1f3c9f Extract metadata from embedded ICC profiles. (#3554)
For a while, we have found embedded ICC profiles in TIFF, JPEG,
JPEG-2000, PNG, and PSD (PhotoShop) files and store them in the
metadata as a byte array with the name "ICCProfile".

With this patch, we further add the facility of parsing the binary ICC
profile data to extract a number of other fields that we add to the
ImageSpec metadata so that "oiiotool -info -v" or "iinfo 'v"
will print this info.

Important caveat: You can read this for informational purposes, but
changing it (e.g. with spec.attribute()) does not change the contents
of the ICCProfile byte array, which is still the canonical ground
truth of the profile. You have to replace the "ICCProfile" byte array
to actually change the profile.
2022-09-15 16:48:14 -07:00
Larry Gritz 9aeece7a53 Strutil utf conversion improvements (#3553)
* Add `Strutil::utf16_to_utf8(const std::u16string& utf16str)`.
  This is subtly different from our existing utf16_to_utf8() that
  takes a std::wstring, because wchar_t is not the same on all
  platforms.  If it really and truly is utf16-in-char16_t, you need
  this and can't use the utf-in-wchar_t which may be 32 bit chars.

* Add `Strutil::utf8_to_utf16wstring()` (identical to the old
  utr8_to_utf16) to make it more self-documenting as returning a
  utf16-encoded wstring and NOT a u16string. Note that wchar_t is not
  necessarily char16_t on all platforms (it is on Windows, but it's 32
  bits on Linux).

* Deprecate the ambiguously named `utf8_to_utf16()` for OIIO >= 2.5 and
  remove it for OIIO >= 3.0.
2022-09-13 21:46:45 -07:00
Povilas Kanapickas 71a329672e cmake: Add library dependencies in Config.cmake.in when building static (#3552)
This fixes builds in projects that compile OpenImageIO as static
libraries and don't themselves depend on the image libraries used by
OpenImageIO such as PNG, JPEG or TIFF.

When OpenImageIO is built as a static library its targets have e.g.
PNG::PNG among INTERFACE_LINK_LIBRARIES. If the including project does
not itself depend on PNG, the following error would be observed:

Target "<...>" links to target "PNG::PNG" but the target was not found.
Perhaps a find_package() call is missing for an IMPORTED target, or an
ALIAS target is missing?
2022-09-13 21:36:04 -07:00
Larry Gritz a22ed46940 Slight change to avoid gcc12 warning (#3551) 2022-09-13 13:38:36 -07:00
Larry Gritz 0d9f098dbb Build: Make the version number be a cmake cache variable (#3549)
Rather than specify the version in the usual project() statement,

    project (OpenImageIO VERSION 2.5.0.0 ...)

this patch decouples it

    set (OpenImageIO_VERSION "2.5.0.0" CACHE STRING "Version")
    project (OpenImageIO VERSION ${OpenImageIO_VERSION} ...)

thus allowing the possibility of overriding the version number at
build confuguration time (`cmake -DOpenImageIO_VERSION=3.1.4.1`).

This should be used with extreme caution. Probably never used by most
people. I don't need to describe all the ways that things can go
sideways if you make your build of x.y.z.w actually be arbitrarily
different from the x.y.z.w that everyone else uses and that is
documented.

That said, there are two scenarios I have in mind for which this
ability is very useful:

1. Sometimes, we add or deprecate API features "in advance" by having
   an `#if` enable or disable code based on the version, essentially
   putting in place changes that can't be enabled yet because they
   would break compatibility rules, but we want to integrate the code
   now and have it become active upon reaching a particular future
   version in which that incompatibility will be allowed. The version
   number override makes it easy to test this by quickly doing a build
   "as if" we had already bumped the version number to see what will
   happen when we actually do.

2. Every once in a while we need to do an internal build that, to
   conform to version compatibility rules, needs to appear to still be
   part of a past version family. This lets individual sites play some
   games with version number overrides rather than have to create new
   branches and tags for certain one-off internal releases.
2022-09-13 09:43:09 -07:00
Larry Gritz 0ff1bf34f9 oiiotool --iccread and --iccwrite (#3550)
--iccread reads a named file and directly adds its contents as the
"ICCProfile" metadata of the top image (as a byte array).

--iccwrite takes the "ICCProfile" metadata of the top image and
writes it to a named file.
2022-09-13 09:42:38 -07:00
Larry Gritz a028a11a0b CI: Re-enable sanitizer tests (#3545)
Oops, at some point, something about the way we set up the CI test
that runs the sanitizers, and ever since then (embarrassingly, perhaps
as much as a couple years ago), the "sanitizer" test has not in fact
been running the sanitizers. Here we fix that up, get sanitizers
running again.
2022-09-07 21:31:43 -07:00
Larry Gritz 99adfb43a8 PNG fixes (#3544)
* Minor png refactoring to fix some memory leaks for broken png files.

* Remove unused string variable from read_info() and simplify the
  surrounding "if"

* Split png test into png and png-damaged, because I just can't seem
  to squash some very minor memory leaks for broken png files, I think
  it's not worth worrying about and I'll just exclude the broken case
  from testing for the address sanitizer.
2022-09-07 13:08:45 -07:00
Johannes Unterguggenberger cd4ca3bae4 Fixes a warning from an unsuitable format specifier (#3540)
Changed the assert  to use format specifier %d and casting the size to an int.
2022-09-07 13:00:40 -07:00
Larry Gritz 73f958341e PNG: fix memory leak when error takes early exit (#3543)
Found by leak sanitizer.
2022-09-06 22:16:01 -07:00
Larry Gritz 23235c9851 Fix heap overflow in DDS input (#3542)
Reading uncompressed scanlines would copy 4 bytes from each pixel into
an int and then decode the bits, incrementing where it was reading
from by Bpp bytes each time.  But when Bpp == 3, the last pixel of
every row would therefore read an extra byte past the end of the heap
storage. Allocation padding would in practice keep it from crashing,
and that meaningless extra byte was not used in the decode because it
knew it only needed the first 3 of the integer. But found by address
sanitizer!
2022-09-06 22:15:13 -07:00
Larry Gritz c85b5d7768 Targa internals: fix incorrect unique_ptr declaration (#3541) 2022-09-05 21:29:39 -07:00
Larry Gritz c23cda28a5 This is now the branch that leads to 2.5 (#3539) 2022-09-01 12:19:20 -07:00
Larry Gritz 5ef709c1b4 CHANGES, docs 2022-08-31 14:31:05 -07:00
Larry Gritz 27745db1da ImageCache: improve file handle limits under heavy thread contention. (#3515)
When enforcing the max open files limit, there's a heuristic where we
only "try" to get the lock, and if we can't, rather than block, we
just defer the cleanup step until the next time around. So what if we
go slightly over the limit temporarily?

Interesting edge case: what if max_open_files is relatively low, but
the number of threads is very high and you have a high contention rate?

Then you can end up *significantly* over the limit, because almost all
the threads say "somebody else has the lock, I'll leave it to them to
clean up" and blithely open new handles.

So this patch modifies the logic so we do the defer trick only if
we're only a little over the limit. If we've exceeded the limit by
16 handles, grab the lock unconditionally and do the cleanup.
2022-08-31 11:08:02 -07:00
Luc 736864dca0 Added checks in PNG_pvt::write_info (#3535) 2022-08-29 23:18:50 -07:00
Larry Gritz afa6c84f68 CI: test latest fmt version (#3536) 2022-08-29 23:17:00 -07:00
Larry Gritz a14523e9b7 Add --version to all the things (#3534)
* ArgParse::add_version(str) tells ArgParse the version string, and
  automatically adds an option --version that prints the version string
  and exits.

* Add this to oiiotool, iinfo, igrep, iv, maketx.

* OIIO::getattribute("version") retrieves the version string.
2022-08-26 10:10:16 -07:00
Larry Gritz 7e77d7b05d Improve JPEG output of 2-channel images (#3531)
JFIF/JPEG files only support 1 and 3 channels. For > 3 channels, we
had just been discarding the extra. For 2 channels, we had been
discarding the second, but maybe that's not always right. Try to
distinguish between files whose names appear to be YA -- in which case
output the Y as grayscale (JFIF has no way to represent alpha anyway),
and other cases which we now promote to RGB and just make B be black.
2022-08-23 00:02:51 -07:00
Larry Gritz 939c25988a DDS improvements (#3530)
* For 2-channel DDS files, label them as Y,A if the flags indicate
  luminance and/or alpha, otherwise label them as R,G.

* Do not set "oiio:BitsPerSample" for cases where the dds.fmt.bpp field
  is not assumed to be valid. MS docs say it's valid only if the flags
  field indicates RGB, LUMINANCE, or YUV types.
2022-08-23 00:02:38 -07:00
Larry Gritz f582b8b5ab Make Filesystem::extension work identically for C++14 and 17 (#3529)
The implementation of boost::filesystem::path::extension() and the
equivalent for std::filesystem disagreed about the result of
extension(".foo"). C++17 correctly considers ".foo" to have no
extension.
2022-08-23 00:02:17 -07:00
Larry Gritz 217c169543 Miscellaneous Sonar-inspired warning fixes (#3532) 2022-08-21 15:09:57 -07:00
Larry Gritz cace0c4b82 Fix warning wth C++20 + g++12 (#3533) 2022-08-21 13:21:57 -07:00
Larry Gritz c2ed61bb85 Remove 'socket' file type (#3527)
This was envisioned to be useful in the very earliest days of OIIO,
but we never really finished it or used it in any helpful way.
In addition to being essentially dead and untested code, it ties us
to boost.asio, which we use nowhere else.

So just get rid of it this vestigial piece.
2022-08-19 19:43:45 -07:00
Larry Gritz b6b3166d4e CI: For Mac, test python 3.9 for MacOS11, and 3.10 for MacOS12. (#3528) 2022-08-19 10:25:34 -07:00
Larry Gritz be30dfa241 Suppress incorrect warnings for gcc12 (#3524) 2022-08-15 22:56:05 -07:00
Larry Gritz e69b267e0f Build: Don't force MACOSX_RPATH on (#3523) 2022-08-14 17:59:05 -07:00
Larry Gritz 59408d630c Fix mail list refereces 2022-08-14 17:58:06 -07:00
Larry Gritz 9501cd71ab Fix analysis trigger typo 2022-08-13 22:58:52 -07:00
Larry Gritz 50286f3e03 Several minor fixes for Sonar warnings (#3522)
Knocking these out a few at a time
2022-08-13 21:56:57 -07:00
Larry Gritz ce3d45a812 Fix destructors that could throw an exception -- big no-no (#3521) 2022-08-12 18:21:11 -07:00
Michael Cho 01cf730d2f cmake: fix ffmpeg 5.1 detection (#3516) 2022-08-11 23:29:06 -07:00
Larry Gritz 79a4803db6 Some minor refatoring to address Sonar warnings (#3518) 2022-08-11 23:22:25 -07:00
toxie f21a666b2d Fix vector-subscript-out-of-range on MSVC Debug builds (#3517)
Also fix potential problems with >31bit pixelsizes
2022-08-11 19:21:15 -07:00
Larry Gritz 1af0a782d3 Fix crash with oiiotool -i:ch= (#3513)
* Any use of `-i:ch=...` would result in a crash because of
  dereferencing an empty shared pointer.

* In the case of `-i:ch=` specifying missing channels, improve the
  warning message to make it clear which channels were actually present.
2022-08-06 23:26:20 -07:00
Larry Gritz 9f4f6ae6cd CI fixes (#3514)
* Remove GHA CI for Mac OS 10.5, it faces imminent deprecation by GitHub.
* Update some dependency version numbers in INSTALL.md.
2022-08-06 23:25:52 -07:00
Larry Gritz f8616d9824 Miscellaneous static analysis warning issues (#3512)
Also re-split the scorecard workflow from the analysis workflow.
2022-08-05 09:10:01 -07:00
Larry Gritz 61a58a17f8 Get rid of redundant 'virtual' when we use 'override' (#3511) 2022-08-04 23:50:28 -07:00
Larry Gritz 540e7e2554 Fix broken workflow file -- copy/paste error (#3510) 2022-08-03 23:34:42 -07:00
Larry Gritz c530e48cb6 Relative image compare (#3508)
Extend ImageBufAlgo::compare() to take relative metrics, which if
nonzero check the symmetric mean relative error, in addition to the
current absolute error. To be formal, this means that a value
comparison will fail if

    abs(A-B) > failthresh && abs(A-B)/((abs(A)+abs(B))/2) > failrelative

Setting the failthresh to 0 is equivalent to only checking relative
error, and setting failrelative to 0 is equivalent to the (previous
behavior) of checking only absolute error.

The idiff utility is extended to take new `-failrelative` and
`-warnrelative` command line arguments.

The hope is that there are various kinds of image comparisons within
tolerances -- like we frequenty use for unit tests, shader
verification, etc. -- where this metric is more helpful than absolute
error.
2022-08-03 23:27:01 -07:00
lmarz c3740921b6 cmake: Escape argument in regex (#3507)
See https://gitlab.kitware.com/cmake/cmake/-/issues/18737 for why this is an issue
2022-08-03 08:35:01 -07:00
Larry Gritz 307fe02a49 Set up SonarQube for static analysis (#3505)
Set up SonarQube to run weekly (seems unnecessary to do on every PR,
it's a LONG run). Also required some build system fixes to enable code
coverage analysis.

This is handled by the "analysis.yml" workflow (into which I also
merged the scorecard analysis we were doing). This workflow runs once
weekly or on only those pushes/PRs with specially named branches.
There's no reason to run this expensive analysis on every last PR or
push.

A number of fixes come along related to things found by Sonar as I was
setting this up:

* Fix buffer warnings
* Address sonar warning: was reading wrong size into buffer
* warning reduction in dpxoutput, simplify string ops
* Clean up dubious uses of sprintf
* Add assertions
* Save a needless string construction in ParamValue::get_string_indexed
* Fix string safety warnings
* iptc: simplify encoding string data and improving safety
2022-08-01 07:23:51 -07:00
Larry Gritz 7ab1ee5108 Refactor TGAInput::open to simplify. (#3504)
It was getting too big. Split off the tga-2.0 header reading parts
into a separate method.
2022-07-29 09:45:00 -07:00
Larry Gritz c72154fa26 Use imath .xyz rather than [] to fix static analysis warnings (#3503)
Stranely, this made slightly numerically different texture test
results on icc.  Switching its math mode to precise brings it back in
line with the other compilers. The differences aren't visible, so this
isn't an issue in practice, but for tests it made it hard to compare
to reference images.
2022-07-29 07:48:09 -07:00
Larry Gritz bc9c931092 Strutil::safe_strlen (#3501) 2022-07-24 22:13:15 -07:00
Larry Gritz 7f90f51792 Fix bug in print_info_subimage -- botched condition (#3499) 2022-07-24 22:12:58 -07:00
Larry Gritz 04e32c9894 Fix aspect ratio logic in jpeg (#3500)
Typo, was checking XRes twice instead of XRes and YRes.
2022-07-24 22:12:32 -07:00
Larry Gritz afc2bd1649 parallel.h refactoring and add support for TBB (#3473)
Hide nearly all of the implementation of the parallel_for family of
methods rather than expose them as inline. This gives us more freedom
to change the implementation in the future without breaking ABI.

Deprecate the parallel methods that take task functions whose first
parameter is the thread ID. The only reason they existed is because
our cobbled together thread_pool used that in its inner workings.  But
there are good reasons why we should not expose that:

  * We never used it anyway.

  * It was not very useful, since sometimes it was a real thread ID, but
    other times it was -1 in cases where the calling thread executed the
    task directly.

  * It is inconsistent with other thread pool implementations that we may
    wish to try in the future.

So better just to not expose those thread IDs at all. Mark those
versions of the parallel loops as deprecated and schedule them for
removal in OIIO 3.0.

If TBB is detected at build time, support will be built in that allows
either the old OIIO built-in pool, or TBB, depending on the setting of
a new global OIIO attribute, "use_tbb" (default 0), if set to nonzero
will use the TBB thread pool.

In my experiments, the TBB thread pool seems slightly better -- I
think because there is less overhead, and maybe the clever
work-stealing it does elps to load balance. It's not used by default,
set the attribute if you want to use it (assuming the build
included. After we've had a chance to test more thoroughly, we may
change to use TBB by default. I'm interested to hear people's thoughts
on the matter.

One case where you almost certainly will want to use the TBB thread
pool is if you're using libOpenImageIO from within an application that
uses TBB for its own threding -- that way you're using one pool for
everything, rather than have two separate thread pools that don't know
about each other (and probably twice as many threads as you have
cores)..
2022-07-24 14:37:34 -07:00
Larry Gritz db1cdd6935 Fix incorrect assignment of oiio_missingcolor (#3497)
Incorrect use of reserve(), then writing past the end of the vector.
It should have been resize(). But it can be cleaned up even further by
using assign().
2022-07-24 09:23:42 -07:00
Larry Gritz f8a237cb80 Bug fix: posible null pointer dereference in inventory_udim (#3498)
If udimfile is null, it would get dereferenced anyway. Was missing
a `return` in that case.

While I was there, I realized that ImageCacheImpl::inventory_udim and
resolve_udim had no reason to be virtual, so I removed that
qualifier. (It was probably a cut/paste error, as the
identically-named methods in TextureSystem are virtual, on
purpose. But they don't need to be for this class.)
2022-07-24 08:28:18 -07:00
Larry Gritz 04137bbeb9 Upgrade to the latest PugiXML (#3494) 2022-07-23 15:34:31 -07:00
Povilas Kanapickas d6594f132f JPEG: Fix a race condition in read_native_scanline() (#3495)
All read_native_* methods of ImageInput are required to be thread-safe
with any other read_native_* call or with the varieties of read_tiles()
that take an explicit subimage and miplevel parameter.

JpgInput::read_native_scanline() does a seek_subimage() call internally,
so it's obviously not thread safe without additional locking.
2022-07-23 11:08:12 -07:00
Povilas Kanapickas 2bcbb06944 filesystem.h: Improve documentation of pread() and pwrite() (#3496)
The current description of IOProxy::pread() and IOProxy::pwrite() is a
little ambiguous. This commit expands the description to explicitly tell
what the functions are and are not required to do.
2022-07-23 10:22:16 -07:00
Povilas Kanapickas fb07a242b2 Make access to imageio_mutex not recursive (#3489)
This will allow switching imageio_mutex to std::shared_mutex to avoid
exclusively locking the internal format database for read operations.
2022-07-22 22:50:55 -07:00
Larry Gritz 43d8d543b6 Fix typos in comments and docs (#3492) 2022-07-22 22:02:24 -07:00
Larry Gritz 1d3bb460e2 Bump version 2022-07-21 22:50:44 -07:00
Larry Gritz 32557090ea Protections against 0-length string attributes (#3493)
Files that have string metadata with length 0 can cause trouble
if we aren't careful. But in a number of protections.
2022-07-21 22:47:06 -07:00
Larry Gritz a9fbf36560 Fix mistake in unordered_map_concurrent (#3485)
Should not have passed an argument. Went undetected for a long time
because I guess we didn't previously call the erase() method. (Until
I did when working on something unrelated.)
2022-07-20 11:14:20 -07:00
Povilas Kanapickas ebee2b7888 Fix -Wsuggest-override warnings (#3488)
Consistently applying override specifiers helps to ensure that functions
are actually overridden when they meant to be such.
2022-07-20 11:13:51 -07:00
Larry Gritz 1bc666a708 Bump version for developer preview 2.4.2.1 2022-07-19 22:32:34 -07:00
Larry Gritz 56e0bd05d8 TIFF: Protect against empty attribs when setting TIFF fields (#3491) 2022-07-19 22:00:06 -07:00
Larry Gritz 590ce5f8f0 Empty string / null pointer safety in metadata printing (#3490) 2022-07-19 15:49:52 -07:00
Povilas Kanapickas 31daceea03 Address -Winconsistent-missing-destructor-override warning (#3481)
Virtual destructors don't significantly differ from regular virtual
functions, so it is customary to add override specifier when virtual
destructor is overridden.
2022-07-19 15:48:08 -07:00
Povilas Kanapickas 2e30e71ef1 cmake: Fix value of OpenImageIO_INCLUDE_DIR in cmake config (#3487)
Current code assumes that CMAKE_INSTALL_INCLUDEDIR and
CMAKE_INSTALL_LIBDIR has exactly one filesystem component. This is not
the case on e.g. Debian, where standard paths are as follows:

CMAKE_INSTALL_INCLUDEDIR=include
CMAKE_INSTALL_LIBDIR=lib/x86_64-linux-gnu

Fortunately the Config.cmake file is installed into a path that is
itself relative to CMAKE_INSTALL_LIBDIR, so we can get
CMAKE_INSTALL_LIBDIR from CMAKE_CURRENT_LIST_DIR and then get
CMAKE_INSTALL_INCLUDEDIR by applying relative path from
CMAKE_INSTALL_LIBDIR to CMAKE_INSTALL_INCLUDEDIR on top of that.

Fixes: c8dfbd7066
2022-07-19 14:25:51 -07:00
Larry Gritz 786a55479e Move guts of OIIO::debug to Strutil so it can be used from util library (#3486) 2022-07-19 11:56:25 -07:00
Povilas Kanapickas e7ad7cef20 Bump maxthreads to 512 (#3484)
The current limit has been already hit when AMD released
second-generation Epyc processors (codename Rome) back in 2019. Top
models have 64 cores per CPU, or 128 threads. This means 2 socket
configuration has 256 threads.

Fourth generation Epyc processors (codename Genoa) are rumored to have
96 cores per CPU, or 192 threads. This means 2 socket configuration has
384 threads. While the CPUs have not been announced yet, it makes sense
to prepare for them in advance.
2022-07-19 09:34:15 -07:00
Larry Gritz 431204b78a CI: Try newest ubuntu 22.04 and MacOS 12 images, test gcc12 (#3480)
Bump the bleeding edge test to use gcc12, C++20, and python 3.10.

Address the couple of new warnings that popped up.

Add a test on MacOS 12.
2022-07-18 08:47:39 -07:00
Larry Gritz 777e7730df Get rid of Boost::system (#3479)
I think whatever we needed it for originally is long since gone.
2022-07-18 08:46:08 -07:00
Larry Gritz 24f804dfd2 Test against pybind11 v2.10 (#3478) 2022-07-17 20:50:14 -07:00
Larry Gritz 07c538071e Build: Use std::filesystem when we can (#3477)
C++17 (and/or adequately new versions of the compilers) support
std::filesystem, and in those cases we no longer need boost.filesystem.
2022-07-17 18:38:33 -07:00
Larry Gritz 1521da6213 Replace unsafe strcpy/strcat in SHA1.cpp (#3476)
Revealed by clang-tidy. Use length-safe versions.

Also get rid of some dead code by disabling some memory-clearing
code that we don't need (we're not using SHA-1 for cryptographic
or security reasons, just for comparing images).
2022-07-16 20:45:57 -07:00
Larry Gritz 97254f625d Filesystem: provide alternate implementations of last_write_time() (#3472)
This is a discrete step in an attempt to wean us off of boost::filesystem
2022-07-15 00:05:32 -07:00
Michael Oliver 836bd0d113 build_opencolorio.bash: update default ocio build to 2.1.2 (#3475) 2022-07-14 23:57:43 -07:00
Larry Gritz 348c4fee6e Remove a stray reference to half.h in a public header (#3474)
There's no reason to expose this here.
2022-07-14 18:13:06 -07:00
Larry Gritz 879dc2fbdb Bump version to 2.4.2.0 for developer preview 2022-07-11 20:56:59 -07:00
Larry Gritz 7b57336a28 CHANGES update 2022-07-11 16:57:34 -07:00
Larry Gritz a12a0cebc7 Strutil::safe_strcat (#3471) 2022-07-11 10:42:37 -07:00
Anders Langlands 3ee1a4d410 Allow loading of dlls from PATH on Windows Python 3.8+ (#3470)
Python 3.8 stopped loading DLLs from PATH on Windows, meaning anything that relied
on that environment for shared library resolution breaks. This PR works around that
behviour by manually adding PATH back to DLL resolution using os.add_dll_directory()
in a new __init__.py which just re-exports everything in the current .pyd.

The new behaviour is enabled by default, but is easily disabled at runtime if the
environment variable OIIO_LOAD_DLLS_FROM_PATH is equal to "1".
2022-07-10 21:58:01 -07:00
Larry Gritz e9103925bb TIFF: Fix some longstanding IPTC buffer safety issues (#3465)
Found this coincidentally during some address sanitizer runs.

Some tiff files out in the wild that have RichTIFFIPTC tags
inexplicably mark them as if the data was LONG instead of BYTE or
NOTYPE. I guess early in our history, we came across one of those and
thought it was correct, because we were always treating it as if it
came in the form of longs. But that's not always true, and in
particular, the size in the tag I think is always expressed in
bytes. So this could make for buffer overruns (generally harmless, but
caught by the sanitizer!).

So this patch cleans this all up.

And also we update a few sample images with bad RichTIFFIPTC tags to
strip out the in the incorrect form of the tag.
2022-07-07 12:55:40 -07:00
William Krick 925a6b7c8a Correctly accumulate 'ofs' when the cubemap has mipmap levels. (#3467) 2022-07-07 12:54:57 -07:00
Larry Gritz ea127e8973 PSD: beef up error message to help track down PSD failures (#3469)
Try to have an error message for every possible failure.
2022-07-06 18:09:24 -07:00
Larry Gritz 7a662829b9 Docs: Clarify how ImageOutput::copy_image propagates read errors (#3468) 2022-07-06 14:59:05 -07:00
Larry Gritz 5c3355bed0 Extend stochastic texturing to anisotropic (#3457)
Recently, we added the ability to do stochastic sampling in texture
lookups, by choosing the MIP level stochastically rather than reading
two MIP levels and mixing them.

This PR adds the ability to also stochastically sample the anisotropic
filter footprint -- instead of multiple anisotropic samples, choose
just one sample well distributed over the footprint axis. On real
scenes, this seems to speed up overall rendering (not just texture) by
up to 2-3%, for scenes where average anisotropy is around 3-4.

It's much less dramatic a speedup than the stochastic MIP selection,
which sped up texturing by around 40% and in practice sped up overall
rendering by around 15% for us. Why doesn't cutting the number of
texture samples by another factor of 3 only speed up by 3% instead of
another 20%? Basically, it's because the stochastic MIP mapping *by
definition* means that each texture call touches half the number of
tiles as before. In contrast, those multiple probes along the
anisotropic axis are almost always within the same tile, and
frequently touch a very nearby pixel within the tile, so not only are
we not needing to look up a new tile from the tile cache, but also the
very memory we need to read is highly likely to be in L1$. But still,
we'll take 2-3% rendering gain any time we can get it, that's
equivalent to a lot of money if you have a really large compute farm.

Some other changes that come along for the ride:

Add a --bluenoise option to testtex (makes for prettier 1spp results),
and add tests for the aniso sampling.

Some internals changes to precompute min w,h of mip levels so there is
less per-texture-call rifling through the ImageSpec of each MIP level.
Sadly, this did not produce any consistently detectable speedup in
overall rendering.

And I changed the interface for stochastic texturing a bit. The old
way involved asking for new MIP modes, StochasticAniso or
StochasticTrilinear, in addition to being sure to set TextureOpt::rnd
to the stratified random number you are using for sampling. Now we are
deprecating StochasticAniso and StochasticTrilinear. Just use the same
old mip levels you always did. So the new interface can be summarized
as follows:

* On each texture call, setting opt.rnd >= 0.0f is itself a request for
  stochastic texturing on that call (opt.rnd will default to -1.0, and
  any negative value does the old fashioned non-stochastic filtering).

* A ShaderSystem-wide option "stochastic" (int) indicates which things
  should be sampled stochastically, for those lookups that have rnd >= 0.
  It's a bit field: 0 means no stochastic sampling (even if rnd >= 0),
  1 means to do stochastic MIP level selection 2 means to do stochastic
  anisotropic sampling (so 3 means to do both, and higher bits are reserved
  for future extensions). The default is 0, so renderers need to enable
  it to get any stochastic texturing.

Finally, let me give a reminder that you ONLY want to do stochastic
texturing for shading that involves multiple stochastic samples per
pixel, like orinary surface shades. For displacement (shade once per
mesh vertex) or "imager" (shade once per pixel), you just have a
single shade that you want perfectly filtered, so you probably don't
want to set opt.rnd >= 0 in those cases.
2022-07-05 19:00:28 -07:00
Larry Gritz f0c3cccd44 CI: Test against fmt 9.0.0 (#3466) 2022-07-05 15:37:42 -07:00
Aras Pranckevičius 62400c3de8 DDS: speed up reading of uncompressed images (#3463)
Previous code was doing ioread one pixel at a time. Change it to
read one scanline at a time, similar to e.g. how BMP reader does it.

On a 8192x8192 rgba8 image (256MB), on Apple M1 Max "iinfo --hash"
time goes from 2.19s down to 0.65s, and is now similar to the time
it takes on an uncompressed TIF or BMP image.
2022-07-04 10:01:49 -07:00
Aras Pranckevičius 8a13790cd5 PR template: fix links to work in actual PR page (#3464)
When viewing this .md file in Github UI, everything seems to work. But when creating an actual PR, the links to CONTRIBUTING and CLAs point to nothing that would exist. Looks like they try to be relative links from the "create a new PR" page. Workaround seems to be to use absolute links instead.
2022-07-04 09:26:46 -07:00
Larry Gritz 43247981c5 CHANGES 2022-07-02 22:33:03 -07:00
Aras Pranckevičius 5e67c09ece DDS: replace libsquish with bcdec, add BC4-BC7 (#3462)
Implements support for BC4, BC5, BC6H (unsigned and signed) and BC7
GPU texture compressed formats in DDS reader (#2338).

- BC4: loaded into 1 channel uint8,
- BC5: loaded into 2 channel uint8,
- BC6H: loaded into 3 channel half,
- BC7: loaded into 4 channel uint8.

This is implemented by replacing whole of libsquish (~4700 lines of
code) with bcdec.h (https://github.com/iOrange/bcdec, ~1300 lines of
code). bcdec.h has an advantage of being faster, smaller and supports
all BCn formats for decoding.

bcdec.h license is MIT or Unlicense (aka public domain), updated all
the relevant third party / license files that I could find.
2022-07-02 09:29:55 -07:00
Aras Pranckevičius 50f0e273a9 dds: Add more DDS test images (#3459) 2022-07-01 22:17:14 -07:00
Larry Gritz 249ccaf21b CI: Security fixes (#3454)
* Add a SECURITY.md detailing our security policy and the private
  email address to contact to report vulnerabilities.

* Create scorecards.yml, to run OSSF scorecard to check supply chain
  security issues. It has some false positives, but it's only advisory.

* Make sure actions we use don't get write perms on our repo.

* Use exact SHA's for actions versions to guard against hijacked
  actions repos that might try to substutite something else at the
  version tag we use.

* Tried to use harden-runner action to ensure no actions on the runner
  overwrite source code or have unauthorized outgoing net connections
  during the GHA run, but currently leaving it disabled because of too
  many false positives -- it flags every dependency download as a case
  of altering source code. Which it technically is, but it doesn't
  matter for any jobs that aren't producing any artifacts that will be
  consumed or relied on by users.

Learned about this from a security talk.
2022-06-30 17:24:04 -07:00
Larry Gritz 7492ef0d0b idiff: add --allowfailures and convert output (#3455)
* --allowfailures is a big hammer to allow a certain number of pixel
  mismatches by any amount.
* Convert diff to modern std::format based output.
2022-06-27 11:27:34 -07:00
Aras Pranckevičius 26cc78c464 Build: allow "arm64" arch in make (#3456)
On Apple Silicon, `uname -m` returns `arm64`. The make platform detection script was allowing `aarch64`, so similar to that one, also allow `arm64`.
2022-06-27 08:35:05 -07:00
Larry Gritz 9aeb9d512b Timer: use clock_gettime rather than gettimeofday (#3443)
On Linux, we'd been using gettimeofday, which gives results with usec
resolution. Switch to clock_gettime, which has nsec results.

In practice, the round trip time of a pair of "get time" system calls
is about 30-50ns in either case. But the new call at least nominally
returns ns resolution values. Another way of saying that is: the
answers we get should be more accurate with this call, but the call
itself is the same expense as before, so we should still be just as
cautious about not inserting timers around events that are so brief
that the timers themselves are going to be a significant addition to
the cost.

This only effects Linux (and maybe BSD?). On MacOS, we use
mach_absolute_time(), and on Windows we use QueryPeformanceCounter(),
so neither of those platforms is affected by this patch.
2022-06-25 08:24:34 -07:00
Larry Gritz 5cee511134 Fix crash when ioproxy is passed to a plugin that doesn't support it (#3453)
The plugin was freed before the error message printed that depends on
it.
2022-06-25 07:20:07 -07:00
Larry Gritz 1e74b7ecf5 ustring: add OIIO_USTRING_HAS_USTRINGHASH symbol (#3449)
This makes it easier for downstream users to test if ustringhash is
available in a particular version of OIIO.
2022-06-18 08:32:06 -07:00
Larry Gritz 2213f62991 Change DoNotOptimize declaration to not conflict (#3444)
More care with "forceinline" so it doesn't interfere with the
"optnone" on some platforms.
2022-06-17 15:09:15 -07:00
Larry Gritz bc617dd0d1 TextureSystem: Change internal hq_filter to std::unique_ptr (#3448)
It's a very minor internal idiom modernization.
2022-06-17 11:26:27 -07:00
Larry Gritz f1a8ea067c TextureSystem: fix typo in attribute name (#3447)
Oops, calling it "m_max_tile_channels" (the name of the member
variable) instead of "max_tile_channels" (the name of the attribute)
actually prevented properly setting or retrieving the attribute by
name.
2022-06-17 11:25:43 -07:00
Larry Gritz 1b9638864e ustringhash (#3436)
ustring is a unique string (that lives in an internal hash table) whose
representation is the pointer to the characters that live in the table.

ustring hash is its alter ego -- it also refers to a ustring in the
internal hash table, but the representation is just the hash itself.

It presents an interface that is a subset of that of ustring, and in
many ways they can be used interchangeably.  For ustringhash,
accessing the characters requires using the hash to find the string in
the table -- which is not hard, but more expensive than accessing the
charcters with a ustring, where the representation is the pointer
directly to the characters.

For some uses where you don't need access to the characters in any
performance-critical paths, this may be a more convenient
representation.  In particular, it's well suited to a GPU that doesn't
have access to the character memory. Another interesting difference is
that from run to run, a ustring may have a different literal value,
since there's no reason to expect that the pointer to a string like
"foo" will refer to the same memory location every time the program
executes, but in contrast, the hash is guaranteed to be identical
from run to run.

In the process of adding unit tests for ustringhash, I ended up
overhauling all of ustring_test.cpp, as I saw that the ustring tests
were extremely cursory. Did a tiny bit of (non-breaking) touch-ups
on a few ustring methods as well.
2022-06-17 11:25:12 -07:00
Larry Gritz 46d97b2cc4 PNG: beef up error detection and propagation (#3442)
Especially for corrupt/broken files.
2022-06-13 10:05:11 -07:00
Larry Gritz 9beaa93d3a JPEG2000: better detect failure to open the file (#3440)
We were missing cases where the underlying OpenJPEG library itself
had errors reading corrupted files, or errors didn't propagate around
correctly.
2022-06-12 17:57:46 -07:00
Larry Gritz 999a7a4b21 BMP: protect against corroptions with palette indices out of bound (#3435)
If the BMP image we're reading declares a certain sized palette, but
then has pixels that contain values outside the range of that palette
size, we would read past the end of arrays.
2022-06-10 19:28:26 -07:00
Larry Gritz b9905464fb BMP: detect corrupted images (#3434)
Check for nonsensical image dimensions or total size before doing
buffer allocation.
2022-06-10 09:52:14 -07:00
Larry Gritz 040d71bfaa Targa: fix reading of tiny image (#3433)
With a 1x1, 2bit image of a Targa 1.0 file, the entire image was only
22 bytes, so the seek to 26 bytes before the end to look for the
Targa 2.0 data... obviously failed.

Don't look for the Targa 2.0 block if the file itself is not long
enough to hold both the header (18 bytes) and the block (26 bytes).
2022-06-10 08:51:26 -07:00
Larry Gritz 069f079eb5 Rename src/dds.imageio/squish/simd.h -> squish-simd.h (#3424)
This tiny change is a quality-of-life fix for me, addressing the fact
that there are two different simd.h files in our code base. I never
would have done that on purpose, but one of them is part of the
imported "squish" source code that we use for dds encoding.

For years I've been frustrated that reflexively typing `CMD-P simd.h`
in the editor has a 50/50 chance of pulling in this file, when in fact
there is literally a 100% chance of my wanting
src/include/OpenImageIO/simd.h.

So finally put my editing brain out of its misery by renaming the file
that I never want to edit.
2022-06-06 23:30:46 -07:00
Larry Gritz 78a504c6a5 ci: Bump OpenColorIO for 'latest' tests (#3425) 2022-06-05 17:14:01 -07:00
Larry Gritz 6d3e16fae3 Minor Python fix -- allow setitem to process a py::bytes as a string. (#3423) 2022-06-02 19:25:20 -07:00
Larry Gritz 597b8e6775 Straighten up OpenColorIO_FOUND vs OPENCOLORIO_FOUND (#3422)
We were using it inconsistently.
2022-06-02 15:17:23 -07:00
Larry Gritz dff26bd738 CI: Test the latest libtiff (#3420) 2022-05-31 22:39:45 -07:00
Larry Gritz a7aa251db4 testtex --minthreads and --lowtrials (#3418)
When doing thread "wedge" tests, most of the time spent is for the
1-thread case. Who cares about 1 thread anyway? So we make two
improvements with new command line options:

* --minthreads sets the minimum number of threads that will be
  used. For example, `--minthreads 2` will skip the single-thread case
  and start the wedge with the 2 thread case.

* --lowtrials is an optional maximum number of trials just for the 1
  or 2-thread case (overriding --trials just for those thread counts,
  if it is a lower value).

By default, the old behavior is still the default. But these allow a
bit of customization in the tradeoff of how much time to invest in the
very low thread counts in a wedge of thread timings.
2022-05-31 09:53:43 -07:00
Larry Gritz 12346eaf09 TIFF: fix read problem with tiff files with non-zero y offset (#3419)
You'd think there would be no way that basic failure like this could
occur after 14 years, right?

But the TIFF reader code was a little mixed up about the fact that the
internal m_next_scanline field is relative to the starting scanline of
the image, not an absolute value. But in the case of the code that has
to deal with handling the stray scanlines at the end of a strip-read
file neglected to set it properly and the end of the stripped part.

Obviously, for TIFF files with a first scanline of 0 (the vast, vast
majority), failing to adjust by this offset doesn't matter. And also
as long as the reading continued to be strictly sequential, it also
was asymptomatic. But in the presence of certain multithreaded random
access patterns, it makes a difference. Oops.
2022-05-31 09:52:16 -07:00
Larry Gritz 593bd319a7 UDIM speedups by eliminating mutex (#3417)
The udim_lookup_mutex_pool is not necessary. Just using an atomic
pointer for udiminfo.icfile is enough.

I'm seeing about a 5-8% overall speed improvement in testtex-based
intense udim benchmarks under heavy threading, a ~2% overall
improvement in a real rendered scene that uses a bunch of udim
textures (I think there are bigger bottlenecks elsewhere that I'll
move on to next, but every little bit helps).

Some testtex enhancements coming along for the ride:

* UDIM-oriented tests (automatically decuded if the test textures
  contain `<UDIM>` in their name.

* --maketests will construct random test textures and use them (handy
  if you need lots of textures for a big test, but don't want to store
  them). The tests are based on a file pattern using std::format-like
  replacement with an index. Also, if the pattern contains `<UDIM>` in
  the name, it's understood to be a udim pattern and many individual
  udim piece files will be created.

An example of these two items in action is:

```
testtex --maketests 200 "tmp/foo{:04}_<UDIM>.exr" --threadtimes 8 -iters 100000000 -runstats -v --handle -maxfiles 1000  -trials 5 -wedge
```
2022-05-25 19:51:38 -07:00
Larry Gritz 7ca693842f Adjust string formatters after change in fmt master (#3416)
fmt master seems to have just deprecated the ability for
fmt::sprintf("%s") to default to printing anything that allows stream
output. This breaks use of Strutil::sprintf formatting ustrings.

This isn't yet in any tagged release of fmtlib, but I'm trying to get
ahead of it.

The quick fix is to just change those handful of places to use
std::format style calls, which we are slowly converting to anyway.

Also throw in a fmt::formater for ustrings for good measure.
2022-05-22 09:24:18 -07:00
Larry Gritz 0dde711a71 Convert testshade to modern string formatting (#3415) 2022-05-21 23:34:56 -07:00
Larry Gritz 7fd5f527c8 CI: Fix ci upload of clang-format diffs (used wrong syntax) (#3414) 2022-05-21 20:33:54 -07:00
Larry Gritz 116a75dc6c Fix comment typos 2022-05-13 10:31:29 -07:00
Larry Gritz e726597fca Build: Do NOT auto-download test images by default (#3409)
It's a lot of data, you don't need it if you don't want to run the
full testsuite, and a lot of places and distros have policies against
live downloads happening in the build step. Also, downstream projects
that need to build OIIO for their CI or other reasons don't want to
accidentally download a lot of test data they won't need.

So change the default of OIIO_DOWNLOAD_MISSING_TESTDATA to OFF.

Build with -DOIIO_DOWNLOAD_MISSING_TESTDATA=ON to turn on auto
download of the data images, or else run
src/build-scripts/install_test_images.

Now, this does have the following danger: That people who build OIIO
and do want to run the tests -- and don't know to turn this option
back on -- will end up with very few tests able to run.

We largely address this by observing that quite a lot of our tests
that depended on oiio-images actually depended only on one file
(grid.tif, which is not especially large). So by making a copy of that
file in testsuite/common, quite a few additional tests can run even
without oiio-images.

Though, to be clear, there are still many tests that want oiio-images,
particularly tests that validate support for various image file
formats, which often depend on large collections of images that are
stored in oiio-images. So remember, if you are developing OIIO, the
best policy is to run the whole testsuite. But on the other hand, if
you submit a PR, they'll all be run in CI as well.
2022-05-12 00:08:53 -07:00
Larry Gritz 2c093e6c5e CI improvements -- don't overwrite cmake caches (#3408)
For failed CI builds, save the cmake caches in a safe place, don't zip
them up in situ, because then when I unpack them in my build area
locally, they overwrite my working cache.
2022-05-08 18:01:51 -07:00
Larry Gritz 866c7ba2ae CI: adjust to upgrading Intel Clang compiler to 2022.1.0 (#3407)
The Intel OneAPI LLVM-based C++ compiler, as we download it from Intel
for our CI, bumped from 2022.0.0 to 2022.1.0.

New warning popped up -- newest Intel LLVM-based compiler warns about
overriding certain floating point math flags.

Also had to adjust thresholds on a couple texture tests that have a
few pixels change slightly due to numerical differences.
2022-05-08 08:50:17 -07:00
Larry Gritz 3f58a8dc78 More changes to hide Imath: new half.h, improve vecparam.h (#3406)
Another round to hide Imath externally to OIIO public headers as well
as speed up our own builds.

* Remove the external reference to Imath::M44f from color.h, and instead
  use M44fParam.

* The `<OpenImageIO/Imath.h>` includes the most commonly used Imath
  headers including half.h. But this is unnecessarily expensive (and
  presumptuous about wanting other Imath types as well as fmt.h) if
  you just need to know about `half`.  So we create a new
  `<OpenImageIO/half.h>` that only includes what you need for `half`
  (as before, with logic to handle the changing location of the half.h
  header depending on whether you're using Imath 3.x or OpenEXR 2.x).

* Several files that included Imath.h, but in reality only needed half
  all along, change to including OpenImageIO/half.h.

* simd.h leans more on vecparam.h and other template trickery to
  reduce exposure of methods that only work in the presence of Imath
  headers, and make fewer use cases that would care whether the Imath
  headers are included before or after simd.h (which is less
  controllable for unity builds).

* Vec3Param gains a `cast<V>()` templated method that allows easy
  casting to foreign vector types even if Imath headers are not
  included prior to vecparam.h being included (which is less
  controllable for unity builds).
2022-05-07 09:32:34 -07:00
Larry Gritz 9c42b0b30e New bitcast is closer to std::bit_cast (#3403)
We have a template OIIO::bit_cast which has served us for a while, but
it turns out that C++20 has std::bit_cast which operates ALMOST the
same -- unfortunately, the tempalte arguments are reversed from the
way we did it!

So here we:

* Set up a new `bitcast<>` that works exactly like C++20 std::bit_cast.
* Implement our old bit_cast in terms of the new one, for now.
* Set up `#if` trick so that the confusing OIIO::bit_cast will be
  marked as deprecated beginning with OIIO 2.5, and will be removed
  entirely from OIIO 3.0. (Farther out than that, we may choose to
  re-introduce bit_cast as truly being identical semantics to
  std::bit_cast. But before that is possible, we need to completely
  ween downstream users off the old one.)
* Took the opportunity to expand the set of compilers for which
  certain bitcast overloads use Intel intrinsics. Previously, we only
  did this for the Intel compiler, but it seems to work for modern
  versions of clang and gcc as well. Do a little bitcast testing in
  fmath_test.cpp to verify that the use of these intrinsics doesn't
  break for any of the compilers we use for CI.
2022-05-03 21:30:27 -07:00
Larry Gritz be78eccbde CI: add clang14 test (#3404)
A couple very minor changes were necessary to address new warnings.
2022-05-01 00:12:33 -07:00
Larry Gritz 5852749bb7 CI tests use unity builds for speed (#3402)
Over the span of several individual PRs, we've made the code base safe
for "unity" (a.k.a. "jumbo") builds -- a feature of CMake that
automatically combines multiple .cpp files into a single compilation
unit (basically making temporary .cpp that `#include`s each original
cpp) in order to, allegedly, speed up compilation by not re-parsing
headers multiple times, and other sources of per-module overhead.

We discovered early on that on a modern computer where modules are
built in parallel (another automatic feature of CMake), jumbo builds
are simply not an overall performance improvement for OIIO. Basically,
the efficiency gain from removing redundant parsing is mostly offset
by the loss of parallel efficiency -- fewer and larger modules means
there are periods where all cores are not able to find work to
do. (Reductive example to illustrate the basic problem: If you have 8
independent modules to compile, and each takes 1 second, 8 cores can
compile the entire collection in parallel in 1 second. But a unity
build that batches those files in groups of 4 and achieves a 2x
speedup, thus compiling each set of 4 modules in 2 seconds instead of
4, only can do two of these compilations in parallel, so it takes 2
seconds. We've cut the total work in half, and yet it takes twice as
long in real time to complete, and 6/8 of your cores are idle.

OK, but that's when you have several cores. If you had only one core
(or maybe two) so you weren't using much parallelism in the first
place, then the unity build would look like a win, since you'd really
see the improvement from the amortized overhead of the combined
modules.

Most of us don't have single core machines on our desks, or laps, or
even in our pockets (or on our wrists?).

But we do have single core machines (or close to it) in our CI runners!
We get 1.5-2 cores, roughly, in the slice of VMs we get to run CI on
GitHub Actions. So maybe this is the one place where a unity build would
be of benefit.

That's the theory anyway. Does it pan out? I tested it, and the answer
is basically yes. I can speed up the "build" step of our CI by
somewhere in the vacinity of 30% (varies a LOT from run to run). I
tried a whole bunch of different approaches, summarized in the table
below. I picked the best basic strategies revealed by those tests and
set up the CI to use them. (I didn't preserve all the other
permutations.)

| Name                    | try 1 build | try 2                | try 3          | try 4    |
|:----------------------- | ----------- | -------------------- | -------------- | -------- |
| **linux gcc9 BASELINE** | 14:19       | 11:46                | 11:56          | 13:32    |
| linux gcc9 group        | 9:39        | 8:06                 | 9:58           | **7:58** |
| linux gcc9 batch 8      | 8:06        | **7:17**             | **8:02**       | **7:59** |
| linux gcc9 batch 16     | 8:29        | 7:32                 | **7:56**       | 9:35     |
| linux gcc9 batch 4      | 8:39        | 8:38                 | 8:52           | 10:31    |
| linux gcc9 batch 2      | 13:34       | 12:43                | 11:22          | 9:32     |
| linux gcc9 batch mix 4  | 7:22        | 9:14                 | 9:01           | 9:39     |
| linux gcc9 batch mix 2  | 9:11        | 7:45                 | 10:55          | 9:36     |
| **linux icx BASELINE**  |             | 14:39                | 15:07          | 15:06    |
| linux icx group         |             | 11:59                | **10:36**      | 10:26    |
| linux icx batch 8       |             | **9:40**             | 11:31          | **9:14**     |
| linux icx batch mix 4   |             | 10:06                | 11:58          | 11:16    |
| **macos11 BASELINE**    | 25:41       | 27:53                | 26:30          | 28:32    |
| macos11 group           | 10:56       | 20:24                | 19:28          | 19:24    |
| macos11 batch 8         | 16:43       | 17:38                | **18:34**      | **17:42**         |
| macos11 batch mix 4     |             | **9:22**             | 19:12          | 18:26         |
| **windows BASELINE**    | 20:17       | 23:27                | 28:43          | 19:13         |
| windows group           | 23:05       | 15:57 (tests broken) | 21:57 (broken) | 15:33         |
| windows batch 8         | 21:16       | 15:57                | **17:38**      | **15:08**         |
| windows batch mix 4     |             | **15:30**            | 23:19          | 15:16         |

Notes:

* Timings vary wildly from run to run. You never know which VMs you'll
  get or how overloaded they are. But over 3 trials, the trends were
  clear.
* I rigged it to clear the ccache, so these are FULL uncached builds.
* This is only "build" time. The CI run also includes time to set up the
  VM, download docker images, build or install dependencies, and of course
  run the testsuite. So the overall speedup of the entire CI run will not
  be as improved overall as these numbers indicate for the build step.
  But still, saving several minutes per job means the CI tests turn
  around faster, and that's what we want.
2022-04-29 12:00:36 -07:00
Larry Gritz 815463344d Eliminate use of boost::gcd (#3401)
For C++17 and beyond (and maybe earlier in some compilers), we already
used std::gcd. Now for C++14 compilers without std::gcd, we roll our
own simple gcd implementation instead of using boost::gcd. Maybe it's
slightly slower, but this is nowhere near a performance-critical
path. It's worth it to take one more step at eliminating boost.
2022-04-28 22:03:16 -07:00
Larry Gritz 50062fc121 Improvements in opening unknown files (#3400)
Reminder: When opening a file by name, first it tries to open assuming
that the file's extension indicates the format. If that doesn't work,
it tries all known format readers to see if one will work.

This patch includes several improvements to this process and surrounding
code in imageioplugin.cpp:

* When trying all formats because the extension was wrong, instead of
  traversing the input_formats map in alphabetical order of the list
  of all format names + extensions, try the three most common formats
  we encounter (openexr, tiff, jpeg) FIRST, then try the other formats
  in alphabetical order. We do this by traversing the
  format_list_vector, which contains all format names in the order
  they were declared, and ensure that those common formats are
  declared first. Basically, this means that if the mislabeled file is
  one of those most common formats, the correct reader is found after
  only a couple tries, instead of having to try a dozen or more bad
  guesses of rarely encountered formats.

* Debug mode messages that make it easier to understand which readers
  are being tried for which files.

* Comments clarify that input_formats and output_formats hold not just
  the map from format names to creators, but also map extensions to
  creators. (That confused me while I was debugging this, so I figure
  the clarification is needed.)

* Establish a new extension_to_format_map that lets you get the format
  name if you know the extension.

* Get rid of input_extensions and output_extensions maps, which weren't
  ever used.

* Some other minor refactoring.
2022-04-28 22:03:04 -07:00
Larry Gritz 0318ea44c1 More changes to support unity/jumbo builds (#3398)
* Make gif, png, targa, tiff unity-ready
* Make exr unity-ready
2022-04-25 21:34:07 -07:00
Larry Gritz abb41e5d05 Adjust debug templates -- they can have a simpler template trick (#3399) 2022-04-23 22:44:59 -07:00
splidje 5dce57435f py_imagespec: added get_bytes_attribute to bypass decoding as utf-8 (#3396)
py_imagespec: added get_bytes_attribute to bypass decoding as utf-8 and instead returning as a Python3 bytes object.

Fixes #3395
2022-04-22 18:43:21 -07:00
Larry Gritz d4074f0b31 ustring::from_hash() (#3397)
If you know the hash of a ustring, this tells you the ustring.
(Caveat: in the very unlikely chance of two ustrings having the same
hash, this will return the first one it finds in the table.)
2022-04-22 09:21:21 -07:00
Larry Gritz f1d619e915 More work to enable unity/jumbo builds (#3393)
* Make dpx and cineon unity-ready

* Make jpeg2000 and dds unity-ready
2022-04-21 21:22:36 -07:00
Larry Gritz 965cf04d7d oiiotool: attribute actions get subimage controls (#3384)
I realized that --attrib (and several related actions) only set the
attribute as directed for the first subimage if it's a multi-image
file (such as a multi-part exr), or all of them if the -a flag is
used.  But there was no ability to set it for a particular (non-first)
subimage, like many other oiiotool actions have the ability to do.

So in this patch, I refactor the following commands to use the
OiiotoolOp and related macros, which automatically make it responsive
to the `:subimages=` optional modifiers:

    --attrib
    --sattrib
    --eraseattrib
    --caption
    --orientation
    --clear-keywords
    --iscolorspace

As a bonus aside, one thing this lets you do is set a different
compression method per-subimage using, e.g.,
`--attrib compression:subimages=3 dwaa:100`.
But if you set compression with `--attrib compression`, do not also
use `--compression`, which will override it and also apply to all
subimages.
2022-04-21 12:36:18 -07:00
Larry Gritz 5767c62394 More unity-ready changes (#3392)
* Everything in texture system
* simd.h
* thread.cpp
* paramlist
2022-04-17 11:16:44 -07:00
Larry Gritz 596210427a OIIO_ERRORHANDLER_HIDE_PRINTF as aid for fmt conversion (#3391)
When this symbol is defined, this marks as deprecated the ErrorHandler
class methods that use sprintf formatting notation. It's not enabled
by default, but a downstream project can define the symbol in order to
help root out any uses of the old style formatting functions, to aid
identifying and changing those spots to the new style, long before
they are truly deprecated or removed from OIIO.

This change also sets up an OIIO_INTERNAL symbol that will be present
when OIIO itself is compiling, but not a downstream project using the
OIIO headers.
2022-04-15 17:01:49 -07:00
Larry Gritz a330bae6a7 Make oiiotool unity-ready (#3389)
This is the first tiny step to fixing all the little things that break
in a unity build. This one is pretty small fry -- the oiiotool set of
modules only needed some minor rearrangement of header file include
order.
2022-04-15 17:01:03 -07:00
Nathan Rusch fdafe1c3dc ImageBufAlgo: Initial implementation of st_warp transform function (#3379)
* Initial implementation of `ImageBufAlgo::st_warp`

* Simplify default filter logic, and share it with `ImageBufAlgo::warp`

* Add st_warp to oiiotool

* Add tests for bespoke `st_warp` validations that are done before IBAprep

* Add st_warp test to oiiotool-xform testsuite

* Address review notes

- Remove ST buffer datatype guard
- Simplify additional ROI prep
- Remove unnecessary buffer reallocation

* Use sample accumulator type for source/dest iterator USERT

* Add `--st_warp` section to `oiiotool.rst`
2022-04-15 16:15:54 -07:00
Larry Gritz 092b6af752 Fix botched build from PR 3381, command line utils not installed (#3390)
Cut/paste error inadvertently deleted a critical cmake line that I
wasn't intending to alter or remove, that resulted in the command line
utilities not being tagged for part of the install step. Oops!
2022-04-14 10:22:57 -07:00
Larry Gritz 7fc5199231 CHANGES and set developer snapshot 2.4.1.1 2022-04-13 10:48:22 -07:00
Larry Gritz 7956ca328f Speed up case insensitive string comparisons (#3388)
Oh boy, never leave anything unbenchmarked.

Turns out the boost::algorithm functions we were relying on underneath
many Strutil "case-insensitive" comparisons were ridiculously slow.
We thought they were good enough because they allowed specification of
locale, so we could just pass the static classic locale, and so they
would be inexpensive because they didn't have to query the current
locale.  But this is wrong, they were still ghastly.

So here I rewrite Strutil::iequals, iless, starts_with, istarts_with,
ends_with, iends_with in terms of a new (internal) Strutil::strcasecmp
and strncasecmp (which underneath handle differences in platform, and
use the locale-independent versions). The net result is that most of
those case-independent comparisons speed up by a factor of
50-100x. Wow.

I still need to tackle the family of 'ifind' related functions. They
are a bit trickier. But I'll leave them for another time, because I
need to roll this present fix out right away to fix a real production
bottleneck.

(Worth noting: iequals is instrumental when you're searching a
ParamValueList for a particular name, which is what happens when you
look up attributes from an ImageSpec, which is what happens when you
call get_texture_info(), which is what underlies OSL gettextureinfo()
calls in the cases that they cannot be constant-folded during runtime
optimization. So this came to my attention when analyzing a slow scene
whose shaders had a pathological explosion of gettextureinfo calls that
couldn't be optimized away.)
2022-04-13 10:31:02 -07:00
Larry Gritz 47eac0dfa7 Speed up IBA::isConstantColor (#3383)
Reminder: isConstantColor() finds out if an ImageBuf is constant
color.  It uses the thread pool to check several areas in
parallel. Once any task finds that its subregion is not constant, it
sets a flag so that as other subregions are pulled off the task queue,
they will take an early out if one of their siblings already knows the
image is not constant.

Turns out this isn't much of a big savings in practice, because lots
of regions may be in flight by the time one region realizes it's
non-constant, and once a region task starts, it doesn't check the flag
again.

This patch speeds up isConstantColor by a pretty big factor for
non-constant images (it can't really help for images that ARE
constant) in the following ways:

1. Before doing anything, it checks to see if the FIRST TWO pixels of
   the image are unequal. If that's the case -- and it's a fairly
   common case for non-constant images -- then it immediately knows
   the whole image is not a constant and doesn't need to look at
   anything else or launch any of the threads at all. (If it is a
   constant image, or if the first two pixels are just coincidentally
   identical, this quick check of only two pixels didn't really cost
   us any masurable time.)

2. In addition to checking the result flag at the start of each
   parallel job, now we also check if the flag has been changed as we
   iterate to each pixel. So pretty much as soon as one thread finds
   unequal pixels, the other threads can spot this and stop their
   tasks early, no need to finish looking at their entire region.  (To
   make the more frequent checks of the flag inexpensive, I changed it
   from an atomic to just a regular bool. It doesn't need to be
   atomic, because the strict ordering is not important at all here
   and it doesn't change the result if the threads' access to the flag
   is unsynchronized.)
2022-04-13 08:50:45 -07:00
Larry Gritz a5d723be8a exr output: Fix dwaa compression default (#3387)
When outputting OpenEXR files, in a case where the "compression"
request was for "dwaa" (no compression specified in the main name,
like "dwaa:100") we accidentally forced a default quality level of 4,
which is the default we wanted for zip compression. But that's not a
good default for dwaa!
2022-04-13 08:50:06 -07:00
Larry Gritz 4e985f6347 Lay groundwork for unity builds (#3381)
As I learned recently, a "unity" (aka "jumbo") build is where multiple
.cpp files are combined into one translation unit -- imagine a unity.cpp
that simply has

    #include "file1.cpp"
    #include "file2.cpp"
    ...
    #include "fileN.cpp"

and so you compile unity.cpp instead of the separate file?.cpp files
individually.

Turns out that CMake understands this concept and can do it for you
automatically!

The benefit of a unity build is that file1...fileN probably include
most of the same headers, expand the same templates, etc., so a bunch
of the per-file work of the compiler can be done once rather than
redundantly for each file.

There are two potential downsides, however:

1. It may not be safe to concatenate your cpp files! For example, if
   both file1.cpp and file2.cpp each contain a `static int foo;`, that
   may have been safe when compiled separately, but is not allowed to
   happen twice in one compilation unit. Similarly, if you have headers
   that don't have proper guards against multiple includes, etc. So one
   should expect a whole lot of little fix-ups are needed for this to
   work properly. (We'll come back to that topic.)

2. Combining source file into these "jumbo" modules can make heavily
   parallelized builds on many-core machine not be able to load balance
   or keep all the cores busy. (Simplified examples: if you have 16 .cpp
   files on a 16 core machine, each core can compile one cpp file in
   parallel with the others. But if you mash the modules into just one
   huge cpp file, give that to one core, and your other 15 cores are
   idle, so the full build probably takes much longer.)

I tried this out, including the many fixups implied by (1) above, and
at first the unity builds were slower on both my laptop (8 cores) and
workstation at work (32 cores), because of downside (2) explained
earlier -- harder to take advantage of parallel builds when there are
fewer, bigger, compilation units. Some tweaking of strategy got me to
the point where I could always get the unity builds to go faster, but
not by a whole lot when many core were available. Slighty faster, but
not worth the trouble. A bit disappointing, nearly abandoned the whole
idea.

HOWEVER, in situation where you are limited to very few cores (like in our
CI, which allocates 2 cores, and it sure seems more like 1-1.5 for the
Windows and Mac CI runners), the unity builds are substantially faster --
there's already not much parallelism to exploit, so you come out ahead
with the savings of that redundant per-file work we talked about.

So my current thinking is to go ahead and make the changes that allow
unity builds. I don't particularly recommend them when highly parallel
builds are available to you, but it might help to cut our CI
turnaround time down on the GitHub runners. And maybe it will help in
other situations for other people.

Ok, then. The present patch introduces these concepts and makes the
CMake and other build system changes to allow unity builds. (N.B. It
won't WORK yet, so don't try it!) After we get that out of the way, in
subsequent PRs I'll show all the changs to the code that were
necessary to fix all the little things that went wrong when source
files got combined.
2022-04-11 22:11:59 -07:00
Larry Gritz 8c8e119d3a CI: Bump 'latest release' versions of openexr and pybind11 (#3386) 2022-04-11 21:37:46 -07:00
Larry Gritz 304e4cee5b Fix formatting 2022-04-08 22:51:28 -07:00
Christopher KullaandLarry Gritz 727be5ad8f Fix a number of small warnings on windows (#3382)
* Fix warning from duplicate define
* Fix warnings about bool/int expressions
* Fix discarded result warning in PSD input
* Fix codepage warning from unicode symbol in string constant
* Ensure the term object is initialized with the stream we intend to output to
* Fix pointer casts in paramlist test

Signed-off-by: Chris Kulla <ckulla@gmail.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2022-04-08 18:25:50 -07:00
Larry Gritz a4f422ccec CHANGES 2022-04-01 16:36:09 -07:00
Larry Gritz 7c660429a8 More format conversion (#3377)
Bit by bit, we convert all our formatted string from the sprintf
convention to the std::format convention.
2022-03-31 12:28:04 -07:00
Larry Gritz e3cc8e041c Python: support uint8 attributes in and out (#3378)
This is necessary for dealing correctly with ICCProfile ImageSpec
attributes, which are simply arrays of uint8's.
2022-03-31 12:24:52 -07:00
Larry Gritz 2dc807b4b5 Suppress MacOS warnings about OpenGL deprecation (#3380) 2022-03-31 12:24:29 -07:00
Larry Gritz 35b220ca02 ffmpeg reader: take care against possible double free (#3376)
In FFMpegInput::close(), some of the tear-down calls would happen
regardless of if their pointers were already null. Seemed safe, but
maybe not always? So check the pointers.

Fixes #3371
2022-03-27 09:37:22 -07:00
Larry Gritz 921fab6423 BMP files - read additional varieties (#3375)
There are two undocumented varieties of BMP files only written by
certain Adobe apps that we did not properly handle, identified by the
size value in their header.

This is the only explanation I could find about it:
https://web.archive.org/web/20150127132443/https://forums.adobe.com/message/3272950
2022-03-27 09:37:00 -07:00
Larry Gritz 429d4ac7a1 Convert texture and ImageCache stats output from stream io to fmt. (#3374) 2022-03-26 15:42:06 -07:00
Larry Gritz 98b434a819 Make ImageCache stats print openexr:core option status (#3373) 2022-03-25 19:11:25 -07:00
Larry Gritz ece2fd4f18 Fix conflict between RESTful and Windows long path notation (#3372)
When trying to break filenames into the base name and any "RESTful"
arguments (such as "/foo/bar.exr?name=value&dog=cat"), we were
just looking for presence of the "?" to determine if it was a RESTful
thingie and using that as the split position.

But this is thrown off by an odd Windows notation where names that
start with (get this) "\\?\" somehow designate long filepaths. See
See: https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation

So the solution is to change Strutil::get_rest_arguments to explicitly
check for this pattern at the start of the string.
2022-03-25 14:57:36 -07:00
Larry Gritz 85e3913bb1 Fix writing deep exrs when buffer datatype doesn't match the file (#3369)
In OpenEXROutput::write_deep_scanlines and write_deep_tiles, don't
just pass the DeepData along -- handle the case of where the DD (the
buffer the caller is presenting) does not match the data types that
you said the file is going to hold. In this case, we need to make a
local temporary DD that holds a copy of the passed-in data, but with
the formats transcoded.

Some changes to DeepData were done to support this.
2022-03-24 22:33:48 -07:00
Larry Gritz 608e593f60 CI: Remove the windows-2016 that will be imminently removed (#3370)
GHA is retiring the windows-2016 image, we won't be able to use it soon.

Also bump openexr versions in a couple places.

There's some in-progress work on a VS2022 test, but ignore that for now,
it's commnted out.
2022-03-21 10:05:06 -07:00
Larry Gritz 9497022cda Custom fmt formatters for vector types (#3367)
I'm a total convert to fmt (and/or std::format, std::print) and slowly
converting all prior use of sprintf and iostream to it.

If I print an Imath::V3f or a simd::vfloat3,

    fmt::print ("v = {} {} {}\n", myvec[0], myvec[1], myvec[2]);

That's ok, I guess, but it's clunky and a big pain to put the format
specification for every element separately if it were a vfloat16,
say. I would like to be able to do this:

    fmt::print ("v = {}\n", myvec);

and in fact, it does print all elements (thanks to some nice behavior
by fmt)!  But this does not work as expected:

    fmt::print ("v = {:.3f}\n", myvec);

fmt's tricks will print all elements, but only using the default format
spec, and the spec above applied so the "whole thing", not each element,
if you see the distinction.

So this patch sets up the custom formatter infrastructure to be able
to print array-like things (and in particular, the Imath and
OIIO::simd vector and matrix classes) by specifying the format spec
used for the elements.

The important elements to note:

* detail/fmt.h adds custom formatter helpers for (a) any class with
  operator[] and size() ("index_formatter"); (b) any class that lacks
  these but nonetheless has an array-like memory layout and a known
  length ("array_formatter"). I also added a nonstandard extension to
  the format spec for these, which optionally lets you use a comma
  separator rather than just the space between elements.

* These building blocks are used to specify custom formatters for
  the commonly-used Imath types (in our Imath.h) and our internal
  SIMD vector types (in simd.h).

* simd.h also adds a few other goodies, including an `is_simd<>`
  template, and `size()` constexpr methods to each vector type. These
  make certain template metaprogramming tasks easier for these types.

* A new "type_traits.h" header for collecting a bunch of little utility
  templates, such as `has_subscript<>` and `has_size_method<>`.
2022-03-19 18:21:36 -07:00
Larry Gritz f846cb531a simd.h fixes for armv7 and aarch32 (#3361)
Some neon instructions are only aarch64, guard them better.

Fixes #3360
2022-03-19 18:14:34 -07:00
Larry Gritz 288d0ad096 Print all 4 version numbers in help messages (#3368) 2022-03-18 09:55:35 -07:00
Larry Gritz 313202fe5d JPEG: better handling of PixelAspectRatio (#3366)
JPEG expresses pixel aspect ratio implicitly as header fields
"xdensity" and "ydensity" (which we call "XResolution" and
"YResolution" in our metadata after the TIFF names). We also have
"PixelAspectRatio", so the three of them, if they are all used, form
an over-constrained system. Plus, they may come both in the JPEG
header and also (not necessarily having the same values) in any Exif
block.

And on top of that, the way Nuke and PhotoShop infer the aspect ratio
is BACKWARDS! (If pixelaspect = width/height of a displayed pixel,
then it's also = ydensity/xdensity. But Nuke is the other way
around. Only for JPEG, it gets it right for TIFF and OpenEXR.)

Anyhoo, there were some edge cases in which we were still getting
confused (specifically, that we were making some files that Nuke was
not properly recognizing as anamorphic). This patch tightens up
these cases.
2022-03-18 09:55:11 -07:00
Larry Gritz 7b09f5d4db Fix typo -- used old name for header guard 2022-03-15 14:19:27 -07:00
Larry Gritz 99aae072e7 V3fParam (#3330)
Create a small shim class template called
Vec3Param (and its specialization, V3fParam) that does nothing but
implicitly convert from and to things that looks like 3-vectors
(thanks to some template magic I developed a while back for the Imath
project). And similar for template MatrixParam (and specializations
M33fParam and M44fParam) to pass a square matrix.

Basically the idea is that we can replace the public API function
parameters where we take an Imath::V3f and instead use a
V3fParam. User code that passes an Imath::V3f still works because
V3fParam accepts and converts it.  Implementation code can implicitly
convert the V3fParam to an Imath::V3f, so it doesn't need to be
changed, either. Only the function declaration itself. (Same basic
situation for MatrixParam and Imath::M33f/M44f.)

So in the process, now we have laundered our public API so that it
doesn't reference the Imath types and headers any longer. This confers
two big advantages:

1. It allows OIIO itself and any downstream client code calling OIIO
   to use *different* versions of Imath if they want.

2. It allows client code to not need Imath at all, for example if they
   have their own proprietary vector type that they prefer to use
   internally.

I'm not necessarily 100% sold on this approach, but I think it's got
promise and am seeking feedback. It seems to work, and I was able
to compile OSL against this altered OIIO with *no changes*.
2022-03-13 21:34:39 -07:00
Larry Gritz 2340b90160 Minor tweaks to CI workflow (#3365)
Just some renames and minor refactoring as I settle into the "strategy"
style.
2022-03-07 20:46:03 -08:00
Larry Gritz e82063d163 ffmpeg: make supported file extension check be case-insensitive (#3364)
The use of ends_with instead of iends_with made it so that
capitizalized files (especially on case-independent filesystems like
Windows or some Mac filesystems) were rejected.

(And yes, I did grep the whole code base for ends_with to be sure that
this was the only place we made this mistake.)

Fixes #3362
2022-03-07 20:45:38 -08:00
Larry Gritz 134ea8cc44 Bump master version to reflect ABI changes with the recent string_view 2022-03-07 10:45:18 -08:00
Larry Gritz 41b2a31b7a Build and CI and support for the icx compiler (#3363)
icx is the *new* Intel LLVM-based compiler, and it behaves a lot like
clang (versus icc, which is the "classic" Intel compiler).

* An additional CI test in ci.yml for icx.

* Tweaks in compiler.cmake and platform.h to detect and set options for
  this compiler.

* A variety of warning fixes encountered for this compiler.

* Add a new cmake build-time option `ENABLE_FAST_MATH` (default: OFF)
  for enabling fast-math optimizations that trade IEEE compliance for
  speed. The Intel compiler enables it by default (!), so this build
  option makes icx behave like the other compilers (not fast math
  unless explicitly asked for), which makes the CI tests and other
  behavior more consisent across compilers and platforms.

* Note: The bug that prevents some versions of fmtlib from working
  with icc does not appear to be a problem for icx.
2022-03-07 10:33:53 -08:00
Larry Gritz fcdbd6cd4c Switch to using std::this_thread::yield() now that we are C++11 (#3359)
Fixes 3357, which reported problems with Clang + libc++ + Windows,
where our old code used something pthreads-specific.
2022-03-07 00:50:38 -08:00
Larry Gritz d3648ab272 Fully templatize our string_view (#3344)
Brings us more in line with C++17 std::string_view.
2022-03-07 00:50:16 -08:00
Larry Gritz 461c9c058f CI: Use GHA "strategy" to make test descriptions more compact (#3356)
I finally learned how the "strategy" stuff works and refactored our
CI workflow based on it.

In short, we previously treated each CI test as its own universe, with
a huge amount of repeated build logic. These changes cut down on
redundancy by, for each set of related tests, collapsing them into
just one recitation of the build script logic and a handful of
variables that create the different test variations.

Currently, the categories are (a) all tests based on ASWF containers and
corresponding to VFX Platform specs, (b) "off-year" combinations based
on the native Ubuntu installations, (c) Mac tests, (d) Windows tests,
(e) the clang-format checker.

This refactor cuts the size of the ci.yml file by more than 50%, and
makes it much easier to add or change individual test configurations
in the future.
2022-03-04 20:57:20 -08:00
Larry Gritz 20645f83a8 Strutil::print vs sync::print (#3348)
Strutil::print wraps fmt::format to render the formatted output into a
std::string, then sends the string to Strutil::sync_output(), which
ensures that every string printed (or sent to a FILE or stream) is
done so atomically, using an internal mutex, and with a stream flush
after each string. But this makes it a lot more expensive than it
needs to be, when you don't need such care -- either because buffered
output is ok, or because you don't need the thread safety.

This patch:

* Adds an optional `flush` parameter to sync_output(), defaulting to
  true, which controls whether sync_output flushes or not.

* Introduces Strutil::sync::print, which is the same fully
  synchronous, thread-safe, non-buffering behavior that Strutil::print
  has traditionally had. Use this when you need those features.

* Redefines Strutil::print to be an alias for fmt::print, which means

  - There is one fewer layer of template expansion and generated code,
    and possibly fewer internal string copies, so that should make for
    both faster compilation and faster runtime performance.
  - Results are buffered, no sync after every output, so much faster
    when you don't need that.
  - No internal mutex.

On the platforms we use -- and with the current implementation of
fmtlib -- fmtlib's underlying use of stream and FILE output appears to
be adequately thread-safe. But we can't 100% guarantee this on all
platforms or all future versions of fmtlib, so users who need the
stronger guarantees (and are willing to sacrifice performance) can
simply use sync::print.
2022-03-04 10:03:49 -08:00
Anthony Nemoff 9f74aa2108 Add UDIM pattern <uvtile> (in lower-case) (#3358)
* Add UDIM pattern `<uvtile>` (in lower-case)

This UDIM pattern is equivalent to `u<u>_v<v>`.
See also #3280.

References:
- Clarisse: https://clarissewiki.com/5.0/image-maps-texture.html
- V-Ray: https://docs.chaos.com/display/VMAYA/File+Names+for+Bitmap+Textures

* LG Updated test and ref output
2022-03-02 15:52:29 -08:00
Larry Gritz 16e2bad47d CI: first stab at CI builds for Intel compiler (#3355)
* New CI test downloads the Intel icc compiler and builds with it.
* A variety of minor fixes to address warnings from icc that were
  not apparent from the other compilers.
* Some minor changes to just a few tests and reference output where
  the icc-built compiler produces slightly different (usually LSB)
  results.
2022-02-28 12:35:59 -08:00
Larry Gritz 2669a7d939 Some denorm and flush utilities no longer need to consider gcc 4.8 (#3354) 2022-02-27 20:53:07 -08:00
Larry Gritz 90323d8130 Fix inline discrepancies between template decl and redecl (#3350)
These are cases where we declared a template, then later gave its full
definition, and we marked the declaration of the OIIO_FORCEINLINE but
omitted it from the later definition.

This addresses some compiler warnings from icc.
2022-02-27 19:21:55 -08:00
Larry Gritz 7171b07dd4 Beef up precision in computePixelStats (#3353)
We should have been doing this particular multiplication as doubles, and
in just a couple spots, it slightly changes the answer.
2022-02-27 09:19:00 -08:00
Larry Gritz 1f1510fca8 runtest.py: Rename oiio_relpath to make_relpath (#3349)
Just reconciling some differences between this file and the analogous
one in OSL.
2022-02-27 09:17:59 -08:00
Larry Gritz 829d337264 Build: allow -Werror to be disabled even on CI branches (#3351)
Slight reworking of -Werror logic to let the default behavior be
changed by setting a cmake variable. In particular, this allows us to
make a CI build disable -Werror when we need to.

Previously, having the "OpenmageIO_CI" env variable set trumped all
else and forced -Werror. Now it just contributes to the default behavior,
but setting `-DSTOP_ON_WARNING=OFF` and cmake config time can still
disable it.
2022-02-26 23:44:38 -08:00
Larry Gritz d0302f6333 Avoid internal use of OIIO::string_view::str() (#3345)
Seemed like a good idea when we wrote it, but subsequently,
std::string_view was accepted into C++17 without a str() method. So
for the sake of future full interchangeability with std::string_view,
stop using this method.  We will eventually deprecate it.
2022-02-26 23:43:31 -08:00
Larry Gritz 7b8f4b9b7e Fix broken iinfo --stats (#3352)
Inadvertently broken by PR 3328.
2022-02-26 23:37:09 -08:00
Larry Gritz d15fd4aa06 Improvements to ParamList and ImageSpec to reduce ustring construction (#3342)
Special case some methods of ParamValue, ParamList, and
ImageSpec::attribute for ustring and string_view data, to reduce some
redundant copies and/or ustring conversions.

The internal method init_noclear() is augmented with a flag that allows
the caller to specify that any string data it might point to is already
ustrings, and thus does avoid the costly default behavior of converting
strings in the data block to ustrings. (This is not publicly exposed, so
users can't screw it up.)

So the new ParamValue constructor directly from a ustring can use this
flag to avoid passing the already-ustring through the string-to-ustring
conversion a needless second time. But also, the copy constructor, move
constructor, and assignment can use the flag and avoid the extra
conversion, since by definition they are copying from the contents of an
existing ParamValue which is guaranteed to be already ustring-ified.

While I was at it, I turned the optional arguments of ParamValue
constructors into "strongly typed" flags, deprecating the ones that
take a raw bool, which might be confusing.
2022-02-21 21:20:14 -08:00
Larry Gritz f6fb1eb81a Wean ourselves off of string_view::c_str() (#3343)
c_str() was cute, but it's a little dicey and it's not present in
the C++20 std::string_view. We didn't use it in a ton of places,
so replace with other idioms so that in the future we are better
able to interchange with std::string_view or replace our own entirely
once we have flying cars and C++20 minimum.
2022-02-20 16:19:19 -08:00
Larry Gritz 8c714804a9 Auto conversion from among different string_view types (#3337)
* Allow ustring and OIIO::string_view to auto-cast to fmt::string_view
  (helps some fmt formattting of types without custom formatters).

* When std::string_view (C++17) and/or std::experimental::string_view
  (some compilers pre-C++17) are available, add OIIO::string_view
  auto-construction from and auto-casting to those types.
2022-02-19 14:39:37 -08:00
Larry Gritz 7ee7477c4f Mark a bunch of long-deprecated things as OIIO_DEPRECATED (#3328)
...and stop using them internally as well.

For some of the IBA functions, we were unable to fully mark them as
OIIO_DEPRECATED (so instead that hint is commented out) because the
function signatures of the deprecated and new ones can be
ambiguous. We're just going to have to delete those when we are at a
compatibility break point, without going through a period where they
are present but marked as deprecated.
2022-02-19 10:11:25 -08:00
Larry Gritz 4260a7cc81 Track down some integer overflow warnings (#3329) 2022-02-19 09:31:11 -08:00
Larry Gritz 4f1398a689 CHANGES and bump version for developer preview 2022-02-18 10:04:33 -08:00
Larry Gritz e800c05dfd oiiotool --warp improvements (#3341)
* New "wrap" optional modifier lets you specify which wrap mode to pass
  to IBA::warp().

* fix typo in error message.
2022-02-17 23:37:00 -08:00
Larry Gritz a53399deb5 oiiotool --pixelaspect : fix setting of attributes (#3340)
We weren't doing quite the right calls to set the attributes correctly
after performing the scale.
2022-02-17 23:36:31 -08:00
Larry Gritz 31b643a02f Testing: OIIO_CHECK_SIMD_EQUAL_THRESH to use <= eps (#3333) 2022-02-16 20:15:57 -08:00
Larry Gritz 1fad2a89dc Imath fiddling (#3339)
Make the imath includes respect the recently added
OPENIMAGEIO_IMATH_DEPENDENCY_VISIBILITY flag, just like the libraries
do.
2022-02-16 20:15:40 -08:00
Larry Gritz 00c09106fe Hide static library dependency symbols from the python module (#3338)
Just like we had done for the other libraries recently. And need
to make sure that the imath libs are added explicitly to the python
module's needs, since for hidden static libraries, they will not get
picked up merely by linking to libOpenImageIO.
2022-02-15 14:38:52 -08:00
Larry Gritz 4323093bdb CI: bump OpenEXR version used for 'latest' (#3336)
Also, for the bleeding edge test, OpenEXR's "master" has been renamed
to "main".
2022-02-12 14:50:24 -08:00
Larry Gritz a2e1ccd7d2 More Imath hiding controls (#3335)
Add an OIIO build-time option for forcing our exported
OpenImageIOConfig.cmake to skip the find_dependency of Imath and
OpenEXR.

This is helpful if you're at a site that is trying to build OIIO
against statically compiled Imath/OpenEXR, and want to be super sure
the downstream projects are definitely not going to encounter that
find_dependency(Imath) when the read the OIIO config files.
(They could do their own `-DOPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH`,
but I want even that to be unnecessary.)
2022-02-11 19:03:30 -08:00
Larry Gritz 4a345ad77e Bump developer preview version to 2.4.0.2 2022-02-10 22:21:48 -08:00
Larry Gritz 620cec2b5b CHANGES 2022-02-10 22:21:48 -08:00
Bernhard Rosenkraenzer e8bd39f078 Port to ffmpeg 5.0 (#3282)
Port to ffmpeg 5.0 -- av_register_all removed, AVPicture
removed, pkt_pts changed to pts

Signed-off-by: Bernhard Rosenkränzer <bero@lindev.ch>
2022-02-10 22:17:47 -08:00
Larry Gritz 54019aef35 Docs touchups
* Change example of set_write_tiles so that it uses a tile size I would
  more strongly recommend. (Very minor nit.)
2022-02-10 14:10:12 -08:00
Larry Gritz a07cb917ba Reduce Imath footprint even more (#3332)
There was that one pesky place where we were still including Imath
headers, from simd.h in the case where OIIO_SIMD==0 and we wanted to
fall back on some Imath::Matrix methods.

Ugh, but this backfired because when including this file from Cuda,
OIIO_SIMD==0 and it included the header. But what happens if a
downstream app (a) includes this file from Cuda, and (b) uses a
DIFFERENT Imath (so names clash) or doesn't want to use Imath at all?

So one more change:

* Remove the include of Imath.h from simd.h entirely.

* Most places where we fell back on the Imath::Matrix methods, just
  replace it with scalar code, it's not complicated. (For some technical
  reasons, this required some minor surgery on the matrix44 class, but
  not anything that changes anything from a caller's point of view.)

* The one complicated case is matrix44::inverse(). Punt! Just let that
  only be implemented if either (a) there is SIMD available, or (b)
  there is Imath available (i.e., included by the downstream code
  prior to this header). That's it. If you want to invert a 4x4 matrix
  without SIMD, you need to arrange inclusion of the correct
  ImathMatrix.h yourself before including this header.
2022-02-10 14:00:46 -08:00
Larry Gritz fd8bdbcfaf Add texture creation metadata: "handed" (#3331)
For vector displacement maps or normal maps that are in tangent space,
it is heplful to be able to record whether the data are intended to use
a local left-handed or right-handed coordinate system, and for that to
be querably from the shader accessing the map.

The `maketx --handed` option, or `oiiotool -attrib -otex:handed=...`,
or adding "handed" metadata to the configuration ImageSpec being
passed to `IBA::make_texture()` does this. It's easy for texture
formats like openexr that allow arbitrary metadata. For TIFF textures,
we embed it in the ImageDescription tag (as we do for several other
texture-specific hints).
2022-02-08 11:26:43 -08:00
jreichel-nvidia 475cf1eccd Targa: Fix parsing of TGA 2.0 extension area. (#3323)
Skip 3 bytes between "software" and "background (key) colour" for the "software
version" (was simply missing). Avoids that m_alpha_type is overwritten with
wrong values.
2022-02-08 10:17:13 -08:00
Larry Gritz f482be2d6a Update THIRD-PARTY info for OSL and OCIO with new URLs and copyright notices 2022-02-06 17:17:48 -08:00
Larry Gritz cc8b41b669 Split fmt setup into detail/fmt.h, fix fmt ostream problem (#3327)
The very latest fmt master changes a behavior: fmt functions no longer
automatically know how to format any type that can output to an
ostream, and instead need custom formtter objects. This breaks A LOT.
Fix by defining the preprocessor symbol `FMT_DEPRECATED_OSTREAM`,
which restores the old behavior (for now, at least).

While I was at it, I moved the fmt inclusion logic out of strutil.h
and into a new separate header, detail/fmt.h. This is in turn included
from strutil.h, so nothing in user code needs to change.
2022-02-06 17:12:06 -08:00
Larry Gritz 91f519ecfd Handle NUL (0) characters in ustrings by truncating. (#3326)
It turns out that this can crop up all the time, sometimes from
malformed metadata inside image files. We weren't noticing it because
in many cases, things ended up being turned into ustrings twice, and
the sequence string-with-nuls -> ustring() -> c_str() -> ustring()
will launder it. As I was tracking down and eliminating some of the
double ustring constructions, the metadata strings that were malformed
all along started becoming symptomatic.

Bad paradoxes follow from a ustring contain embedded NUL characters,
including ustring.c_str() and ustring.string() being different
character sequences, as well as ustring.hash() not being equal to
strhash(ustring.c_str()). One should definitely be able to count on
ustring(cstring) == ustring(ustring(cstring).c_str()).

So this patch checks for embedded NUL characters at the appropriate
time of ustring construction, and truncates the character sequence at
the point of any internal NUL character.
2022-02-06 17:11:48 -08:00
Larry Gritz 52f7c40b57 CMake: Remove redundant include of GNUInstallsDirs (#3325) 2022-02-06 17:11:26 -08:00
Larry Gritz 1921787fed Changes to make it easier to hide the Imath dependency (#3322)
* `OPENIMAGEIO_IMATH_DEPENDENCY_VISIBILITY` is a new CMake cache
  variable at OIIO build time that controls whether the Imath library
  dependencies will be declared as PUBLIC (default) or PRIVATE target
  dependencies of libOpenImageIO and libOpenImageIO_Util.

* For *downstream projects* that consume OIIO's exported cmake config
  files, setting CMake variable `OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH`
  to true will skip the find_depencency() calls for Imath and OpenEXR.
  To clarify, this is not a variable that has any effect when building
  OIIO, it's something set in the downstream project itself.

* Add a `OIIO_IMATH_H_INCLUDED` header guard in OpenImageIO/Imath.h,
  which allows something downstream to pre-define it to prevent OIIO
  headers it needs to read from using the contents of that header.

Most builders of OIIO won't care and shouldn't change the defaults or
use any of these.  But here's the specific case it addresses: If you
are building OIIO against static libraries of Imath & OpenEXR, but the
libOpenImageIO will be consumed by a downstream project that wants to
use a different Imath version, this can help you avoid some build-time
conflicts in the downstream project.
2022-02-06 17:11:02 -08:00
Larry Gritz 5dd4cb224f Color space adjustment for PPM and PNG files. (#3321)
PPM by specification is Rec709! Make it so.

PNG files were getting marked as sRGB or Gamma if certain header
attributes were found in the file, but if they were absent, we didn't
designate a color space at all. Change so that the default assumes
sRGB, in the absence of any metadata telling us for sure.

Fixes #3084
2022-02-05 11:25:22 -08:00
Larry Gritz c6f9d40135 Expose additional OCIO utility functions via ColorConfig (#3319) 2022-02-02 13:21:25 -08:00
Daniel Flehner Heenanddaniel aef4227aed update example and definition to match C++ (#3320)
Co-authored-by: daniel <daniel@stormstudios.no>
2022-02-02 13:20:19 -08:00
Larry Gritz afd1d31d80 Correction to recent wstring changes: un-virtualize one method (#3318)
One new method that should have been inline and non-virtual (so that
this whole set of changes does not change ABI by shifting the vtable
around) was accidentally marked virtual -- cut and paste error. This
patch fixes it to restore ABI compatibility.
2022-02-01 22:37:43 -08:00
Larry Gritz d1a3d279ef TIFF: Mitigate IPTC corruptions (#3316)
IPTC data blocks seems buggy, and I don't know why. Our code?
Something in libtiff?  Since nobody is depending on it and none of our
testsuite appears to fail when disabled, only write the IPTC block if
the user explicitly asks for it.  Also, when reading them, don't
overwrite other metadata of the same name.
2022-01-31 09:38:21 -08:00
Merwan Achibet c8dfbd7066 Relocatable cmake package (#3302)
CMake: use relative paths in the config script
2022-01-31 09:35:34 -08:00
Larry Gritz ca75260255 Work toward eliminating string_view::c_str() (#3315)
We wrote our string_view before C++17 std::string_view was finalized,
and the std one doesn't have a c_str() method. For conformance with the
standard, I want to remove this over time from ours.

Part 1: There were some places we did not need to call c_str() at all,
and some places where it was much more appropriate to just use a
std::string.
2022-01-30 08:21:15 -08:00
Larry Gritz 2b01dd3350 string_view: beef up tests of constructors (#3314) 2022-01-30 08:20:47 -08:00
Larry Gritz 2b453321b7 wstring (almost) all the things (#3312)
As Doug Rogers points out in Issue 3304, it is customary for Windows
applications to use wstring extensively for Unicode support. But it's
especially critical for unicode filenames, because unlike Unix-like
OS's where fopen() and similar functions support UTF-8, on Windows
those functions are strictly ASCII, and Windows users are used to
calling _wfopen() and other nonstandard functions that expect
filenames to be std::wstring if they want to support Unicode.

This patch:

* More clearly documents through all of our classes when parameters that
  represent filenames or searchpaths are assumed to support UTF-8.

* Augments ImageInput, ImageOutput, and ImageBuf so that their methods
  that take file names or path lists have additional flavors that take
  wstring (always implemented as an inline shim that translates the
  UTF-16 wstring to a std::string with UTF-8 encoding to pass on to the
  usual method).

* Augments ImageCache and TextureSystem in just a couple places, the
  functions where a filename is turned into a handle. All the many
  other functions that take ustring for function names were left alone,
  because they are called very frequently and are performance-sensitive,
  so we don't want any translation from wstring to string happening on
  every call.

We do not attempt to add wstring-based versions of functions that take
strings for other purposes -- that is, that are not intended to
represent filenames.
2022-01-29 08:56:24 -08:00
Larry Gritz ac46f1f7f1 Avoid unsafe isspace() (#3310)
C isspace() takes an int, but on Windows when building in debug mode,
the implementation of isspace() can hit an assert if the value is < 0,
which of course it can be if you're looking at a character in a string
whose high bit is set (because char is signed).

Easiest solution is to make our own Strutil::isspace that does exactly
what we want and is safe.

Fixes #3300
2022-01-28 21:29:11 -08:00
Larry Gritz 8eb2c6a9da Embed Imath version symbols in oiioversion.h (#3305)
This makes sure that two new preprocessor symbols are defined in
oiioversion.h: `OIIO_USING_IMATH_VERSION_MAJOR` and
`OIIO_USING_IMATH_VERSION_MINOR`, revealing the version of Imath being
used by the build of OIIO (which may not be the same as the version
found or being used by the app that's calling OIIO). They also get
defined as CMake variables in our exported cmake configs, allowng
downstream cmake build systems to be able to easily test whether the
Imath they found is compatible with the version that we use in our
APIs.
2022-01-28 14:32:26 -08:00
Larry Gritz 71f0aa6a58 Hide Imath headers and types from most of the public API (#3301)
This patch sets out to minimize the extent to which Imath is a
necessary source dependency for using OIIO C++ header files and
APIs. The major changes are:

* Remove the unconditional `#include <OpenImageIO/Imath.h>` from
  fmath.h and simd.h. Those forced Imath headers on nearly all all
  code that uses OIIO's public APIs, whether or not they needed the
  very few calls where Imath types are used as parameters.

* Make sure all public OIIO non-virtual methods and freestanding
  functions that have Imath types as parameters are enclosed in header
  guards like `#ifdef INCLUDE_IMATHVECTOR_H`. Downstream client code
  needs to include Imath headers before including OIIO headers, if
  they want to call those few particular functions.

This means that client applications who don't need those particular
functions, but call other parts of the OIIO APIs, don't need to
`#include` any Imath headers (or pay the extra compilation time for
doing so), and don't need any knowledge of which specific version of
Imath is used by the OIIO they are using.

The small number of public API calls that will no longer be visible
downstream unless the client code also include Imath headers (before
the OIIO headers) are:

  - color.h: ColorConfig::createMatrixTransform (needs ImathColor.h)

  - fmath.h: type conversions involving `half` (needs half.h).

  - imagebufalgo.h: warp(), colormatrixtransform() (needs ImathMatrix.h)

  - simd.h: conversions between our SIMD types and Imath types (Vec3,
    Matrix33, Matrix44) and vtransform() calls involving those types
    (requires ImathVec.h and ImathMatrix.h), and SIMD load/store
    involving `half` data (requires half.h).

These changes necessitated adding including of Imath.h in a number of
internal .cpp files, the ones where those types are actually used.

The following header files do still unconditionally reference Imath
types or headers:

  - texture.h: Some virtual methods of TextureSystem use Imath types
    as parameters.
  - imagebufalgo_util.h: For `half` support. We use this a lot
    internally, but presume most client code never uses this header.
  - simd.h, ONLY IF USE_SIMD=0 (which is generally only used for
    development debugging and if porting to obscure platforms that are
    neither x86 nor ARM).

The bottom line is that the vast majority of downstream callers of OIIO
APIs who need ImageInput/ImageOutput, ImageBuf, ImageBufAlgo, and
generally everything in the OpenImageIO_Util library, do not need to
use Imath types, include Imath headers, or even be aware of which Imath
release OIIO is using.

Why would we do all this?

Because this paves the way for optionally building OIIO to link against
static libraries for OpenEXR and Imath, essentially embedding and
completely hiding an OpenEXR/Imath inside libOpenImageIO.

That allows libOpenImageIO to use the very latest Imath (3.1, say,
with the new faster core API), even though that libOpenImageIO is
being consumed by an application that for whatever reason is forced to
use an entirely different (older) OpenEXR or Imath library.  In other
words, it lets OIIO use OpenEXR/Imath fully embedded without
transitively passing that OpenEXR version as a downstream dependency
(except for the few use cases that need to call the tiny number of
OIIO API methods that require Imath types.

There is a small chance that client code that use Imath types and
SHOULD have been includeing Imath headers themselves actually omitted
those includes and dependd on the fact that certain OIIO headers
included them.  Now that they don't, it may require the client-side
code to add those includes. I'm going to claim that this is a "bug" in
the client code (they didn't include a header that defined a type they
used), and not a breaking incompatibility in OIIO's public calls
themselves. Thus, I feel comfortable with these changes being in OIIO
2.4 (today's master) and not necessitating a 3.0 release (in which
arbitrary loss of backward compatibility would be allowed). So watch
out for the occasional need for OIIO-calling code to need to add an
`#include` for Imath types the code was always using, but neglected
to explicitly include.
2022-01-28 13:04:40 -08:00
Larry Gritz 22a67bd24d CI: revise failed build artifact storage to capture cmake files (#3311) 2022-01-27 16:52:22 -08:00
Larry Gritz a7bd12b565 utf8 / utf16 conversion modernization. (#3307)
Our Strutil utilities for utf8 <-> utf16 conversion were based on
Windows specific calls that we had added even before C++11 was our
minimum. Replace the Windows-specific code with std calls, and
expose them in strutil.h for all platforms (why not?).
2022-01-26 20:33:50 -08:00
Larry Gritz cbd0917d03 Filesystem::searchpath_split handle empty paths (#3306)
Fixes #3274
2022-01-25 15:45:31 -08:00
Larry Gritz 7a4f0221cf Separate C++ that we build with from what we demand downstream (#3288)
We were passing along, in the exported cmake config files, a demand
for downstream clients to use a C++ standard version equal to that
which we used to build OpenImageIO itself. But that's not
necessary. We may choose to build with C++17 (for example), but all of
our public APIs are safe to use for C++14.

Split the build-time options to CMAKE_CXX_STANDARD for the standard we
build this project with, and DOWNSTREAM_CXX_STANDARD for the standard
we are declaring is the minimum to *use* the library.
2022-01-23 23:10:18 -08:00
Larry Gritz 7babbbfe79 Targa improvements: attribs, unassociated alpha handling, and more (#3279)
The main event:

* Assume that for a TGA 1.0 file (too old to have the header field
  that says if alpha is associated, unassociated, or meaningless), if
  the alpha is zero everywhere, it means that it's meaningless, not
  unassociated, so in that case we should skip the
  auto-premultiplication. (See issue 3277)

Public-ish stuff:

* Be more consistent with Targa-specific attributes all being called
  "targa:foo" (most were, but one was "tga:alpha_type").
* Document all the targa-specific attributes (a few were not).
* Add "targa:version" to reveal whether the file was a TGA 1.0 or
  2.0 version of the format.

Internal stuff, opportunistic:

* Some more minor conversions of string fomatting to fmt style.
* Convert some std::cerr debugging code (commented out) to the DBG macro
  we use anywhere.
* The `std::unique_ptr<uint8_t> m_buf` should always have been
  `unique_ptr<uint8_t[]>` because it's not a pointer to a single value.
2022-01-23 23:09:38 -08:00
Larry Gritz dc223d93c9 simd.h: more guards for Cuda are necessary (#3292) 2022-01-20 15:54:44 -08:00
Larry Gritz fc793ee786 oiiotool --ch : warn for unknown channels (#3290)
I realized recently that if you said something like

    oiiotool foo.exr --ch R,G,B,A -o out.exr

and there was no "A" channel... it would just silently fill the channel
with 0 in the output.

This patch adds a warning if --ch is told to copy a channel that doesn't
exist in the input.
2022-01-20 09:16:15 -08:00
Larry Gritz f22b1f7755 TIFF: Special hint to suppress output of EXTRASAMPLES tag (#3289)
Ugh, there's a situation where PhotoShop is misinterpreting an alpha
channel for certain OIIO-written TIFF files, but it's fine with some that
came from elsewhere, and the only thing that appears to be different is
that the non-OIIO one entirely lacks the EXTRASAMPLES TIFF tag.

So I'm adding an option (use with extreme caution) allowing you to
tell the TIFF output to not output this tag, even though clearly it
should be.
2022-01-20 09:16:01 -08:00
Larry Gritz 10a35e2d55 simd.h: when compiling with Cuda, don't include intrinsic headers (#3291) 2022-01-20 09:15:49 -08:00
Larry Gritz 2714b71bb5 TIFF: gracefully handle missing ExtraSamples tag (#3287)
Some rogue app out there is writing 4-channel TIFF files without the
ExtraSamples tag in the header that explains that the data is a valid
alpha channel.

We were using TIFFGetFieldDefaulted to retrieve this tag, and guess what?
The defaulted behavior changed between libtiff 4.0 and 4.3!

Changing to TIFFGetField actually turns out to fall back to the right
logic on our side, which boils down to assuming a 4th channel is alpha
if there's no other information. That seams reasonable -- RGB + mystery
channel is almost certainly RGBA.
2022-01-19 15:00:31 -08:00
Larry Gritz aa81e78006 Clarify UDIM docs (#3285) 2022-01-18 22:53:05 -08:00
Larry Gritz 35cb6a83e2 Add UDIM pattern <UVTILE> (specified by MaterialX) (#3280)
MaterialX documents a udim pattern that we hadn't previously supported,
`<UVTILE>`, which is equivalent to our `<U>_<V>`.

Fixes #3275
2022-01-17 11:25:00 -08:00
Merwan Achibet 0f1d5caf64 Fix OpenEXR build script for Windows (#3281) 2022-01-17 10:01:26 -08:00
Larry Gritz c2a41fc35e Minor build and compile fixes (#3278)
* Bugs fixed in build_opencolorio.bash, it botched some of the directory
  choices when customizing where to place and build it. Also, switch to
  the more standard BUILD_SHARED_LIBS cmake variable to control whether
  to build dynamic or static libraries.

* Correctly handle the cmake variable VISIBILITY_MAP_FILE being set to
  "" on the command line as a way to disable using the visibility map file
  entirely.

* FindOpenColorIO.cmake changes:
    - Prefer and use an exported cmake config for OCIO if found (is should
      be present for OCIO 2.1+), unless caller set OPENCOLORIO_NO_CONFIG=ON.
    - New hint OPENCOLORIO_INTERFACE_LINK_LIBRARIES lets caller force a
      list of interface link libraries. This is helpful when purposely using
      a static OCIO library, which itself has static dependencies, and you
      need to name those specific library filepaths.

* Simplify some of the logic for setting extra link flag arguments for the
  two main libraries.

* On Linux, also set link flags `--exclude-libs ALL` to hide symbols from
  any embedded static library dependencies, to prevent clashes with other
  versions of those libraries that may be compiled into a DCC app.
2022-01-16 21:55:28 -08:00
Larry Gritz c0ab86d423 make_texture: ensure that "maketx:ignore_unassoc" is honored (#3269)
I realized that a call to make_texture() with the "maketx:ignore_unassoc"
attribute set did not properly set the configuration attribute up when
opening a new ImageBuf.
2022-01-15 23:57:31 -08:00
Thiago IzeandThiago Ize 1259ca80c1 Fix clang 10 warning: (#3272)
```include/OpenImageIO/typedesc.h:620:10: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
auto parse(format_parse_context &ctx) -> decltype(ctx.begin()) const // c++11
```

Co-authored-by: Thiago Ize <thiago@solidangle.com>
2022-01-15 23:55:17 -08:00
Larry Gritz 65c457d6f5 Bump version after developer preview tag 2022-01-07 11:55:22 -08:00
Larry Gritz 5317863c45 CI: Update 'latest' fmt to 8.1.1 2022-01-06 22:36:09 -08:00
Larry Gritz 1e488aedc2 CHANGES 2022-01-05 17:17:07 -08:00
Larry Gritz c885e5b05c Python: fix clamp() when min or max are just a float (#3265)
The docs said that passing a tuple for min or max param of the clamp()
function gave per-channel values, but passing a single float gave one
value for all channels.

In fact, the implementation used the float to clamp only the first
channel. This patch fixes the behavior.

Fixes #3264
2022-01-05 12:59:50 -08:00
Larry Gritz 6d2df7095d Docs: supply more python and oiiotool examples to IBA docs (#3263)
In addition to C++ code examples for each IBA function, work toward
also having equivalent Python code. Also, where applicable, show the
equivalent operation using oiiotool.
2022-01-05 12:58:50 -08:00
Larry Gritz 908ce0cd56 TIFF: make it work for 16-bit palette images (#3260) 2022-01-04 10:26:12 -08:00
Larry Gritz f8fc2358cf oiiotool: don't warn for --colorcount or --rangecheck (#3262)
We had forgotten to mark --colorcount and --rangecheck as commands
that intentionally outputs to the console. This omission meant that an
oiiotool command consisting only of a those would warn about no
output.  But we didn't really want it to.
2022-01-03 23:51:50 -08:00
AdamMainsTL b4aa7aa40c Fix variable usage example in docs (#3261)
I found this while reading through the image output section and it seems wrong given the following examples.
2022-01-03 13:08:25 -08:00
Larry Gritz 01fbf4167d oiiotool: control flow (#3243)
How do you craft an oiiotool command that will examine a file and add
an alpha=1 channel if it's a 3-channel file, but leave the existing
alpha alone if it's already a 4 channel file?

This patch adds control flow, so you could express the above like this:

    oiiotool in.exr --if "{TOP.nchannels < 4}" --ch R,G,B,A=1 --endif -o out.exr

The following slate of new fetures is added:

* `--set name value` sets a "user variable".

* Expression evaluation will expand identifiers that are the names of
  user variables. For example, `{i}` is replaced by the value of user
  variable `i`, and `{i+3}` returns 3 more than the current numerical
  value of `i`.

* Expression evaluation has been extended to support the following
  numerical comparison operators: `<` `>` `<=` `>=` `==` `!=` and
  `<=>` (the last one being the 3-way comparison, like in C++20).
  Also logical operators `&&` and `||`. All return 1 for true, 0 for
  false. Note that the comprison and logical operators have the same
  precedence as `+` and `-`, so use parentheses liberally to
  disambiguate complex mixed expressions.

* New functions recognized within expressions:
  - the value held by a named user variable: `var(name)`
  - logical negation: `!`, `not()`
  - string comparison: `eq()`, `neq()`

* `--if condition commands... [--else commands...] --endif`

* `--while condition commands... --endwhile`

* `--for variable range commands... --endfor` where the range may be,
  like Python, any of `end` (implied begin=0, step=1), `begin,end`
  (implied step=1), or `begin,end,step`.

Also needed to modify ArgParse so that it has the notion of whether
it's "running" -- actually calling the actions for each argument, or
if it's merely parsing but taking no action -- and to be able to set
and retrieve which command line argument index an action is responding
to.
2022-01-03 11:12:20 -08:00
Larry Gritz f705510f14 ImageBufAlgo: Slightly more flexibility in inferring constants (#3257)
This little change makes this work:

    ImageBufAlgo::add (buf, { 0.2f, 0.2f, 0.2f });

instead of the more awkward

    ImageBufAlgo::add (buf, cspan<float>({ 0.2f, 0.2f, 0.2f }));

and for anyplace tht has Image_or_Const parameter types.
2022-01-02 20:11:51 -08:00
Larry Gritz c66a532352 CI: Bump OCIO and fmt versions (#3258)
New OpenColorIO and fmt versions are out.

* Bump "latest releases" test to fmt 8.1.0, and OCIO 2.1.1.
* Re-adjust CI test fmt versions across many tests to give a better
  spread over the supported releases.
* Bump the default version to download and use if none is found to 8.0.0.
2022-01-02 14:50:25 -08:00
Larry Gritz 15f4da1f2a oiiotool --point (#3256)
We had --line (wrapping IBA::render_line) and --box (wrapping
IBA::render_box).

This adds the obvious --point, wrapping the existing IBA::render_point.
2022-01-02 10:48:51 -08:00
Larry Gritz 71c2d3da71 Python: improve ParamValueList and ImageSpec dict interface (#3252)
The Python bindings for ParamValueList and ImageSpec allow a "dict"
style (associative array) interface:

    imagespec["key"] = value
    val = imagespec["key"]

This patch makes some minor improvements:

* Clarify in the docs that like a regular Python dict, the associative
  retrieval will raise a KeyError if the key is not found.

* Add `__contains__` python method as a synonym for contains(), thus
  implementing `key in dict`.

* Add `__delitem__` python method as a synonym for erase(), thus
  implementing `del dict[key]`.

* Add an `ImageSpec.get()` method that is a synonym for getattribute
  (which retrieves the item or returns None or a default if not
  found), mirroring the behavior of Python's `dict.get()`.
2022-01-02 10:48:34 -08:00
Larry Gritz 1fe7bcd6a0 Python: implement ROI.copy() (#3253)
Somehow I never implemented a copy() method for ROI, which of course is
super useful if you want to make an actual copy of an ROI and modify
the copy.

I also realized that ImageSpec.copy() unnecessarily/incorrectly set
return_value_policy to reference_internal, but actually it should be a
real copy, which it has to be anyway because the implementation
creates a separate copy.
2022-01-01 11:55:51 -08:00
Larry Gritz 7deafc4718 oiiotool --pattern checker tweak and documentation fix (#3255)
* Docs: we previously only documented the "width=" optional modifier.
  Add height, color1, color2.

* Change behavior ever so slightly so that if the "height=" modifier is
  not supplied, the height defaults to the "width".
2022-01-01 11:41:51 -08:00
Larry Gritz af030f3b07 Docs: add missing Python docs for ImageBufAlgo.bluenoise_image (#3254) 2021-12-31 15:04:29 -08:00
Larry Gritz 9d6daca9be Python: ImageBuf constructor/reset from numpy array (#3246)
Deduce the ImageSpec from the shape and type of the ndarray, and
copy its contents into the ImageBuf.

Closes #2954
2021-12-31 15:04:03 -08:00
Larry Gritz 7d8fd72654 Docs: better C++/Python examples in ImageInput chapter (#3250) 2021-12-29 13:25:17 -08:00
Larry Gritz ee146a8c3f CI: pybind11 version bumps (#3248)
* Use the new pybind11 v2.9.0 for 2022 and "latest" tests.
* Bump the default version built by build_pybind11.bash to 2.8.1.
* Adjust the pybind11 version used in many of the other CI tests, to
  give an even spread across versions, and to make each of the
  "vfx platform" CI tests use the pybind11 version that was available
  near the start of its repsective year.
2021-12-29 12:44:02 -08:00
Larry Gritz 3cf4e1b81e ImageSpec: allow getattribute("format") to retrieve the data type name (#3247) 2021-12-29 11:56:53 -08:00
Larry Gritz 84a61b11f8 ImageSpec: New constructors to accept string for data type (#3245)
For each ImageSpec ctr that takes a TypeDesc, add another one
that's the same but takes a string_view (which is just a simple
pass-through of the TypeDesc-from-string_view).
2021-12-28 09:56:37 -08:00
Larry Gritz 6b316f2d15 Docs: more C++/Python dual examples (#3244)
* Add Python examples comprehensively to the ImageOutput chapter.
* Clean up some of the C++ code, too, using more modern idioms.
2021-12-27 09:59:41 -08:00
Larry Gritz aeeb3e741b oiiotool internals: convert all error and warning to fmt style (#3240)
Also tagged Strutil and ustring::fmtformat as 'nodiscard', to produce
warnings if people call it and ignore the results. (As was the case in
my own bug that I tracked down in the course of this patch.)
2021-12-24 17:26:35 -08:00
Larry Gritz fe9d572160 oiiotool: allow all filtered ops to take highlightcomp= modifier (#3239)
When doing operations with filters that have negative lobes, you can
sometimes get visible ringing artifacts in very high contrast regions
of HDR images (you tend not to see these artifacts in images that have
range [0,1] because the ringing is very low amplitude unless the input
is very large).

You can do "highlight compensation" to reduce the artifacts when they
occur by doing --rangecompress, which does a log transform on the
input, then the filtered op, then --rangeexpand to transform back to a
linear space. But that makes for kind of verbose and clumsy command
lines, and makes it easy to err by doing the transforms in the wrong
sequence or omitting one.

The -otex command takes a highlightcomp=1 modifier, which does this
bracketing automatically, foolproof, with a compact notation.

This patch adds support for optional highlightcomp=1 modifier for all
of the oiiotool commands that let you specify a filter= option:
--rotate, --warp, --resize, --fit, and --pixelaspect.
2021-12-24 16:17:50 -08:00
Larry Gritz 399e1fad6e Docs improvements (#3238)
* Clean up intra-document section references.
* New explanations about input and output configuration hints.
* More code examples in both C++ and Python.
* Fix some formatting flubs.
2021-12-21 15:03:28 -08:00
Larry Gritz 88f2c26f25 Get rid of obsolete header (#3237)
This was an obsolete experiment in adding a C binding. We abandoned
this effort (a replacement will happen eventually), but this one file
was left behind when we intended to remove it all.
2021-12-19 15:41:26 -08:00
Larry Gritz 57fdf840b2 Improve error propagation from ImageCache to higher levels (#3233)
Errors encountered while reading tiles were getting lost as we used
ImageBuf::Iterator to iterate over an image. Have the iterator keep a
flag for whether it encountered an error, set to true if the
ImageBuf::retile indicates an error occurred during the read.

Also, some ImageCache errors might get lost on the way to
TextureSystem calls, fix that as well.
2021-12-16 11:24:26 -08:00
Larry Gritz 9792b753e0 Make texture system 64-bit safe for tile access (#3232)
TextureSystem is designed primarily for tiled images (typically 64x64
pixels each), but to handle untiled images, it just treats the whole
image as one big tile. That means for very large untiled images, you
might end up with one VERY large tile, and if the image is large
enough, the size and/or offset computations therein may overflow a
32 bit int.

This patch attempts to make all the offset computations in the texture
system be 64-bit safe.
2021-12-16 11:24:09 -08:00
Brady 8232c157b1 Fix the reference (#3234) 2021-12-14 18:19:14 -08:00
Larry Gritz e4cf482bf2 IOProxy cleanup -- use new helper methods for TIFF, DPX, and PNG. (#3231)
After setting up the new IOProxy helper methods for ImageInput and
ImageOutput, here we go back to the readers/writers that had used
proxies for a long time, and switch them to using the new helpers.
2021-12-14 10:41:36 -08:00
Larry Gritz d1ec7624bf Protect against corrupt headers with image size and channel limits (#3230)
Add two new global OIIO attributes: "limits:channels" and
"limits:imagesize_MB" which are imposed limits for validating a
reasonable number of channels and total uncompressed image size,
respectively. We presume that an image file header describing an image
that purports to exceed these is most likely corrupted or even
maliciously crafted. The limits, therefore, are designed to avoid
crashes, absurd memory allocations, or other cascading errors that
would result from taking such a claim at face value (for example,
a file that appears to have tens of thousands of color channels).

The limits default currently to a maximum of 1024 color channels, and
a maximum uncompressed data size of a single 2D image to 32GB.  These
seem reasonable today, but if such large sizes become likely to be
seen in the wild in legit files in the future, we may change the
defaults. They may be adjusted now simply by setting the attributes,
of course, as should be done by applications that legitimately expect
to see input that exceeds them. (Applications also may make the
validation limits even smaller if they wish.)

I've modified the TIFF reader to check these limits as a first step.
We'll expand to doing such validation checks on other readers over time,
as we have opportunities to visit them.
2021-12-14 10:41:08 -08:00
Larry Gritz 9e897fe9a0 Strutil::edit_distance() (#3229)
This string utility computes the "edit distance" between two strings.
Currently it only uses the Levenshtein metric, but it has room for
future expansion by taking a parameter that can specify which metric
to use. Levenshtein is an algorithm for computing how many single
character insertions or deletions are necessary to turn one string
into the other.

I have a few ideas for where this can be useful, but as one
demonstration, I also modify the ArgParse class internals so that if a
command is not found, it will print a suggestion naming the valid
command option that has the closest edit distance (but only if one
choice is <= 2 edis away, and only if it's not a single-character
option, in order to reduce the number of useless suggestions). Here's
its behavior in action:

    $ iinfo --stat foo.exr
    iinfo error: Invalid option "--stat" (did you mean --stats?)
    ...
2021-12-14 10:40:19 -08:00
Larry Gritz bfd99269f7 CMake: don't download missing test data if BUILD_TESTING is off (#3227)
Fixes #3189
2021-12-12 22:38:32 -08:00
Larry Gritz 43a8dbbed8 IOProxy support for JPEG2000 (#3226) 2021-12-10 12:45:01 -08:00
Paul Melis 3bd9e44796 Mention that git is needed for certain dependencies (#3228)
... if they cannot be found and are installed from source as part of the build process.
2021-12-10 11:31:05 -08:00
Larry Gritz 0541331cdb JPEG2000: enable multithreading, other fixes (#3225)
* The main event here is that we're now telling OpenJPEG to use
  threading when compressing/decompressing JPEG-2000 files.  This
  improves the speed of JPEG-2000 reading on my laptop by 2-3x!  The
  threading feature was added to OpenJPEG 2.2 for decode, and 2.4 for
  encode.

* CI: Build OpenJPEG 2.4 for the "latest releases" test, and build
  their master for our "bleeding edge" test.

* Fixes to deal with the in-progress 2.5 deprecating a struct field.

* Generally clean up our detection of what OpenJPEG version we are
  using.

* Some clean-up of the FindOpenJPEG.cmake file, use PATH_SUFFIXES.
2021-12-09 23:01:50 -08:00
Larry Gritz 794ec616b5 IOProxy support for BMP (#3223) 2021-12-09 12:20:03 -08:00
Larry Gritz 70f7991c5b Webp IOProxy support (#3224) 2021-12-09 11:48:36 -08:00
Larry Gritz d3521a3d37 Docs: touch-ups to maketx argument explanations 2021-12-09 10:23:10 -08:00
Larry Gritz 8f1e33b611 Targa: add IOProxy support (#3221) 2021-12-08 17:08:23 -08:00
Larry Gritz b74a2e9523 Refactor PSD input to support IOProxy (#3220) 2021-12-08 17:08:08 -08:00
Larry Gritz 85768195e5 PNM overhaul to support IOProxy (#3219)
Also fix longstanding bugs in PNM input:
* We weren't correctly emulating random scanline access, as is expected
  (but in practice rarely used) of all ImageInput implementations.
* We weren't marking the color space in any way, now we do mark as
  "Gamma2.2", which is the correct/preferred interpretation according
  to the PNM spec.
2021-12-07 16:15:33 -08:00
Larry Gritz c4d9b6e66d hdr overhaul (#3218)
* Add full IOProxy support to both input and output.

* This necessitated a major refactor, including sucking the I/O specific
  code from rgbe.{cpp,h} into hdr{input,output}.cpp and getting rid of
  the old files.

* Add a testsuite entry for hdr (shockingly, there was none before)
2021-12-07 16:15:10 -08:00
Larry Gritz 3e9cbd1950 DDS input IOProxy support (#3217)
As well,

* Add a DDS test, apparently we never had one.
* Remove DDS setting of "texturetype", we don't ever use that, it's only
  "textureformat" that we use. Not sure how that crept in there years ago.
2021-12-07 14:22:26 -08:00
Larry Gritz 36bfeb6694 Minor ImageInput/ImageOutput IOProxy handling tweaks: (#3222)
Helper functions ioproxy_opened() and iotell() should have been const
all along, since they just return back information and should not
change state of the proxy, and also ioproxy() should have both const
and non-const versions.
2021-12-07 14:21:52 -08:00
Larry Gritz 6cfba204be CMake: use the more compact TARGET_NAME_IF_EXISTS (#3215) 2021-12-07 10:13:12 -08:00
Larry Gritz 6d0c98e516 Build/CI openvdb tweaks (#3216)
* On Mac CI, use openvdb from Homebrew now that it's OpenVDB 9, which
  properly supports OpenEXR/Imath 3.1.

* Update our FindOpenVDB.cmake target names to match the names used in
  OpenVDB's own FindOpenVDB.cmake (even though we don't use their module,
  may as well stick to their convention, especially if they eventually have
  a properly exported config file).
2021-12-07 10:08:09 -08:00
Larry Gritz 91b60106e7 Name gamma-corrected color spaces "GammaX.Y" (#3202)
For some reason, in the early days I got in the habit of having OIIO
input readers call their color space "GammaCorrected2.2" (for example)
when they appeared to be a straight-up gamma. (Generally only used for
certain fairly old formats that date from before sRGB existed.)

But there appears to be a widely used convention of naming OpenColorIO
spaces "GammaX.Y", so I'm switching OIIO to conform that
convention. It's more straightforward and increases the chances that
it will match the names of color spaces that already exist in people's
OCIO configs.
2021-12-07 10:07:32 -08:00
Larry Gritz 5bf288be33 Better IOProxy support for image format implementations (#3203)
As we move toward fully equipping all image format implementations
with full IOProxy support, it's clear that a lot of repeated code is
error-prone. I first tried to collect this in a mixin class, but then
re-implemented after realizing that we can use the existing PIMPL
ImageInput::Impl and ImageInput::Impl classes, without changing any
ABI or making new headers.

This patch add a couple data members to the Impl data -- an
`IOProxy*`, (the current proxy, used for both passed-in and created
proxies) and also a `unique_ptr<IOProxy>` used when we have to create
our own and want to make sure it's destroyed with the ImageInput or
ImageOutput.

Then we add a number of protected member functions to ImageInput and
ImageOutput, not meant to be ever called by "users" of the OIIO APIs,
but used internally by II's and IO's to encapsulate several common
tasks related to managing IOProxy's.  This coalesces redundant code
that would need to appear separately in most of the plugins that
support IOProxy, helps to reduce cut-and-paste errors from having to
make these changes separately in many places, and centralizes the
logic so that as our ideas of how to implement IOProxy evolve, we can
easily change it in just one place and have it apply to all plugins.

GIF revise with new IOProxy utility methods

JPEG simplify with new IOProxy utilities.
2021-12-04 23:05:01 -08:00
Larry Gritz f423cde454 Build: Make sure to use tbb target if it exists (#3214) 2021-12-04 12:31:07 -08:00
Larry Gritz 1fe77f312b Refactor ImageBuf::Iterator, ConstIterator (#3195)
To try to combat long template instantiation times, did some refactoring
on the ImageBuf iterators:

* Pushed more functionality from the templated Iterator and
  ConstIterator to the non-templated base class IteratorBase. This
  should reduce the amount of code that is separately instantiated for
  every data type, in every module that uses iterators.

* Pushed many implementations from inline defined in imagebuf.h to
  separately compiled in imagebuf.cpp. The most important methods that
  are called on every pixel are still inline, but we are switching to
  separate compilation for all the methods that are only called upon
  construction (once per image being iterated over) and most of the
  code that is called only when we wrap to the next scanline.

* Some other miscellaneous refactor to remove redundant computation in
  those classes.
2021-12-03 20:27:23 -08:00
Larry Gritz 08e86b795d Use a project-specific var for whether we're running in CI (#3211)
Maybe somebody else is building this as a subproject or has a varible
called "CI"?

* For our CI runs, set an env variable "OpenImageIO_CI" (not just
  generic "CI").

* Make sure STOP_ON_WARNING is true for our CI runs, even for release
  branches -- but now check OpenImageIO_CI, not CI, in case somebody
  else has set that.
2021-12-03 20:25:38 -08:00
Larry Gritz 59ef613b90 fmath.h: bit_cast specializations should take refs, like the template (#3213) 2021-12-03 20:19:52 -08:00
Larry Gritz e481e40dc2 Testing: Gracefully handle failing to find git for test data download (#3212)
Fixes #3208
2021-12-03 13:34:21 -08:00
Larry Gritz ffe7c190c1 Fix typo 2021-12-02 17:06:04 -08:00
Larry Gritz e582e2e166 Restore code that finds Jasper when using static libraw (#3210)
This was deleted a few months back, but I think I did not realize
it still served a purpose. We don't use JasPer directly, but LibRaw
does, so if we are using static LibRaw, we still need it here.

Fixes #3209
2021-12-02 10:01:12 -08:00
Larry Gritz 028582817c Add documentation for new texture CDF options (#3206)
Also, fixed the fact that direct calls to make_texture() were not given
proper defaults for the cdfsigma and cdfbits options.

Related to PR #3159
2021-11-29 21:39:02 -08:00
Larry Gritz 5563aec0e5 make_texture()/maketx fix to channel name with monochrome_detect (#3205)
When the make_texture option monochrome_detect is used to collapse 3
identical channels to 1, it was leaving the first channel name in
place (for example, "R"). That was confusing, because at this point,
we're not trying to represent a red image, we're trying to represent a
grayscale image. A strategic call to `default_channel_names()` clears
it up, imposing the standard "Y" we use for a single channel luminance
image.

Also amended the documentation of IBA::channels(). It turned out not
to be the way I called channels() that was the problem here, but by
the time I figured that out, I had already seen that its docs could be
improved.

Fixes #3204
2021-11-29 21:17:28 -08:00
olegul 78a67fe6a0 Add support for writing Gaussian forward and inverse transform lookup tables (#3159) 2021-11-29 09:52:01 -08:00
Larry Gritz f0ac3e1022 imageinout_test debugging aids (#3201)
* --onlyformat or env IMAGEINOUT_TEST_ONLYFORMAT to test only one format.
* --no-delete to preserve the temporary files for inspection
* other debugging checks
2021-11-29 00:04:45 -08:00
Larry Gritz 9aca017113 DDS: add test, minor adjustments (#3200)
* Add a DDS test, apparently we never had one.
* Remove DDS setting of "texturetype", we don't ever use that, it's only
  "textureformat" that we use. Not sure how that crept in there years ago.
2021-11-29 00:04:22 -08:00
Larry Gritz 963b5673d2 filesystem.h: New write_binary_file utility template (#3199) 2021-11-28 22:01:42 -08:00
Larry Gritz df77c3fcfc Fix typo 2021-11-28 00:22:37 -08:00
Larry Gritz f2ae8a594e IBA::maxchan(), minchan(), and oiiotool --maxchan / --minchan (#3198)
The previously existing max and min take 2 images and compute the
pixel-by-pixel, channel-by-channel max or min of the two images.

The new maxchan/minchan take one multi-channel image and produce a
single-channel image where each pixel contains the max or min of the
*channels* of the corresponding pixel of the original image.

It is equivalent to this (for an RGB image):

    oiiotool in.exr -ch R in.exr -ch G in.exr -ch B -max -max -o max.exr

Except, of course, that --maxchan is a single command, is much more
efficient, and doesn't require you to know the number or names of the
channels of the input.

This was a specific user request.

Note: in the course of making the tests, I noticed that we did not
have documentation or testsuite coverage of the python bindings for
IBA.min() an max(), although they were implemented. So I added that as
well.
2021-11-27 10:22:25 -08:00
Larry Gritz 0a69fa3ceb CMake tweaks (#3197)
* Make PROJECT_VERSION_RELEASE_TYPE be a cache string, so individual
  build configs or sites can override it.

* Change OpenImageIO_IS_SUBPROJECT to PROJECT_IS_TOP_LEVEL (and with
  the opposite sense), to match CMake 21+ behavior. And no need to set
  it ourselves if using cmake 21+.
2021-11-27 10:21:57 -08:00
Larry Gritz bc4685ccdd oiiotool --repremult (#3192)
ImageBufAlgo has both premult and repremult (as well as unpremult).
But oiiotool only exposed unpremult and premult, but not repremult.
This little patch rectifies that oversight.

Just to remind everybody of the difference:

`premult` just multipies the color channels by alpha, like it says.
Note that for a pixel that has Alpha = 0 but nonzero color, this will
crush the color to black.

That's fine if you have an *original* image that's unpremultiplied and
you want to do a one-time conversion to premultiplied.

But there's another use case, which is when you start with a
premultiplied image, you need to temporarily unpremultiply it (like
for a color space conversion), and then re-premultiply it. In that
case, you may have those glowing pixels in the original image, the
unpremult will preserve them, and you DO NOT want to crush them to
black with the subsequent premult.  So there is a "repremult"
operation that's like premult, but preserves the color values when
alpha == 0. This is the preferred operation when you are doing the
sequence of "unpremult, do something, re-premult" so that the glowing
pixels make it through the round trip.
2021-11-22 23:25:56 -08:00
Larry Gritz d4da1fde87 Fix to oiiotool --invert : avoid losing the alpha channel values (#3191)
When I implemented `oiiotool --invert`, I knew that the default should
be to only invert the first three channels (presumably R,G,B) and not
anything beyond, because we wouldn't want to invert the Alpha channel.

But I botched it, and instead what happened is that if given an RGBA
image, it would just leave the A black in the result image.

So this patch has two improvements:

1. If there are more channels in the source image than we are
   inverting, make sure to copy the other channels unmodified, don't
   just leave them blank.

2. Allow optional modifiers chbegin= and chend=, so users can change
   the default if they want a different channel set to be inverted.
2021-11-22 23:24:54 -08:00
Larry Gritz 9206e45256 IBA::saturate() and oiiotool --saturate (#3190)
This new IBA/oiiotool command adjusts the saturation of a color image,
with a scale factor. Scale = 0 makes the image gray scale of
equivalent perceptual luminance, scale = 1 leaves color unchanged,
scale > 1 increases color saturation.
2021-11-22 23:24:23 -08:00
Larry Gritz 81aebd2f56 Build: option to time individual compile commands (#3194)
This adds a new cmake variable in our build system, TIME_COMMANDS,
that when set ON will adjust the compile and link rule launch to
include a time command. This is probably only useful when also setting
`CMAKE_BUILD_PARALLEL_LEVEL=1` so that build are happening serially.
The use case is to investigate how long each module takes to compile,
for optimizing the build.
2021-11-22 00:20:45 -08:00
Larry Gritz 85acf8b250 CI enhancements: MacOS 11, other updates (#3193)
* Add a test for MacOS 11
* Updated supported versions of dependencies
* Move linux clang test to clang13 on vfx2022 container
* Switch clang-format test to use clang12
2021-11-22 00:20:21 -08:00
Larry Gritz 1217102b0f GIF full IOProxy support (#3181) 2021-11-20 18:02:12 -08:00
Larry Gritz 32e00ada6a JPEG output IOProxy support (#3182)
IOProxy was already supported for JPEG input.
2021-11-19 23:41:43 -08:00
Larry Gritz 717b0bb175 Expand the list of TERM values supporting color (#3185) 2021-11-19 20:39:53 -08:00
Larry Gritz 82c7a5af94 Raise ImageCache default tile cache size to 1GB (#3180)
In the early days of OIIO, it was 100MB. Ten years ago, we bumped it
to 256MB. I've heard a rumor that computer memories have grown in the
last 10 years, and so have the size of images some people deal
with. So it seems reasonable to raise it to 1GB.
2021-11-19 20:37:52 -08:00
Larry Gritz 4b6bffafc9 Banish sscanf (#3178)
`sscanf()` still has locale-dependent behavior that we wish to avoid
because it can lead to subtle bugs for people whose machines are
configured for certain locales.

This patch removes from the OIIO codebase almost every remaining
sscanf use (and definitely every one that could harbor locale bugs).
Instead, we use the rich set of parsing functions we've added to
Strutil over the years, which are locale-independent, and in most
cases are also faster than the standard C/C++ equivalent.
2021-11-19 20:37:16 -08:00
Larry Gritz f046c42ee1 TypeDesc ctr from string: accept "box2f", "box3f" (#3186)
The official names we use are "box2" and "box3", but users of Imath
know these as box2f/box3f, so accept these as synonyms when
constructing a TypeDesc from a string.
2021-11-17 16:42:54 -08:00
olegulandOle Gulbrandsen da21b7a98e SPI Specific: default to LLVM 12.0.1 (#3187)
Co-authored-by: Ole Gulbrandsen <ogulbrandsen@imageworks.com>
2021-11-17 15:06:22 -08:00
cmstein 3092639295 adding host/device attributes to make TypeDesc methods GPU device-friendly (#3188) 2021-11-17 15:04:32 -08:00
Larry Gritz 476c02eb92 Fix docs/behavior with webp "LoopCount" (#3183)
* Typo in webp section -- said "gif:LoopCount" when we meant
  "webp:LoopCount".

* In the code, did not actually set the "oiio:LoopCount" metadata
  that the docs said would be set.

* Opportunistic fix: TIFF docs said we only suported IOProxy for input,
  but we have supported it for output for a while now.
2021-11-15 21:31:42 -08:00
Larry Gritz 985bda763a Strutil::parse_line (#3177) 2021-11-11 21:14:53 -08:00
Brecht Van Lommel 4f97ff6eef Fix excessive memory usage when saving EXR file with many channels (#3176)
Scratch memory allocation in ImageOutput::to_native_rectangle was using
the number of channels squared.
2021-11-11 13:25:55 -08:00
Larry Gritz 974f79b6aa Strutil: add new utilities for parsing values out of strings (#3173)
* `parse_values()` and `scan_values()` both can parse a series of
  values in a string, with optional prefix, suffix, and separator. The
  scan versions just figure out the values, the parse versions
  optionally can update a string_view& like the other parsing
  functions in Strutil.

* `scan_datetime` parses the int components of a string that looks like
  "YYYY:MM:DD hh:mm:ss" (and a few minor variants).

* Fix stoui -- it was previously casting stoi results, which is not
  correct.

* Add `from_string<>` specialties for `double`, `int64_t`, `uint64_t`.
2021-11-10 13:45:03 -08:00
Larry Gritz ba1d19dd74 SPI specific: updates to versions used by Makefile-bits 2021-11-08 11:44:28 -08:00
Larry Gritz e09a2e66bd oiiotool: better detection of file reading failures (#3165) 2021-11-07 18:07:07 -08:00
Larry Gritz b65412c22b oiiotool: Fix bug autocropping to positive area for all-negative data (#3164)
When outputting to formats that don't support negative pixel origins
(such as JPEG), we crop away the negative areas. But we did not
consider the case where the entire data window was in the negative
region!
2021-11-07 18:06:50 -08:00
Larry Gritz 1b22597371 RLA input: guard against malformed input (#3163) 2021-11-07 18:01:50 -08:00
Larry Gritz 429883dc88 Targa: more safety for corrupted files (#3162)
* Check for palette mode files that don't supply a color map.
* Fix implementation bug in handling x flipped images.
2021-11-07 14:38:48 -08:00
Larry Gritz 60e3ea8c28 tiff output: switch to "bigtiff" for really big images (#3158)
TIFF has an absolute limit of 4GB file size due to use of uint32
offsets within the file. If you try to write a big enough TIFF image,
it will fail. This is not a software problem, it's a limitation of the
original TIFF file specification itself.

The underlying libtiff supports a nonstandard "bigtiff" extension that
uses 64 bit offsets. This patch switches to this automatically for
images whose uncompressed size would get too close to (or exceed) the
4GB limit.  Any such files can be read by OIIO-based software, as well
as anything else using a relatively modern version of libtiff, but may
not be readable by independent TIFF reading implementations.

This is a mixed bag, though. On one hand, this at least lets us write
files that would have been an error before.  But note that some files
that would have worked as classic TIFF before -- because their
*compressed* size was still under the 4GB limit, even if their
uncompressed pixel size was not -- will now be written as bigtiff
because we have to commit at the time we open the file, before we've
seen the pixels and know the final compressed size.  We just can't
know for sure, for an image with > 4GB of pixels, if the file will get
lucky and be below the limit by the time the scanlines or tiles are
compressed.  So for those files, not all apps will be able to read
them (though anything using libtiff >= 4.0 or OIIO will be fine).

Fixes 3156
2021-11-07 08:21:53 -08:00
Larry Gritz 152f6c8849 New global OIIO attribute: "try_all_readers" (#3172)
When ImageInput::create() or open() is called, it first uses the
extension of the filename to guess which reader plugin to try (for
example, "foo.jpg" will try the jpeg reader). If that fails, however,
the default behavior is to then try EVERY reader to see if any will
open the file, in case it guessed wrong, or the extension is used by
more than one format, or the file was simply given the wrong
name. Thus, ultimately, OIIO will never fail to open a valid image
file in a known format, even if the file is wildly misnamed. However,
it's a lot faster to open a correctly named file, because it will try
that one first, before trying a long succession of readers in the hope
that eventually one will work.

There are three cases where this is not the desired behavior:

1. You are confident that files are named with the correct extensions,
and you want a corrupt or invalid file to fail QUICKLY, without trying
every format reader.

2. If the file is corrupt, rather than see a generic "Could not find
any format reader that will open the file" because they all failed,
you want to see the more specific error message for why the (presumed)
correct reader could not succeed.

3. When doing regression tests to make sure that sample corrupted
files are correctly reporting the right errors, we really do want to
see error messages from that one reader we are testing.

This PR exposes a global OIIO attribute, "try_all_readers", which
defaults to 1, but when set to 0, changes the behavior so that ONLY
the one format implied by the file extension is tried, and OIIO does
not subsequently try every known reader.
2021-11-07 08:21:30 -08:00
Larry Gritz eae19db2f9 oiiotool --oiioattrib (#3171)
This new oiiotool command lets you set global OIIO attributes, i.e.,
making calls to OIIO::attribute(). It allows oiiotool command lines to
set some additional OIIO-wide options for which no specific oiiotool
command flags could otherwise access.
2021-11-05 00:13:00 -07:00
Larry Gritz e058dc8c4a Fix per-file boilerplate to just link to the github project (#3170)
Not the specific license file. Users can find that. Better to use
the project link. I'd been meaning to do this for a long time.
2021-11-04 09:51:41 -07:00
Rémi Achard 26cd4113c2 Fix identifier not found error on MSVC (#3168)
Signed-off-by: Rémi Achard <remiachard@gmail.com>
2021-11-03 16:27:56 -07:00
Larry Gritz 3850e29ed6 CI: OCIO has renamed its master branch to main (#3169) 2021-11-03 13:20:34 -07:00
Larry Gritz 4c1bdfefbd build_libtiff.bash: Allow override of build type (#3161)
Also make the default version of libtiff we build be the current 4.3
2021-11-03 09:59:08 -07:00
Larry Gritz 25bbb7fa7f Update to newer stb_printf for our implementation of vsnprintf (#3160)
Solves some security problems and/or just false positives in
address sanitizer.
2021-11-03 09:58:49 -07:00
SebTV 022d42a871 Fix Typo that prevents setting Compile Definitions (#3167) 2021-11-03 09:58:17 -07:00
Larry Gritz 91bc398073 exr output: Support new OpenEXR zip compression level choices (#3157)
When building against OpenEXR >= 3.1.3, exr output now allows zip/zips
compression to take a quality metric (such as compression
"zip:4"). The range is from 1-9, 4 is the default, and it's a control
over speed of compression vs compression ratio (higher number is more
expensive but may result in smaller files). This only affects
compressed output -- it's lossless and will be read to the same pixel
values upon input.

This is also incentive to upgrade to OpenEXR >= 3.1.3, because its new
default (and ours) is 4, versus the old (implied, not directly
controlled) 6. This change was made because compared to 6, it's
significantly faster to write exr files with zip compression 4 (tens
of % faster), while only increasing file size by 1-2%, so that seemed
like the right tradeoff. Lower numbers make much larger files for
little speed gain, and larger numbers than 6 make for much slower
writes of exr files for very tiny compression improvements. But YMMV
and you may want to experiment to find the right trade-off for your
use cases.
2021-11-01 23:06:47 -07:00
Larry Gritz 00a6c6023a CHANGES 2021-10-31 12:15:50 -07:00
Larry Gritz 71177ff402 Field3D deprecation part 2: Remove field3d support (#3151)
OIIO 2.3 marked it as deprecated. This new change is for master (2.4+)
only -- removing all support for Field3D.

F3d is effectively unmaintained, is known to be incompatible with
the latest versions of OpenEXR/Imath, and we haven't found anyone
prepared to speak up as a user of it via OpenImageIO support.
2021-10-31 12:14:07 -07:00
Larry Gritz 5c89335ddc Rewrite Filesystem::searchpath_split to remove boost::tokenizer (#3154)
One more boost extraction:  tokenizer.

The only place we used it is Filesystem::searchpath_split, which can
easily be rewritten in terms of the Strutil parsing functions.
While I'm at it, add a new version that returns the vector instead
of needing to pass in a ref.
2021-10-29 21:28:20 -07:00
Larry Gritz 04293edaa3 Stochastic mipmap interpolation (#3127)
Suggested by Luke Emrose, the idea here is that we introduce two new
MIP interpolation modes: StochasticTrilinear and StochasticAniso.
These work similarly to Trilinear and Aniso, respectively, except that
instead of sampling both of the bracketing MIP levels and blending
between them, in stochastic mode we use a random variate to select ONE
of the two MIP levels with probability proportional to the computed
blending weight.

If these mip modes are used, the caller needs to pass a
well-stratified value in the new "rnd" field of TextureOpt. Also note
that the method only really makes sense in the context of a renderer
that is using many samples per pixel. As a single texture lookup, it
looks horrible and noisy, as you can see by the testshade-based tests
we do of this, which are 1spp and looks pretty rough.

My benchmarks (in a hard stress test of the texture system using
`testtex --threadtimes 8`) show that this approach has speedups of
35-40% when using between 1-4 threads, dropping to more like 25-30%
speedup as threads are in the 12-32 range (that makes sense, it's
doing the same amount of total I/O).

In this first implementation, in order to preserve ABI compatibility
if we decide to backport this feature to the release branch,
TextureOpt::rnd is added as a union co-member with the unused "bias"
field. For TextureOptBatch, we had to add it outright, but it's
guarded by an `#if` and will not be backported to 2.3. (We may change
our minds and not backport it at all, I just wanted to leave the
option open with this initial patch. Also, there will probably be
additional further ABI-breaking changes coming later that will
definitely not be backported.)

In this first phase, we only use the stochastic component to turn the
2-MIP-level lookup into one level lookup.  It has been further
suggested that we could apply stochastic techniques to anisotropic
filtering (instead of many samples spaced across the major axis of the
filter footprint, take one sample distributed across the axis), and
even for the ordinary bilinear or bicubic within each level (instead
of 4 or 16 weighted texels, just retrieve one texel chosen with the
weights as probabilities). But these deserve to be benchmarked and
have their quality evaluated separtely and deliberately, and so will
be relegated to a later investigation and implementation.
2021-10-28 14:02:52 -07:00
Larry Gritz b8f25e0541 Remove the last vestiges of the experimental C API (#3144)
We will have a C API eventually, but it will be implemented
differently, and this cruft will probably get in the way. If the new
code needs any of this (particularly the test cases), it's easy enough
to revive it from the project history).
2021-10-27 21:24:58 -07:00
Larry Gritz 3f0e12a822 raw: fix ProPhoto gamma, add ProPoto-linear (#3153)
When requesting that raw image be returned as "ProPhoto" color space,
we were using the wrong gamma. Also, at user request, add
"ProPhoto-linear", which is the same but with linear response. (This
is analogous to the existing "sRGB" and "sRGB-linear".)

Fixes #3152
2021-10-27 21:22:22 -07:00
Larry Gritz fff364ffce Fix bad alignment and simd assumptions in fill_gray_channels (#3145)
Thiago Ize points out that TextureSystemImpl::fill_gray_channels
assumes that the `float*` addresses it is passed are big enough for
a vfloat4, and also properly aligned as such. Not true.

This is an edge case anyway, only called in particular cases where
we are doing 3/4 channel lookups on 1/2 channel files with the option
turned on to expand single channel gray to RGB gray, and also doesn't
do enough SIMD to have a perf impact. So just recode as scalar and
have no more alignment mismatches to worry about.

Also make sure at least one of the Windows CI tests is explicitly
turning SSE on.

Fixes #3128
2021-10-27 21:21:27 -07:00
Larry Gritz 3715f15ce7 docs: formatting fixes 2021-10-24 22:40:33 -07:00
Larry Gritz 4cde5b72b9 Field3D deprecation -- stage 1 (#3140)
Field3D is essentially unmaintained, and is currently incompatible with
OpenEXR/Imath >= 3.

In this first stage (which will apply to OIIO 2.3):

* By default, Field3D support is disabled. To enable it, you must
  invoke CMake with `-DENABLE_FIELD3D=1`. No warning or other messages
  are printed by the build configure step when not enabled.

* If requested, but an incompatible OpenEXR is found, it will be disabled
  with a clear error message.

* If requested and enabled, a warning will be printed indicating that
  Field3D support will be removed from future versions (2.4 and beyond).

* Add a new test, texture-texture3d, that provides the same testing that
  texture-field3d did, but with openvdb.
2021-10-24 12:07:10 -07:00
Larry Gritz a844c7a0ed Improvements related to image dithering and low-bit-depth output (#3141)
We have options that allow adding random dither to images before
output, which when converting float images to 8 bit or less, can
greatly reduce the appearance of banding artifacts. This PR makes a
number of improvements:

* When the option is used, it should apply dither any time you are
  reducing an image with > 8 bits/channel to an output with <= 8
  bits/channel. Not just from float/half, but also from uint16, for
  example. (When outputting > 8 bits per channel, there are enough
  gradations that you tend not to see banding artifacts, so dithering
  is not necessary for 16 bit output, even if coming from a float data
  source.)

* Change the actual dither we use to blue noise. The old dither just
  used a hash to add uniformly distributed random numbers to each
  pixel value before quantization, completely uncorrelated from pixel
  to pixel. Blue noise is specially constructed to still have a
  uniform distribution of the output range, but it ensures that
  spatially, similar values are distributed as far away from each
  other as possible, rather than having similar values sometimes
  clumped together.  The result is a MUCH NICER appearance.

* Of course, this means the we needed to store a blue noise table in
  the library, and some access routines for it. We incorporate a
  public domain blue noise texture as a table.

* ImageBufAlgo::noise() and `oiiotool --noise` now take "blue" as a
  noise name to return blue noise. Also, make "white" the (preferred)
  synonym for "uniform" (to disambiguate the fact that both white and
  blue noise are uniformly distributed; the difference is that white
  is independently random for each pixel, whereas blue shapes the
  spectrum to favor high frequencies, making it better suited for
  dithering and sampling purposes.

* ImageBufAlgo::bluenoise_image() returns a reference to a stored
  periodic blue noise image.

* oiiotool -d would let you say "uint10" or "uint12" to indicate 10 or
  12 bit output (for formats that support it), but had no way to ask
  for less than 8 bit output (for example, TIFF supports that). So we
  add "uint6", "uint4", "uint2", "uint1" as recognized names for the
  `-d` option in those rare cases when you specifically want to
  produce a low bit depth file. And furthermore, if you ask for
  `--dither` when using lower bit depths, the dither amplitude is
  adjusted to be right sized for the bit depth you are using.

* Many format output modules that support 8 bit output honor the
  option to dither the output, but in the "built-in plugins" chapter
  of the docs, most did not list this option in the section that
  describes which special output options it knows. So now we've added
  this to the docs for all the output plugins that did support it.
2021-10-24 11:27:03 -07:00
Larry Gritz 77ff294664 Fix copy/paste error in ImageCache docs for 'failure_retries' attrib (#3147) 2021-10-24 11:25:30 -07:00
Larry Gritz c3cf7b9c08 heif: Handle unassociated alpha (#3146)
Turns out that heif files that contain alpha can have either
associated or unassociated alpha. We had been assuming
associated. With LibHeif 1.12 and beyond, you can ask, so now we
do. Thanks Frédéric Devernay for pointing this out.

Similar to other formats that optionally have unassociated alpha:

* The default behavior is to associate/premultiply automatically when
  reading, but set metadata "heif:UnassociatedAlpha" to indicate that
  it was unassociated in the file.

* Open configuration hint "oiio:UnassociatedAlpha", when nonzero,
  means to please keep the data unassociated and not premultiply. In
  that case, metadata "oiio:UnassociatedAlpha" will be set in the
  ImageSpec to indicate that the returned image (not just the file)
  consists of unassociated values.

I did a couple other minor docs touch-ups while I was at it.

Fixes #3129
2021-10-24 11:04:48 -07:00
Larry Gritz 6507724330 raw: Fix compat break in their 202110 snapshot (#3143) 2021-10-23 12:58:13 -07:00
Larry Gritz fb55e52843 [docs] Add an oiiotool example of putting a border around an image (#3138) 2021-10-21 23:46:13 -07:00
Larry Gritz f749be7bd3 oiiotool --dumpdata:C=name (#3136)
New ":C=name" modifier for --dumpdata will cause the dumped image data
to be formatted with the syntax of a C array, that can be dropped right
into source code.

    $ oiiotool --dumpdata:C=foo image.exr
    // image.exr       :  256 x  256, 4 channel, float openexr
    float foo[256][256][4] =
    {
      { /* (0, 0): */ { 0.517036676, 0.261921108, 0.017822538, 0.912108004 },
        /* (1, 0): */ { 0.653315008, 0.527794302, 0.359594107, 0.277836263 },
        ...
    };

Without this modifier, --dumpdata will keep the same formatting it
always had.

This works pretty well for ordinary boring flat, single subimage,
non-MIPmap images.  The option should probably not be used (or at
least is very unpolished) for multi-subimage, MIP-mapped, deep, or
other oddball cases (but you probably don't want to shove those into
a single C array anyway).
2021-10-21 23:46:01 -07:00
Larry Gritz 245ae961b1 cmake: Need OpenImageIO_SUPPORTED_RELEASE to be cache variable (3142)
I have a reason for needing to be able to override it on the command
line when we do a cmake config step.
2021-10-21 23:45:03 -07:00
Brad Smith 713b78d18b Sysutil: improvements to NetBSD and OpenBSD support (#3137) 2021-10-18 00:45:32 -07:00
Brad Smith b4787213e3 Fix building with Clang on big endian archs (#3133) 2021-10-16 11:27:44 -07:00
Larry Gritz 0ecea4e275 Fix sometimes build breaks related to OpenCV headers (#3135)
Reclassify the OpenCV headers as "system" includes, which will turn off
warnings for things that show up in those headers that we can't control.
2021-10-16 11:16:12 -07:00
nick black c1997ddc3d [jpeg] remove debugging cruft (#3134) 2021-10-16 09:20:35 -07:00
Larry Gritz 7cc7a3a816 Fix broken oiiotool --dumpdata: botched a formatting string (#3131) 2021-10-14 22:34:34 -07:00
Larry Gritz e1060c3d2a Fix typo (#3130) 2021-10-14 22:34:15 -07:00
Larry Gritz 4f77d8b8d1 Replace Imath::clamp with OIIO::clamp (#3126)
We had long ago established that the one in fmath was a slightly
faster formulation, as well as having the property of squashing
NaNs. There were a few remaining places where we used a different
clamp so fix them.
2021-10-13 21:02:27 -07:00
Larry Gritz 23de7648fa Clean up src/doc/Makefile (#3124)
It was still by default referencing the old latex files that we've
long since removed.
2021-10-13 20:57:14 -07:00
Larry Gritz 99085de393 libraw: add new color space names (#3123)
The DSLR raw format reader has the ability to pass hints to the
underlying LibRaw requesting that the pixel data be returned to us in
particular color spaces.

* Add new supported color spaces "DCI-P3" and "Rec2020" when using a
  LibRaw new enough to understand them -- which means the upcoming 0.21.

* A new name to request the data be returned using sRGB color
  primaries but a linear response curve: "sRGB-linear".

* The old name we used for sRGB-linear, "linear", is now considered
  deprecated since it's ambiguous -- since its first use, new color
  spaces "ACES", "DCI-P3", and "Rec2020" have been added, all of which
  are also linear response.
2021-10-12 22:34:26 -07:00
Larry Gritz dea9b1fa7b Beef up error checking in Targa read (#3120)
When reading tga files, make sure that every seek and every read
checks results and issues error messages. Also double check that
large allocations succeed.

Also improve error propagation in several spot of iinfo, oiiotool
2021-10-12 22:33:55 -07:00
Larry Gritz 7745ac72b9 Address new warnings revealed by clang13 (#3122) 2021-10-10 10:24:30 -07:00
Larry Gritz 37e9ac2bae ci: Bump versions for the 'latest' tests (#3121)
* OpenEXR -> 3.1.2
* pybind11 -> 2.8.0
* On Windows, no longer vcpkg install boost regex, we no longer need it.
2021-10-08 20:12:03 -07:00
Larry Gritz 780fce4dc7 Use inline constexpr for C++17 (#3119)
Owing to our C++11 focus in previous years, we had a number of places
were constants were declared as `static constexpr`. When done in
headers, this potentially causes separate copies of those constants to
be instantiated in each module that includes the header. It's not
really harmful the way we're using it for small constand objects, but
it's wasteful to potentially have dozens of copies of each those
constants by having it repeated in each module.

C++17 has a new idiom, `inline constexpr` that is more like we want --
makes it a true compiler constant that doesn't get instantiated in the
memory of each module.

We still have to cater to C++14, and in platform.h we already had a
C++-standard-dependent definition of OIIO_INLINE_CONSTEXPR that was
almost correct. Fix it (it wasn't previously used, but I must have
seen this coming at some point) so that it expands to
`inline constexpr` for C++17 and beyond, but stays as
`static constexpr` for C++14, and then use it for these constants.

Fixes #3117
2021-10-05 16:12:43 -07:00
Larry Gritz b7f470b68f Guard against invalid UDIM tile numbering (#3116)
If think that our inventory of UDIM tile files won't find names with
wildly out-of-range tile indices, you haven't been working in a
production studio! When those indices imply tile numbers < 0, we were
running off the beginning of the vector when filling in the udim
table, to hilarious results.
2021-10-01 15:08:04 -07:00
Larry Gritz 4d50578d9c Allow quotes in oiiotool command modifiers (#3112)
Oiiotool::extract_options was kind of fishy and brittle before --
splitting the string at ':' characters, then split each piece (which
should form a `name=value` pattern) at the first '=' character. There
are probably many malformed option strings that would have had weird
results with the prior naive parsing method. And it has been noted
that it can't handle a value that is intended to be a Windows filename
(like "C:/foo"), nor a searchpath (like "/usr/bin:/usr/local/bin").

Rewrite to parse it more carefully as name=value pairs delimited by
':'. In the process, we now have the ability to have the value be
enclosed by a single or double quoted string, in which case the
contents of the quote may themselves contain a colon, for example, the
following command and modifier is now no longer a problem:
`--foo:filename='C:/blah':count=3:`
2021-09-29 18:26:54 -07:00
Larry Gritz 2fbdbf9d9d TIFF output: Honor zip quality request when we do our own compression (#3110)
We were already passing this on to libtiff when it handles the
compression.  But for the case where we were calling zlib ourselves
(to facilitate multi-thread compression, which libtiff doesn't do),
we were just using the default compression.

This is inspired by a great [blog post](https://aras-p.info/blog/2021/08/05/EXR-Zip-compression-levels/)
by Aras Pranckevičius in which he made a similar change to OpenEXR
and benchmarked the results. He reported approximately a slightly more
than 2x write speed increase, while getting files that were only around
2% larger.

I tried replicating his experiment for TIFF, and while I don't quite
get results as good as he did, it still is really interesting.  I
tested with 100 images randomly selected from the [Animal Logic Lab
USD scene](https://animallogic.com/usd-alab/) (they are almost all
4k^2, a mix of 1- and 3-channel images), converted from half exr to
uint16 TIFF images. I ran the tests for both scanline and tiled
images.

Compared to the default zip level 6, using level 4 resulted in 3%
bigger files, and around 40% faster write times. That seems like it
is a potentially very helpful tradeoff.

I tested the same set of images also with zip levels 8 and 2. For
level 8, the files were only another 2% smaller than the default level
6, but the write speed was 45-50% slower, so there is little value to
asking it to work harder on compression -- it just burns up time. For
level 2, it went somewhat faster (maybe another 10% faster than level
4) but the files started getting bigger, level 2 was 12% bigger than
level 6, that's definitely getting into territory where people might
mind the larger files.

So I want to add the control now, though I'm deferring a decision on
changing the default value until I can do some more extensive
tests. In particular, I would like to assess how it behaves with 8 bit
files (I was testing uint16, specifically), how well it works with
rendered images and with natural/photographic images (I was testing a
set of textures, which may not have the same characteristics), and
perhaps also see if results are better or worse for lower resolution
images.
2021-09-29 18:24:19 -07:00
Larry Gritz 7b0352b58a Add multithreading to exr core read_scanlines and read_tiles (#3107)
The old libOpenEXR/libIlmImf (default) implementation handled
multithreading on the exr side of things, inside the readPixels method.

The new (experimental, enabled only by option) OpenEXRCore
implementation leaves the threading to the caller, and we weren't
doing it, so the performance was unsurprisingly awful.

This patch turns the implementations of the exrcore-based
read_native_scanlines and read_native_tiles (and also the deep
versions thereof) to use parallel-for loops, restoring parallel
processing to the exr reader when using OpenEXRCore.

Reading of whole scanline and tiled images now is on par or slightly
faster (a few %) than when using the main OpenEXR library. Reading of whole
scanline and tiled deep images is substantially faster (2-3x!) than
before.

I did some extra refactoring while I was there, simplifying and
eliminating some redundant error handling and using a new
DecoderDestroyer utility class.

STILL TO DO:

* See the long comment at the end of read_native_scanlines -- the error
  message strategy implemented here is temporary, I'd like to improve it,
  will probably involve both some work here as well as on the openexr
  side.
2021-09-29 13:05:30 -07:00
Larry Gritz f8aca7b0d3 SPI only: Minor tweaks to the site file. 2021-09-29 11:10:57 -07:00
Larry Gritz 6197716bf9 Suppress OCIO console info output (#3113)
Make sure OCIO isn't spraying info messages at the console when we
first ask for a config.
2021-09-28 10:32:55 -07:00
Larry Gritz ee36fd5b91 Build: Add ENABLE_INSTALL_testtex option (#3111)
If set to ON, will include the testtex program in the install.
The default is OFF, which builds it for tests, but doesn't install it
with the real command line utilities.
2021-09-28 10:32:23 -07:00
Larry Gritz 6a339bc957 Bump minimum supported OpenEXR/Imath to 2.3 (#3109)
In forward looking code (current master means OIIO 2.4, which won't
be released until mid-2022), get rid of some stray logic catering to
OpenEXR releases 2.2 and older.
2021-09-28 10:31:40 -07:00
Larry Gritz 8de11b8d73 Build: fix over-eager use of targets (#3108)
Background: Old style CMake was to use FindFoo.cmake modules, which
set FOO_INCLUDES and FOO_LIBRARIES variables. Best new cmake practices
are for the upstream packages themselves to export a FooConfig.cmake
and friends, which set up cmake targets. Of course, many packages don't
provide exported configs, so we use the old Find modules for many of
our dependencies.

I've slowly been migrating our Find modules to set up targets in addition
to the variables, and favoring use of the targets over the variables.

But I was wrong about this. It's more than just a choice of style.
When targets are used, use of transitive linkage (especially for static
library versions of dependencies) make the dependency targets show up in
our own exported OpenImageIOConfig.cmake. But to a downstream package,
now our config talks about a target like Libsquish::Libsquish, but it
doesn't know what that is, and it doesn't have the FindLibsquish.cmake
module that we used (internally) when we found that dependency.

This was causing particular problems for Libsquish on Windows with
vcpkg, but I see now that this could be a problem elsewhere as well:
field3d, libheif, openvdb, and webp.

So this patch:

* Reverts from the ill-advised targets back to the old style
  variables, for the dependencies where we use *custom* Find modules.
  (We presume that a dependency's exported configs, as well as any
  Find modules that are distributed as part of CMake itself and define
  targets, are done correctly, and will be available to downstream
  packages, and so we continue to use targets in those cases.)

* Beefs up our FindLibsquish.cmake module to correctly find debug
  versions of the library, to use in debug builds.

* Alters build_webp.bash to allow WEBP_BUILD_TYPE to override the build
  type, which had previously been hard-coded to Release.

* Removes search for HDF5, which as far as I can tell was unused
  directly by OIIO.
2021-09-27 21:49:57 -07:00
Larry Gritz 9d2a52341d strutil_test: add a test of split when the separator is not found (#3106)
I had a hunch about a problem. Was wrong, this function worked right
all along. But I'm keeping the beefed-up test.
2021-09-25 10:01:51 -07:00
Larry Gritz 93a16297e3 fmath: Improvements to round_to_multiple (#3104)
* More clearly document, test, and correctly handle the cases where
  the value < 0.

* Add `round_down_to_multiple`.
2021-09-20 23:10:14 -07:00
Larry Gritz 78901c3b04 Always have OpenEXRCore C library on tap -- with option (#3100)
Instead of a build-time option for enabling (and always using) the
experimental OpenEXR "core" library...

* Build support for it by default any time we're using a new enough
  OpenEXR version (>= 3.1). You can still hard-disable it being compiled
  in at all with `-DOIIO_USE_EXR_C_API=OFF`.

* Select whether it's actually used with the global OIIO attribute
  "openexr:core" (default to 0, disabled, for now).

This easily lets an app select support at runtime, and also may be
selected by user with environment variable
`OPENIMAGEIO_OPTIONS="openexr:core=1".

This all is intended to make it easier to benchmark use of this new
feature, switching back and forth without a rebuild.
2021-09-20 23:09:56 -07:00
Larry Gritz 31d5a6f1d3 Remove FindOpenImageIO.cmake (#3098)
Downstream clients should use the exported config.
2021-09-20 22:56:17 -07:00
Larry Gritz eb4b84e74d OCIO 2.1 now exports cmake config -- explain 2021-09-17 20:38:24 -07:00
Larry Gritz 4399477fd4 Improvements to font finding (#3096)
* Honor env $OPENIMAGEIO_FONTS as an additinal font searchpath.

* Global attribute "font_searchpath" as an additional font searchpath.

* Refactor and simplify the code that assembles the list of directories
  to search.
2021-09-16 19:53:05 -07:00
Larry Gritz 2d14cec834 Adjust logic of getting OCIO config (#3095)
When $OCIO was not set at all, the call to OCIO::GetCurrentConfig()
was checking it again and writing the info message that none was found
to stdout, which we really don't want.  And as Patrick pointed out
recently, asking for the "current" config is suspect, since who knows
exatly what the app has done.

So we're making the following executive decision: At least from OIIO's
viewpoint, if you want an OCIO color config, you either have to name it
expliticly, or have it determined by the `$OCIO` env variable. That makes
cleaner logic, and also rids us of the info messages.

I also now have the exported cmake config set
`OpenImageIO_HAS_OpenColorIO`. This makes it easier for downstream
consumers of our exported OpenImageIOConfig.cmake to know if the OIIO
build they have found has build-in support of OpenColorIO.
2021-09-15 10:24:59 -07:00
Larry Gritz 9dc2f971fd Fix ImageBuf::read bug for images of mixed per-channel data types (#3088)
When it comes time to read_image() into the ImageBuf's internal
memory, we should have said to convert to `m_spec.format`, which
describes the buffer we allocated. Instead, we asked for `convert`,
which is the user request, which at that time can still be UNKNOWN,
which indicates to preserve the file's data format, which in fact does
not necessarily match the internal buffer.

This becomes especially troublesome for images with mixed per-channel
data types, which will obviously never match the internal buffer since
ImageBuf only internally stores one data format for all channels.
2021-09-15 09:57:03 -07:00
Larry Gritz 689bfbfd54 When possible (>= C++17) use std::gcd instead of boost (#3076)
This is a very low priority change, but every little bit helps when it
comes to limiting boost's footprint as thing we used to require it for
become available in the standard library.
2021-09-15 09:46:43 -07:00
Larry Gritz cc67fab4f3 Rewrite ColorConfig::reset for clearer logic and better err handling (#3092)
Add tests to be sure we have reasonable error reporting for at least
two important cases: a specified OCIO config file is not found at all,
and an OCIO config is present but cannot be read (in particular, if
the config is newer than the library). Because the exact error spewage
is different for each OCIO version, and apparently also depending on
the exact version of the yaml library that OCIO used, we have a few
different possible output references.

* oiiotool --nostderr (new hidden command)

This hidden flag causes oiiotool errors to go to stdout instead of the
default stderr. It only does this for oiiotool's own error and warning
calls; if there are other places within library functions that
directly output to stderr, they will not be redirected by this
command.

The main purpose of this is for testsuite and debugging. I don't
expect ordinary users to have any use for this, and so it is currently
hidden from the oiiotool --help explanation.  If it seems useful for
something other than testsuite, I'll expose it in oiiotool --help.

It seems that for the case of OCIOv1 reading a v2 config, OCIO itself spews a bunch of warnings to stderr. And apparently the order is nondeterministic, because I just could not get any set of reference error output to match stably from run to run in CI. But the problem is, if I don't capture stderr, I also don't get the oiiotool error messages, which are the very thing I'm trying to test!

So what I did is add a new flag to oiiotool, --nostderr, which causes oiiotool's error and warnings to get sent to stdout rather than stderr. This lets me capture the usual output and the error messages from oiiotool, for this test, while allowing OCIO's stray stderr output to go into the ether where we don't care about its order.

I'm not sure if there's any non-CI, non-debugging application for oiiotool --nostderr, but maybe it'll turn out to be generally useful.
2021-09-11 19:10:36 -07:00
Larry Gritz 5506f34f85 Use latest aswf docker container for vfx platform 2022 (#3094) 2021-09-10 22:09:40 -07:00
Larry Gritz 7b22ba6305 CI: Adjust how we specify what to exclude from failure artifacts (#3091)
We weren't using a recognized notation, and so our artifacts were
including huge files unintentionally.
2021-09-04 18:20:34 -07:00
Larry Gritz d8661b783c OCIO: better catching of exceptions. (#3089)
When OIIO that was built against OCIO 1.x, but encounters an OCIO 2.x
config file, OCIO could throw an exception that was not caught by
OIIO.  The problem was the call to OCIO::GetCurrentConfig(), it should
have been inside the try/catch block.
2021-09-03 19:02:59 -07:00
Dalai Felinto 085aa98cc4 Update CREDITS.md (typo) (#3090) 2021-09-03 10:38:53 -07:00
Larry Gritz 6ba1f1faa4 CHANGES 2021-08-31 23:41:10 -07:00
Larry Gritz 7037cfba47 CI: Build VFXP2022 and latest releases against OCIO 2.1 (#3080) 2021-08-31 23:36:05 -07:00
Larry Gritz 112a318ad6 Additional TIFF IOProxy bug fix -- we don't want a full init inside open (#3077)
Calling close() in open will forget too much state. All we want to do
here is make sure the TIFF file itself is closed at that point (so it
can be re-opened in append mode to add a subsequent subimage).
2021-08-31 08:48:50 -07:00
0ea473527a tiffoutput: support ioproxy (#3075)
Co-authored-by: Alexandre Gauthier-Foichat <alexandre.gauthier@left-angle.com>
Co-authored-by: Larry Gritz <lg@larrygritz.com>
2021-08-30 14:51:10 -07:00
Larry Gritz b53cdeddc8 CI test for VP2022, fix revealed python binding bugs (#3074)
* CI test for VP2022, fix revealed python binding bugs

* CI test against ASWF's latest VFXPlatform-2022 docker container,
  including Python 3.9.

* Pesky crash resulted in testsuite/python-imagebufalgo, laboriously
  traced to IBA_color_range_check releasing the GIL too liberally. The
  scoped release cannot contain the tuple construction!

* Audited the rest of py_imagebufalgo.cpp and found the same mistake in
  only one other place: IBA_histogram. Was asymptomatic so far, but fixed
  now.

* Presumably we just got lucky and these bugs were never symptomatic
  until we started building against Python 3.9.

* Noticed that the recent change in build tree layout where we now
  copy the test images into the build/testsuite area, resulted in HUGE
  GHA build artifacts for failed tests. Modify ci.yml use of
  upload-artifact action to exclude those directories.

* more tweaks
2021-08-30 09:14:04 -07:00
Larry Gritz bdf6a40bad oiiotool: Overhaul operations timing (#3073)
oiiotool --runstats tries to report how much time was taken by each
operation.  But it has always had a major flaw: Because we try to read
input files lazily and use ImageCache underneath, only in certain
circumstances do the true cost of reading the files show up in the
entry for "-i"; often the cost gets wrongly credited to the other
command (like --add or -o) whose operations triggered the I/O.

This patch addresses the problem, and I think correctly credits I/O
time where it belongs.

The workhorse here is a new helper class within oiiotool,
OTScopedTimer, which does some tricks to try to account for both
direct read time and ImageCache I/O time, subtracting those from the
op it was instructed to time and instead adding it to the counter for
"-i".  Because the destructor apportions time to the right commands,
this eliminates a whole bunch of spots where we did that by hand.

Also fixed a few places where ops directly called ImageRec::read()
instead of Oiiotool::read(), which would also result in bypassing some
timers we relied on. I made the ImageRec one be private, so harder to
make that mistake in the future.
2021-08-30 09:13:40 -07:00
Larry Gritz 159d7e7ae9 Beef up strongparam.h comments and fix typo 2021-08-25 21:02:42 -07:00
Larry Gritz 218e1bd731 gitignore adjustments
Make it ignore a lot of the test case clutter I tend to accumulate
in the project root.
2021-08-25 21:02:24 -07:00
Larry Gritz be5dda397f Timer::add_seconds, add_ticks (#3070)
Add methods to the Timer class that allows you to add (or subtract, if
negtive) to the total elapsed value of a timer.
2021-08-24 21:22:47 -07:00
Larry Gritz 97532b814f Build: Be careful about default installation directory (#3069)
Use a cmake idiom so that you need an explicit `-DCMAKE_INSTALL_PREFIX=`
in order to write over /usr/local or any potentially sensitive area.
In the absence of this being set explicitly, it will configure the
cmake build so that an "install" ends up in ./dist (which is what the
Makefile wrapper did all along).
2021-08-24 21:21:37 -07:00
Larry Gritz 8b4f8f2321 oiiotool --ch : reduce expense for no-op (#3068)
Before doing all the work of copying the image, first see if the
`--ch` is actually specifying any change versus the image as it
stands. If not, skip all the copying and just stick to the image we
have.

The main benefit here is if you have a --ch primarily for "conformance",
e.g. you want to reduce to a known subset of channels and remove any
extra that may be unanticipated in the input, but it's possible that
the input will come to you already with only the desired channels. As
an example,

    oiiotool in.exr --ch R,G,B ...more ops... -o out.exr

Previously, if in.exr aleady had channels R,G,B (and no other), there
would be some unneceessary expense of creating (in memory) a new image
for the output of --ch copying data to fill it in. With this patch,
the --ch would very nearly turn into a no-op. In both cases, if
in.exr's channels were something other than R,G,B, channel copies
would need to be done identically in both old and new code.
2021-08-24 21:20:54 -07:00
Larry Gritz 0ab127226a Build scripts: rename OIIO_DEP_DOWNLOAD_ONLY to DEP_DOWNLOAD_ONLY (#3072)
I realized after this was merged that I often share and copy a lot of
these little dependency build scripts across multiple projects, so I
wanted to remove the OIIO-specific naming.
2021-08-24 21:20:17 -07:00
Larry Gritz 4ebae5f91e Update ref output for slightly different libjpeg 2021-08-23 16:18:09 -07:00
Shootfast 5024e8dd5e formatspec: Implemented deserialization of extra_attribs from XML (#3066) 2021-08-20 22:32:50 -07:00
Larry Gritz c6b4424564 More testsuite cleanup for arbitrary build directory (#3067)
To help make testsuite pass even with nonstandard relative path to the
build area, slightly change how we reference the OCIO config that is
in the testsuite.
2021-08-20 18:36:32 -07:00
Larry Gritz 741c6d7b51 Increase timer_test slop in CI to remove spurious failures 2021-08-20 13:07:47 -07:00
Larry Gritz 44bbf1f434 Testsuite: fix use of OIIO_TESTSUITE_ROOT (#3065)
Fixes python error about OIIO_TESTSUITE_ROOT not defined in the case
where the testsuite dir wasn't found in the standard places. This can
happen if you put the build directory in an unusual location that's
not right in the main project area.
2021-08-20 12:29:04 -07:00
Thomas MansencalandThomas Mansencal 1866f2fdb8 PR: Minor Windows Build Fixes (#3062)
* Ensure that "CMAKE" built "OpenCV" libraries can be found.

* Fix incorrect url to "openexr-images" repository.

* Fix typo in "FindTBB.cmake" module.

Co-authored-by: Thomas Mansencal <tmansencal@wetafx.co.nz>
2021-08-19 09:27:49 -07:00
Larry Gritz 8ff28a9d58 Fix typo in test generation 2021-08-18 16:28:38 -07:00
Larry Gritz 09766c95a9 Bump version to 2.4.0.0 after branching 2.3beta 2021-08-17 17:15:21 -07:00
Larry Gritz a17769cb57 CHANGES 2021-08-17 13:48:31 -07:00
Larry Gritz 231e885c21 Fewer spurious CI failures for timer_test 2021-08-17 13:48:31 -07:00
Larry Gritz 273952b642 cmake: checked_find_package enhancements (#3061)
* New SETVARIABLES option sets named cmake variabes to true if the
  package is found.
* DEBUG should print variables even if not found. Duh, failing to find
  the package is the most important debugging situation.
2021-08-16 09:01:14 -07:00
Larry Gritz f91d391b1a Build: collapse build and dist hierarchy (#3057)
For historical reasons, our wrapper makefiles assume that we build in
`build/ARCH[.variant]`, so maybe build/linux64, build/linux64.debug, etc.

I think this is a throwback to literally decades ago when I would
build multiple architectures from different machines that viewed a
common shared directory of code, this allowing them to build
simultaneously and/or erase one without needing to rebuild the others,
etc.

But now I find that:
* It's contrary to modern cmake practice, and there are many benefits
  to having our build directory structure identical to the vast majority
  of other open source projects.
* I never want or need those simultaneous builds in practice, haven't
  for a long, long time.
* ccache means that there is no longer an onerous cost to, for example,
  having to blow away a release build and do a debug build and then
  blow that away and do release again. It's just a few seconds to do a
  ccache-based full rebuild of a recently-built tree.

So this patch switches all our assumptions to having a single level
hierarchy to the build and dist areas.

Also, I'm changing the assumption that the oiio-images (and other data
sets used by the testsuite) live "up a level", but instead added code
that either copies it from there (or another area settable with the
cmake variable OIIO_LOCAL_TESTDATA_ROOT) or downloads it, into the
build/testsuite directory itself. This simplifies a great number of things
in the test scripts as well as the test reference output (a lot of which
changes slightly to accommodate the new paths to test files).
2021-08-15 15:00:24 -07:00
Larry Gritz 63f69cbca8 Try to decrease spurious CI failures (#3059)
* On Windows, increase number of tries for tests that timeout.
* On all CI runs, allow timer_test to be less accurate.
2021-08-15 14:25:11 -07:00
Larry Gritz 83e44727f5 Update FindTBB.cmake to create proper targets (#3060) 2021-08-15 14:24:54 -07:00
Shootfast b2f9a9be79 RAW plugin improvements (#3045)
* raw: Fixed output when raw:Demosaic == "none"

* raw: Include metadata regarding filter pattern

* raw: Added missing call to set unpacked status

* raw: Implement "balance_clamped" mode to help HDRI processing

* raw: Implement raw:apply_scene_linear_scale feature

* Fix up formatting with clang-format

* Update testsuite reference output

* raw: Fixed error message format handling

* raw: Updated documentation to include new raw features
2021-08-14 14:03:57 -07:00
Anders Langlands bbc2dfca2c Add flags to control stages of dependency build scripts (#3058)
* Ensure that all the `build_*.bash` scripts don't download anything if the packages appear to already be there.
* Env variable `OIIO_DEP_DOWNLOAD_ONLY` can be used to do the download only (if not present) and skip the actual build.

This combination allow the scripts to be run twice: once to do all the network I/O to download the packages we'll need, and a second time to trigger the builds.
2021-08-14 09:58:24 -07:00
Larry Gritz 0dd908f4e9 New oiiotool commands: --printinfo, --printstats (#3056)
The existing --info and --stats seem a little confusing and
inflexible.  Unlike the majority of oiiotool arguments which are
evaluated in order, these merely set flags which apply to the entire
oiiotool command (specifically, they cause all image inputs to print
the metadata or image statistics at the time that the input are read
from disk).  There isn't a way to make it apply to a single image, nor
to print the metadata or stats of any *computed* image, leading some
people to awkwardly save a computed image and re-read it merely to
print information about it.

So in this patch, we add new commands

* `--printinfo` which is like `-info -v` but is done immediately for
  the "current" image on the top of the stack (even if it's a computed
  image and does not correspond to any disk file).

* `--printstats` which is like `--stats` but is done immediately for
  the current image on top of the stack.

  Furthermore, `--printstats` takes an optional modifier `:window=`
  which can be given a rectangular region in either of the notations
  we use ("WxH+X+Y" or "xmin,xmax,ymin,ymax"), for example:

      oiiotool blah.exr --printstats:window=30x30+1000+500

  prints the statistics of the 30x30 region whose upper left corner
  is pixel (1000,500).

The code to implement this is actually pretty short and straightforward,
but this patch turns out to touch a lot more. I needed to plumb
some of the info-printing internals for this support and did some
refactoring along the way.

Also, upon adding these to the docs, I realized that it would be
better to reorganize a bit to separate descriptions of the "flags"
from the "actions", and so many of the oiiotool arguments got shuffled
between different subsections, and in a few cases the descriptions
themselves got rewritten for clarity.
2021-08-13 21:21:54 -07:00
Larry Gritz 2284dc038e Udim refactor and expose more helper functions (#3054)
To help applications that need to deal with UDIM textures, the
TextureSystem now exposes the following public API calls:

* is_udim() : is a filename (or a `TextureHandle*`) referring to a
  UDIM pattern / virtual file?

* resolve_udim() : given a filename (or handle) and s,t coordinates,
  return the handle for the concrete file corresponding to those
  coordinates.

* inventory_udim(): retrieve the full list of concrete filenames, as a
  vector indexed by `(utile + vtile * nvtiles)`, and the nutiles,
  nvtiles counts. Empty filenames in the vector indicate UDIM tiles
  that are not populated.

Some extra functionality falls out naturally from these and existing
ingredients:

* inventory_udim + get_texture_handle together can get you the list of
  handles corresponding to each found udim tile.

* resolve_udim + get_texture_info together can retrieve the attributes
  of the udim tile corresponding to a particular texture coordinate.

Additionally, I have done some refactoring and performance
improvements of the internals:

* The internal UdimInfo that's stored inside the ImageCacheFile record
  is now a vector, not a flat_map, so conversion of texture
  coordinates to a handle is now O(1) rather than O(log n).

* Per Luke Emrose's suggestion, use `rcontains()` when searching for
  UDIM pattern markers, since they will almost always occur close to the
  end of the full pathname.

* Added TextureSystem and ImageCache methods that lets you find out
  the filename that corresponds to a handle. (That's bound to be handy
  for somebody.)

* Beefed up the udim tests to be sure to test every udim notation that
  we support.
2021-08-11 20:51:38 -07:00
Thomas Mansencal 6a3b7569a0 Fix broken section links in "INSTALL.md" file. (#3055) 2021-08-09 16:08:11 -07:00
Larry Gritz 77217afe20 Strutil: Add rcontains, ircontains, improve contains, docs (#3053)
* At the suggestion of Luke Emrose, add rcontains() and ircontains(),
  which are like contains/icontains, but start the search at the end
  of the string rather than the beginning. This is measurably faster
  than contains() for the case when you are reasonably certain that if
  the search pattern is found at all, it is highly likely to be close
  to the end of the string. (They're approximately the same speed when
  the pattern is not found.)

* To verify this, I added a bunch of benchmarking to strutil_test.

* The benchmarks also revealed that contains was about 2x slower than
  calling find! It should be the same. I don't know what the underlying
  boost::algorithm::contains is doing differently than find, but whatever.
  Changing our implementation of Strutil::contains to simply call find
  doubles its speed.

* The new implementation of contains has an extremely minor behavior
  change for the degenerate case of `contains("", "")`, which used to
  return true and now returns false. Since the right behavior here is
  debatable at best (is it false because the first empty string
  contains nothing? or is it true because containts(a,b) should return
  true if a==b?), I'm going to accept this behavior change as well
  worth the 2x speed improvement (besides, "contains(a,b) should have
  the same result as find(a,b)!=npos" is also a reasonable
  expectation).

* The benchmarks also reveal that the case-insensitive functions (like
  ifind) are not just a little bit slower than their case-sensitive
  siblings (like find), they are 20x or more slower! I don't think
  there is anything to do about that, but I did note it in the
  documentation of those functions so that we are disuaded from using
  them except when a case-insensitive test is really necessary.
2021-08-07 20:33:55 -07:00
pumkinpal 57fe02c0e2 WebpInput: Fixed mismatched new[] and delete (#3052) 2021-08-05 14:09:14 -07:00
Larry Gritz 2c7e762774 Udim improvements (#3049)
The primary issue being addressed here was that get_texture_info() on a
udim pattern filename (like "foo_<UDIM>.exr") was unable to retrieve
info, except for an extremely narrow range of queries, because of course,
different UDIM "tiles" might have different attributes or be missing.

So in consultation with Lee Kerley, we decided that get_texture_info should
work as follows:

* If the attribute exists and has the same value for all of the
  matching UDIM file files, then succeed and return the value.

* If any of the tile files does not contain the attribute, or if the
  attribute doesn't have the same value in all found files, then it's
  a failure and the value cannot be retrieved.

This necessitated a more rebust accounting of all the tile files
comprising a UDIM pattern, by doing a full inventory the first time
the UDIM pattern is encountered, rather than (ick) iterating through
all possible tile files every time we retrieve an attribute, as we
were apparently doing before. And so the following improvements were
also made:

* get_texture_info now works for more queries -- in fact, any query
  that would be possible to ask about on an individual file, without
  restriction.  (Though, as I said, the query will fail if the value
  isn't identical across all the found tile files.)

* The info queries (even the few that were previously supported) will
  be MUCH FASTER than before, because we are doing the tile file
  inventory once per udim pattern, rather than on every query.

* That inventory will also pre-build the association between u,v tiles
  and the concrete filename (and texture handle!), so that each
  individual texture call does a simple map lookup to get all the way
  to the texture handle, without any string manipulation to first
  construct a concrete filename, then look that new filename up in the
  cache to get a handle, etc. I'm expecting this to reduce some of the
  overhead of using UDIM files with the TextureSystem.

Note: I added an ImageCacheImpl::find_file_no_add at some point in
this work, eventually not needing it by the time I got to the final
version of my implementation of this PR, but I'm going to keep it
because I can forsee its usefulness and I don't want to delete it only
to write it again some day.
2021-08-04 21:05:33 -07:00
Larry Gritz cd6c0f146f Remove the experimental C APIs (#3051)
We now think that this C API should be removed, and replaced by a
different one coming soon.

Merely commented out the option and other lines in the top-level
CMakeLists.txt, since almost the exact thing will be needed eventually.
Also kept libOpenImageIO-C/CMakeLists.txt since we'll eventually need
one much like it. But deleted the .cpp and .h files, since those will
be totally replaced.
2021-08-04 20:26:34 -07:00
Larry Gritz 263abf165a Build: Updates to handling OpenColorIO (#3050)
For the upcoming OCIO 2.1, the library names will incorporate the
major/minor version numbers, so our Find module needs to take that into
consideration.

Work towards eventually using OCIO exported configs (though still not
100% working now, may need fixes on their end).

Change CI to use the OCIO's that come in the aswf containers instead
of building from scratch in many cases.
2021-08-04 20:21:19 -07:00
Larry Gritz faac914959 filesystem.h: Switch some methods to using string_view (#3047)
Also improve comment documenting get_directory_entires, I realized it
was a little garbled.
2021-08-03 08:29:45 -07:00
Larry Gritz 1bc0cdcebf Filesystem::filename_to_regex (#3046)
Sometimes we use a filename, or pieces of it, as a regex.
But filenames can have characters that are interpreted differently when
part of a regex pattern (like `.`, which in a filename is literal, but
in a regex means to match any character!).

So this handy utility inserts the right backslashes so the filename will
end up as a literal match when part of a regex.
Furthermore, there's an optional parameter `simple_glob`, which when
true, will also substitute `?` with `.?` and `*` with `.*`.

We then use this to fix a latent bug in scan_for_matching_filenames():
it could have incorrectly matched files during the search.
2021-08-02 18:33:28 -07:00
Larry Gritz 5f2cdb5828 imagebuf.h: remove inclusion of imagecache.h (#3036)
I noticed when working on an ImageCache thing that even the smallest
change to imagecache.h was causing a substantial amount of the
codebase to needlessly recompile even though very few places really
need to use the IC APIs directly.

It took a little bit of juggling of some declarations, but this patch
allows imagebuf.h to be able to treat ImageCache and ImageCacheTile as
opaque, forward-declared types, without the need for every file that
needs imagebuf.h to also have to parse imagecache.h and everything it
might pull in.

This speeds up my development cycle substantially in many cases, and
it also speeds up compilation of user code (by a small amount) by
avoiding parsing of imagecache.h in circumstances where the user code
only needed to know about ImageBuf but not ImageCache.

There's a downside to this -- it's possible that user code that truly
needs both imagebuf.h and imagecache.h only includes the former
(inadvertently relying on the fact that the latter was transitively
included). These apps may need `#include <OpenImageIO/imagecache.h>`
to be added after upgrading to OIIO 2.3. Is that really really bad?
2021-08-02 18:32:52 -07:00
Larry Gritz 3e31830158 Strutil::contains_any_char (#3043)
Added this handy function that figures out if the first string contains
any character present in the second string.

Also rewrite the comments describing parse_until and parse_while for
better clarity and correctness.
2021-08-01 12:21:26 -07:00
Larry Gritz de53f325ef exr read: don't rename "version" attribute to "openexr:version" (#3044)
Some of the OpenEXR sample files had an attribute "version".
All along, I assumed this was telling me the version of the OpenEXR file
itself, so I was passing it along and also renaming "openexr:version".

Turns out I was wrong! This is just arbitrary metadata. Who knows why
it's in some of these files? Maybe nobody. But it's not meant to indicate
the file format version, and indeed it does not correctly reflect it.

In fact, there is no simple API call in the OpenEXR API that tells you
the file format version, you have to infer it from the features
present (multi-part or deep or long attribute name indicate changes
that came along with OpenEXR 2.x, but there is no version number in
the file per se).

So I'm just going to stop doing this rename, let "version" be "version",
it's just some user's metadata, I guess.
2021-08-01 12:20:37 -07:00
Larry Gritz b0b17a8f35 openexr reader internals: Remove unused fields (#3042) 2021-07-31 14:04:05 -07:00
Larry Gritz 3fdb3ecc21 Overhaul of how to read/write thumbnails (#3021)
A few image formats (but not most) support "thumbnails" -- low-res preview
images.

Traditionally, we have shoved them in the ImageSpec metadata as a byte
array (and ints for the width, height, nchannels). This is less than
ideal: It makes the metadata very bloated, taking more memory and
being more expensive to copy metadata, and potentially wastes time
doing I/O on this data that most applications don't want or
need. (Remember that any alterations to the image will make the
thumbnail "wrong", also. So it's rarely useful except for applications
that specifically want a preview image.)

Discussion in Issue 2902 led us to think that thumbnails should be
treated explicitly by the API, rather than shoved into the metadata in
this way. This patch is the attempt to overhaul thumbnail handling:

* ImageInput has a new `get_thumbnail()` method that can retrieve the
  thumbnail (if it exists) into an ImageBuf. The base class / default
  implementation does nothing; the image formats that support
  thumbnails should have their readers override this method. They are
  encouraged to read the thumbnails "lazily" if possible -- only
  if/when this method is called, and avoid the cost, memory, and I/O
  if not requested.

* ImageOutput likewise has a new `set_thumbnail` method.

* These are implemented for Targa and PSD, the only two formats for
  which we previously had implemented thumbnail functionality. (There
  are probably other formats that support thumbnails, but for which we
  never added OIIO support. Leave that for another day.)

* ImageBuf has new `has_thumbnail`, `get_thumbnail`, `set_thumbnail`,
  and `clear_thumbnail` methods.

* ImageCache has a new `get_thumbnail` method.

* oiiotool and iconvert attempt to preserve a thumbnail from input to
  output (but of course, only if both file types support it).

* ImageBufAlgo::IBAPrep clears the thumbnail in the destination image,
  on the theory that pretty much everything IBA would ever do will
  likely invalidate any preview image that it started with. This gets
  us to the point with oiiotool where a straight copy (like a format
  conversion) `oiiotool in.tga -o out.tga` will preserve the thumbnail,
  but just about anything else `oiiotool in.tga --stuff -o out.tga`
  will not transmit the original thumbnail to the output (which would
  almost certainly be wrong).

There is more work to do in the future. Some file formats that support
thumbnails don't yet have OIIO support for it. I'm not sure we ever
really want (except in the case of a truly straight copy) for oiiotool
to keep any input thumbnails; maybe if a thumbnail is wanted for
output, it should always be created anew (by downscaling) so that it
definitely matches the main image? Maybe also oiiotool needs a command
to explicitly extract and save the thumbnail (is that needed for any
legit use? or only as a debugging tool?).
2021-07-30 19:24:52 -07:00
Larry Gritz 7fe6710406 Streamline determination of whether file type is procedural. (#3039)
Imagecache repeatedly has to determine whether a filename is a type
of file that's "procedural" and does it expensively -- every time, it
creates the type of ImageInput in question just to ask it if it
supports("procedural").

We can ask this of each plugin type once, when we first register it.
Then just look it up when we need it.

This is strictly internal, has nothing to do with public APIs.
2021-07-30 10:06:21 -07:00
Larry Gritz b866cc9210 Augment PR 3037 to make it not break ABI compat (#3040) 2021-07-29 16:49:20 -07:00
Larry Gritz 0aaed34c2e Let CUE_THREADS help determine default number of threads for OIIO (#3038)
OpenCue-launched apps are encouraged to honor the setting of
CUE_THREADS to limit the number of threads they use. This change makes
oiiotool (and other OIIO-based tools and scripts) better citizens when run
as part of an OpenCue job.

CUE_THREADS has lower precedence than the more OIIO-specific
`OPENIMAGEIO_THREADS`.

For ordinary command line usage, this should not change behavior, since
you wouldn't expect CUE_THREADS to be set.

(Also fix docs which incorrectly named `OPENIMAGEIO_TEXTURE_OPTIONS`.)
2021-07-28 09:50:26 -07:00
Larry Gritz 4ba3380305 Extend Sysutil::getenv() to take a default if the env var is not found (#3037) 2021-07-27 09:31:39 -07:00
Larry Gritz 3df1923e5a CI: update "latest" releases we test against, notably OpenEXR 3.1 (#3033)
OpenEXR -> 3.1.0
pybind11 -> 2.7.0
OCIO -> 2.0.1
2021-07-25 16:04:50 -07:00
Larry Gritz bc1a8b3541 ImageCache: add a variety of invalidate() that takes an ImageHandle* (#3035)
Most of the rest of the IC methods that take a filename, also have
a version that takes a handle.
2021-07-25 14:08:03 -07:00
Larry Gritz d1fb156ebb Mark some long-deprecated things with OIIO_DEPRECATED (#3032)
And make sure to switch all of our internal uses of those to the
preferred new equivalents!

Also, hide some deprecated things from the documentation system so that
new people won't be tempted to use them.

These are all things that have been deprecated starting with OIIO 2.0
(or in some cases, even earlier). Multiple releases (2.0, 2.1, 2.2)
have gone by with them commented or documented as deprecated, but
without our adding the warnings. It's about time. We're still not
taking them away entirely, I usually don't do that until we've had at
least one release where it's been marked as OIIO_DEPRECATED, and also
only do true removals of API at major releases. But we're laying the
groundwork for being able to totally remove these when we eventually
have a 3.0 release.
2021-07-17 16:56:13 -07:00
zomgrolf d1073accae Make finding Boost more flexible. (#3031)
This patch modifies the build system to make it possible to control
whether OIIO should link Boost in the form of static or dynamic
libraries, independently from the LINKSTATIC setting, without
having to use the fully custom route (BOOST_CUSTOM).

This is done by preserving the value of the Boost_USE_STATIC_LIBS
variable, if it has been defined by the user. If the value
of Boost_USE_STATIC_LIBS has NOT been explicitly defined, it is
set to match the value of the LINKSTATIC variable, which should
result in Boost being linked in the same way as other dependencies.
2021-07-17 16:49:01 -07:00
Larry Gritz 23116709f5 Bump version after dev preview release 2021-07-16 14:56:53 -07:00
839 changed files with 121018 additions and 34867 deletions
+3 -3
View File
@@ -14,12 +14,12 @@
<!-- Put an 'x' in the boxes as you complete the checklist items -->
- [ ] I have read the [contribution guidelines](../CONTRIBUTING.md).
- [ ] I have read the [contribution guidelines](https://github.com/OpenImageIO/oiio/blob/master/CONTRIBUTING.md).
- [ ] If this is more extensive than a small change to existing code, I
have previously submitted a Contributor License Agreement
([individual](../src/doc/CLA-INDIVIDUAL), and if there is any way my
([individual](https://github.com/OpenImageIO/oiio/blob/master/src/doc/CLA-INDIVIDUAL), and if there is any way my
employers might think my programming belongs to them, then also
[corporate](../src/doc/CLA-CORPORATE)).
[corporate](https://github.com/OpenImageIO/oiio/blob/master/src/doc/CLA-CORPORATE)).
- [ ] I have updated the documentation, if applicable.
- [ ] I have ensured that the change is tested somewhere in the testsuite
(adding new test cases if necessary).
+135
View File
@@ -0,0 +1,135 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio
name: Analysis
on:
schedule:
# Run nightly while we're still working our way through the warnings
- cron: "0 8 * * *"
# Run unconditionally once weekly
# - cron: "0 0 * * 0"
push:
# Run on pushes only to master or if the branch name contains "analysis"
branches:
- master
- '*analysis*'
- '*sonar*'
# Allow manual kicking off of the workflow from github.com
workflow_dispatch:
# Uncomment the following line if we want to run analysis on all PRs:
# pull_request:
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
aswf:
name: "SonarCloud Analysis"
# Exclude runs on forks, since only the main org has the SonarCloud
# account credentials.
if: github.repository == 'OpenImageIO/oiio'
strategy:
fail-fast: false
matrix:
include:
- desc: sonar gcc9/C++14 py39 boost1.76 exr3.1 ocio2.2
nametag: static-analysis-sonar
os: ubuntu-latest
vfxyear: 2022
vfxsuffix: -clang11
cxx_std: 14
python_ver: 3.9
simd: "avx2,f16c"
fmt_ver: 8.1.1
pybind11_ver: v2.9.0
coverage: 1
# skip_tests: 1
sonar: 1
setenvs: export SONAR_SCANNER_VERSION=4.7.0.2747
SONAR_SERVER_URL="https://sonarcloud.io"
BUILD_WRAPPER_OUT_DIR=bw_output
OIIO_CMAKE_BUILD_WRAPPER="build-wrapper-linux-x86-64 --out-dir bw_output"
CMAKE_BUILD_TYPE=Debug
CMAKE_UNITY_BUILD=OFF
CODECOV=1
CTEST_TEST_TIMEOUT=1200
OIIO_CMAKE_FLAGS="-DOIIO_TEX_IMPLEMENT_VARYINGREF=OFF"
OPENCOLORIO_VERSION=v2.2.0
runs-on: ${{ matrix.os }}
container:
image: aswf/ci-osl:${{matrix.vfxyear}}${{matrix.vfxsuffix}}
env:
CXX: ${{matrix.cxx_compiler}}
CC: ${{matrix.cc_compiler}}
CMAKE_CXX_STANDARD: ${{matrix.cxx_std}}
USE_SIMD: ${{matrix.simd}}
FMT_VERSION: ${{matrix.fmt_ver}}
OPENEXR_VERSION: ${{matrix.openexr_ver}}
PYBIND11_VERSION: ${{matrix.pybind11_ver}}
PYTHON_VERSION: ${{matrix.python_ver}}
# DEBUG_CI: 1
steps:
# We would like to use harden-runner, but it flags too many false
# positives, every time we download a dependency. We should use it only
# on CI runs where we are producing artifacts that users might rely on.
# - name: Harden Runner
# uses: step-security/harden-runner@248ae51c2e8cc9622ecf50685c8bf7150c6e8813 # v1.4.3
# with:
# egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
with:
fetch-depth: '0'
- name: Prepare ccache timestamp
id: ccache_cache_keys
run: echo "::set-output name=date::`date -u +'%Y-%m-%dT%H:%M:%SZ'`"
- name: ccache
id: ccache
uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
with:
path: /tmp/ccache
key: ${{github.job}}-${{matrix.nametag}}-${{steps.ccache_cache_keys.outputs.date}}
restore-keys: ${{github.job}}-
- name: Build setup
run: |
${{matrix.setenvs}}
src/build-scripts/ci-startup.bash
- name: Dependencies
run: |
${{matrix.depcmds}}
src/build-scripts/gh-installdeps.bash
- name: Build
run: src/build-scripts/ci-build.bash
- name: Testsuite
if: matrix.skip_tests != '1'
run: src/build-scripts/ci-test.bash
- name: Code coverage
if: matrix.coverage == '1'
run: src/build-scripts/ci-coverage.bash
- name: Sonar-scanner
if: matrix.sonar == 1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
sonar-scanner --define sonar.host.url="${{ env.SONAR_SERVER_URL }}" --define sonar.cfamily.build-wrapper-output="build/bw_output" --define sonar.cfamily.gcov.reportsPath="_coverage"
# - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
# if: failure()
# with:
# name: oiio-${{github.job}}-${{matrix.nametag}}
# path: |
# build/cmake-save
# build/testsuite/*/*.*
# !build/testsuite/oiio-images
# !build/testsuite/openexr-images
# !build/testsuite/fits-images
# !build/testsuite/j2kp4files_v1_5
+399 -701
View File
File diff suppressed because it is too large Load Diff
+73
View File
@@ -0,0 +1,73 @@
name: Scorecards supply-chain security
on:
# Only the default branch is supported.
branch_protection_rule:
push:
# Run on pushes to master, but only the main repo, not forks
branches: [ "master" ]
if: github.event.pull_request.head.repo.full_name == github.repository
pull_request:
# Only run on individual PRs if the workflow file itself is changed.
paths:
- .github/workflows/scorecard.yml
# Declare default permissions as read only.
permissions: read-all
# Allow subsequent pushes to the same PR or REF to cancel any previous jobs.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
analysis:
name: Scorecards analysis
if: github.repository == 'OpenImageIO/oiio'
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Used to receive a badge. (Upcoming feature)
id-token: write
# Needs for private repositories.
contents: read
actions: read
steps:
- name: "Checkout code"
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # v1.1.1
with:
results_file: results.sarif
results_format: sarif
# (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecards on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
# Publish the results for public repositories to enable scorecard badges. For more details, see
# https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories, `publish_results` will automatically be set to `false`, regardless
# of the value entered here.
publish_results: true
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
with:
sarif_file: results.sarif
+13 -1
View File
@@ -1,10 +1,22 @@
*~
*.bak
branches/
build/
dist/
ext/
testsuite/runtest.pyc
.idea
.vscode
.cproject
.project
.DS_Store
*.pyc
_coverage/
# Exclude test files I tend to leave around at the top level. The leading
# slash ensures that files with these extensions within subdirectories are not
# ignored.
/*.exr
/*.tif
/*.jpg
/*.tx
/*.log
+1665 -42
View File
File diff suppressed because it is too large Load Diff
+59 -25
View File
@@ -1,24 +1,43 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
cmake_minimum_required (VERSION 3.12)
project (OpenImageIO VERSION 2.3.6.0
set (OpenImageIO_VERSION "2.5.0.3")
set (OpenImageIO_VERSION_OVERRIDE "" CACHE STRING
"Version override (use with caution)!")
mark_as_advanced (OpenImageIO_VERSION_OVERRIDE)
if (OpenImageIO_VERSION_OVERRIDE)
set (OpenImageIO_VERSION ${OpenImageIO_VERSION_OVERRIDE})
endif ()
project (OpenImageIO VERSION ${OpenImageIO_VERSION}
HOMEPAGE_URL "https://openimageio.org"
LANGUAGES CXX C)
set (PROJ_NAME OIIO) # short name, caps
string (TOLOWER ${PROJ_NAME} PROJ_NAME_LOWER) # short name lower case
string (TOUPPER ${PROJ_NAME} PROJ_NAME_UPPER) # short name upper case
set (PROJECT_VERSION_RELEASE_TYPE "dev") # "dev", "betaX", "RCY", ""
set (PROJECT_VERSION_RELEASE_TYPE "dev" CACHE STRING
"Build type, for example: dev, beta2, RC1 (empty string for normal release)")
set (${PROJECT_NAME}_VERSION_RELEASE_TYPE ${PROJECT_VERSION_RELEASE_TYPE})
set (PROJECT_AUTHORS "Contributors to the OpenImageIO project")
set (${PROJECT_NAME}_SUPPORTED_RELEASE 0) # Change to 1 for release branch
set (${PROJECT_NAME}_DEV_RELEASE 1) # Change to 0 for release branch
option (${PROJECT_NAME}_SUPPORTED_RELEASE
"Set ON for supported release branch, OFF for master" OFF)
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
set (${PROJECT_NAME}_DEV_RELEASE OFF)
else ()
set (${PROJECT_NAME}_DEV_RELEASE ON)
endif ()
# Identify whether this is included as a subproject of something else
if (NOT "${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}")
set (${PROJECT_NAME}_IS_SUBPROJECT ON)
message (STATUS "${PROJECT_NAME} is configuring as a CMake subproject")
# Set PROJECT_IS_TOP_LEVEL to ON if if this is the top level project (not
# if this is included as a subproject of something else). Note that this is
# handled automatically for CMake >= 3.21.
if (CMAKE_VERSION VERSION_LESS 3.21)
if ("${CMAKE_PROJECT_NAME}" STREQUAL "${PROJECT_NAME}")
set (PROJECT_IS_TOP_LEVEL ON)
endif ()
endif ()
# If the user wants to use Conan to build dependencies, they will have done
@@ -36,6 +55,15 @@ if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE "Release")
endif ()
# If the user hasn't configured cmake with an explicit
# -DCMAKE_INSTALL_PREFIX=..., then set it to safely install into ./dist, to
# help prevent the user from accidentally writing over /usr/local or whatever.
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
AND PROJECT_IS_TOP_LEVEL)
set (CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/dist" CACHE PATH
"Installation location" FORCE)
endif()
message (STATUS "Configuring ${PROJECT_NAME} ${PROJECT_VERSION}")
message (STATUS "CMake ${CMAKE_VERSION}")
message (STATUS "CMake system = ${CMAKE_SYSTEM}")
@@ -45,6 +73,7 @@ message (STATUS "Project build dir = ${CMAKE_BINARY_DIR}")
message (STATUS "Project install prefix = ${CMAKE_INSTALL_PREFIX}")
message (STATUS "Configuration types = ${CMAKE_CONFIGURATION_TYPES}")
message (STATUS "Build type = ${CMAKE_BUILD_TYPE}")
message (STATUS "Supported release = ${${PROJECT_NAME}_SUPPORTED_RELEASE}")
# Make the build area layout look a bit more like the final dist layout
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
@@ -71,13 +100,19 @@ option (BUILD_OIIOUTIL_ONLY "If ON, will build *only* libOpenImageIO_Util" OFF)
option (BUILD_DOCS "If ON, build documentation and man pages." ON)
option (INSTALL_DOCS "If ON, install documentation and man pages." ON)
option (INSTALL_FONTS "If ON, install default fonts" ON)
option (INSTALL_CMAKE_HELPER "If On, install FindOpenImageIO.cmake" ON)
option (EMBEDPLUGINS "Embed format plugins in libOpenImageIO" ON)
option (BUILD_COIIO "Build C interface library" ON)
set (PLUGIN_SEARCH_PATH "" CACHE STRING "Default plugin search path")
file (TO_NATIVE_PATH "${PLUGIN_SEARCH_PATH}" PLUGIN_SEARCH_PATH_NATIVE)
set (CMAKE_DEBUG_POSTFIX "_d" CACHE STRING "Library naming postfix for Debug builds")
if (CMAKE_UNITY_BUILD_BATCH_SIZE)
set (UNITY_SMALL_BATCH_SIZE "${CMAKE_UNITY_BUILD_BATCH_SIZE}" CACHE STRING "Unity batch mode size for expensive files")
else ()
set (UNITY_SMALL_BATCH_SIZE 8 CACHE STRING "Unity batch mode size for expensive files")
endif ()
message(STATUS "CMAKE_UNITY_BUILD_MODE = ${CMAKE_UNITY_BUILD_MODE}")
message(STATUS "CMAKE_UNITY_BUILD_BATCH_SIZE = ${CMAKE_UNITY_BUILD_BATCH_SIZE}")
option (OIIO_THREAD_ALLOW_DCLP "OIIO threads may use DCLP for speed" ON)
if (NOT OIIO_THREAD_ALLOW_DCLP)
add_definitions ("-DOIIO_THREAD_ALLOW_DCLP=0")
@@ -87,6 +122,10 @@ set (TEX_BATCH_SIZE "" CACHE STRING "Force TextureSystem SIMD batch size (e.g. 1
if (TEX_BATCH_SIZE)
add_definitions ("-DOIIO_TEXTURE_SIMD_BATCH_WIDTH=${TEX_BATCH_SIZE}")
endif ()
option (OIIO_TEX_IMPLEMENT_VARYINGREF "Implement the deprecated batch texture functions taking VaryingRef params" ON)
if (NOT OIIO_TEX_IMPLEMENT_VARYINGREF)
add_definitions (-DOIIO_TEX_NO_IMPLEMENT_VARYINGREF=1)
endif ()
# Set the default namespace
set (${PROJ_NAME}_NAMESPACE ${PROJECT_NAME} CACHE STRING
@@ -100,6 +139,9 @@ if (${PROJ_NAME}_NAMESPACE_INCLUDE_PATCH)
endif ()
message(STATUS "Setting Namespace to: ${PROJ_NAMESPACE_V}")
# Define OIIO_INTERNAL symbol only when building OIIO itself, will not be
# defined for downstream projects using OIIO.
add_definitions (-DOIIO_INTERNAL=1)
list (APPEND CMAKE_MODULE_PATH
"${PROJECT_SOURCE_DIR}/src/cmake/modules"
@@ -124,7 +166,7 @@ include (pythonutils)
include (externalpackages)
# Include all our testing apparatus and utils, but not if it's a subproject
if (NOT ${PROJECT_NAME}_IS_SUBPROJECT)
if (PROJECT_IS_TOP_LEVEL)
include (testing)
else ()
macro (oiio_add_tests)
@@ -210,11 +252,6 @@ if (NUKE_FOUND)
add_subdirectory (src/nuke/txWriter)
endif ()
if (BUILD_COIIO)
add_subdirectory(src/libOpenImageIO-C)
oiio_add_tests(coiio)
endif ()
# Last minute site-specific instructions, if they exist
if (OIIO_SITE AND EXISTS "${PROJECT_SOURCE_DIR}/site/${OIIO_SITE}/cmake/sitecustom.cmake")
include ("${PROJECT_SOURCE_DIR}/site/${OIIO_SITE}/cmake/sitecustom.cmake")
@@ -228,11 +265,6 @@ if (NOT MSVC)
COMPONENT developer)
endif()
# Oddball: install the FindOpenImageIO.cmake file
install (FILES src/cmake/modules/FindOpenImageIO.cmake
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/Modules
COMPONENT cmake)
# Export the configuration files. There are also library-specific config
# exports in the CMakeLists.txt of libOpenImageIO.
include (CMakePackageConfigHelpers)
@@ -273,9 +305,11 @@ install (EXPORT OIIO_EXPORTED_TARGETS
NAMESPACE ${PROJECT_NAME}::)
oiio_add_all_tests()
if (PROJECT_IS_TOP_LEVEL AND BUILD_TESTING)
oiio_setup_test_data()
oiio_add_all_tests()
endif ()
if (NOT ${PROJECT_NAME}_IS_SUBPROJECT)
if (PROJECT_IS_TOP_LEVEL)
include (packaging)
endif ()
+1 -1
View File
@@ -113,7 +113,7 @@ the pull request URL and discussing any issues you think are important.
6. All pull requests automatically launch CI jobs on GitHub Actions to
ensure that the build completes and that the tests suite runs correctly, for
a varity of platform, compiler, library, and flag combinations. The status
a variety of platform, compiler, library, and flag combinations. The status
of the CI tests for your PR will be displayed on the GitHub PR page. We will
not accept PRs that don't build cleanly or pass the existing testsuite.
+19 -1
View File
@@ -4,6 +4,7 @@ by first name.
If you know of somebody that I missed or have corrections, please email:
lg@openimageio.org
* Adam Mains
* Akihiro Yamasaki
* Alan Jones
* Alejandro Conty
@@ -18,13 +19,17 @@ lg@openimageio.org
* Aman Shah
* Ananth Garre
* Anders Langlands
* Anthony Nemoff
* Aras Pranckevičius
* Arkady Shapkin
* Basileios Anastasatos
* Bastien Montagne
* Ben De Luca
* Bernhard Rosenkraenzer
* Biswapriyo Nath
* Blair Tennessy
* Blazej Floch
* Brad Smith
* Brecht Van Lommel
* Brent Davis
* Brian Hall
@@ -40,6 +45,7 @@ lg@openimageio.org
* Christoph Willing
* Cliff Stein
* Clément Champetier
* Dalai Felinto
* Dan Wexler
* Daniel Dresser
* Daniel Flehner Heen
@@ -47,7 +53,6 @@ lg@openimageio.org
* David Aguilar
* David Gordon
* Deepak Gopinath
* Delai Felinto
* Dennis Schridde
* Dieter De Baets
* Dinko Galetik
@@ -82,8 +87,10 @@ lg@openimageio.org
* Jeremy Rose
* Jeremy Selan
* Jim Hourihan
* Johannes Unterguggenberger
* John Burnett
* John Haddon
* Jonathan Hearn
* Jonathan Scruggs
* Joseph Goldstone
* Julien Enche
@@ -91,6 +98,7 @@ lg@openimageio.org
* Justina Mikonyte
* Kazuki Takahashi
* Kevin Brightwell
* Kimball Thurston
* Konrad Kleine
* Krzysztof Blicharski
* Larry Gritz (project leader)
@@ -114,6 +122,9 @@ lg@openimageio.org
* Matteo F. Vescovi
* Matthew E. Levine
* Max Liani
* Merwan Achibet
* Michael Cho
* Michael Oliver
* Michel Lerenard
* Michel Normand
* Mikael Sundell
@@ -127,19 +138,23 @@ lg@openimageio.org
* Nixon Kwok
* Northon Patrick
* Nuno Cardoso
* Ole Gulbrandsen
* Ott Tinn
* Pascal Lecocq
* Patrick Hodoul
* Patrick Piché
* Paul Melis
* Paul Molodowitch
* Pavel Karneliuk
* Pete Larabell
* Philip Nemec
* Pino Toscano
* Povilas Kanapickas
* Puneet Jain
* Radu Arjocu
* Ramon Montoya
* Ray Molenkamp
* Rémi Achard
* Richard Shaw
* Robert Matusewicz
* Roeland Schoukens
@@ -151,6 +166,7 @@ lg@openimageio.org
* Samuel Nicholas
* Scott Wilson
* Sebastian Elsner
* SebTV
* Seifeddine Dridi
* Sergey Sharybin
* Shane Ambler
@@ -170,7 +186,9 @@ lg@openimageio.org
* Vishal Agrawal
* Vitor Franchi
* Will Rosecrans
* William Krick
* Wormszer
* Xo Wang
* Yang Yang
* Yann Lanthony
* zomgrolf
+127 -34
View File
@@ -3,8 +3,8 @@ Installation instructions for OpenImageIO
# Table of Contents
1. [OpenImageIO's Dependencies](#dependencies)
2. [Installing binaries from package managers](#installingfrompackagemanagers)
3. [Building OIIO from source](#buildingfromsource)
2. [Installing binaries from package managers](#installing-from-package-managers)
3. [Building OIIO from source](#building-from-source)
Dependencies
@@ -17,12 +17,17 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**.
* **C++14** (also builds with C++17, and C++20)
* The default build mode is C++14. This can be controlled by via the
CMake configuration flag: `-DCMAKE_CXX_STANDARD=17`, etc.
* Compilers: **gcc 6.1 - 11.1**, **clang 3.4 - 12**, **MSVS 2017 - 2019**,
**icc 17+**.
* CMake >= 3.12 (tested through 3.20)
* OpenEXR/Imath >= 2.0 (recommended: 2.2 or higher; tested through 3.1)
* libTIFF >= 3.9 (recommended: 4.0+; tested through 4.3)
* Boost >= 1.53 (recommended: at least 1.66; tested through 1.76)
* Compilers: **gcc 6.1 - 12.1**, **clang 3.4 - 15**, **MSVS 2017 - 2019**,
**Intel icc 17+**, **Intel OneAPI C++ compiler 2022+**.
* CMake >= 3.12 (tested through 3.24)
* OpenEXR/Imath >= 2.3 (recommended: 2.4 or higher; tested through 3.1)
* libTIFF >= 3.9 (recommended: 4.0+; tested through 4.5)
* libjpeg >= 8, or libjpeg-turbo >= 1.1 (tested through jpeg9d and jpeg-turbo
2.1)
* Boost >= 1.53 (recommended: at least 1.66; tested through 1.80)
* [fmtlib](https://github.com/fmtlib/fmt) >= 6.1.2 (tested through 9.1). If
not found at build time, this will be automatically downloaded unless the
build sets `-DBUILD_MISSING_FMT=OFF`.
### Optional dependencies -- features may be disabled if not found
* If you are building the `iv` viewer (which will be disabled if any of
@@ -30,23 +35,23 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**.
* Qt >= 5.6 (tested through 5.15)
* OpenGL
* If you are building the Python bindings or running the testsuite:
* Python >= 2.7 (tested against 2.7, 3.6, 3.7, 3.8, 3.9)
* pybind11 >= 2.4.2 (Tested through 2.6.)
* Python >= 2.7 (tested against 2.7, 3.7, 3.8, 3.9, 3.10)
* pybind11 >= 2.4.2 (Tested through 2.10. Note that pybind11 v2.10+ does
not support Python < 3.6.)
* NumPy
* If you want support for camera "RAW" formats:
* LibRaw >= 0.15 (tested 0.15 - 0.20; LibRaw >= 0.18 is necessary for
* LibRaw >= 0.15 (tested 0.15 - 0.20.2; LibRaw >= 0.18 is necessary for
ACES support and much better recognition of camera metadata; if
building with C++17 or higher, LibRaw >= 0.20 is necessary)
* If you want support for a wide variety of video formats:
* **ffmpeg >= 3.0** (tested through 4.4)
* **ffmpeg >= 3.0** (tested through 5.1)
* If you want support for jpeg 2000 images:
* **OpenJpeg >= 2.0** (tested through 2.4)
* If you want support for Field3D files:
* Field3D (tested through 1.7.3)
* **OpenJpeg >= 2.0** (tested through 2.5; we recommend 2.4 or higher
for multithreading support)
* If you want support for OpenVDB files:
* OpenVDB >= 5.0 (tested through 8.0) and Intel TBB >= 2018 (tested
through 2021)
* Note that OpenVDB 8.0+ requires C++14 or higher.
* OpenVDB >= 5.0 (tested through 9)
* If you want to use TBB as the thread pool:
* TBB >= 2018 (tested through 2021)
* If you want support for converting to and from OpenCV data structures,
or for capturing images from a camera:
* **OpenCV 3.x, or 4.x** (tested through 4.5)
@@ -54,25 +59,22 @@ NEW or CHANGED MINIMUM dependencies since the last major release are **bold**.
* giflib >= 4.1 (tested through 5.2; 5.0+ is strongly recommended for
stability and thread safety)
* If you want support for HEIF/HEIC or AVIF images:
* libheif >= 1.3 (1.7 required for AVIF support, tested through 1.11)
* libheif >= 1.3 (1.7 required for AVIF support, tested through 1.12)
* libheif must be built with an AV1 encoder/decoder for AVIF support.
* Avoid libheif 1.10 on Mac, it is very broken. Libheif 1.11 is fine.
* If you want support for DDS files:
* libsquish >= 1.13 (tested through 1.15)
* But... if not found on the system, an embedded version will be used.
* If you want support for DICOM medical image files:
* DCMTK >= 3.6.1 (tested through 3.6.5)
* DCMTK >= 3.6.1 (tested through 3.6.6)
* If you want support for WebP images:
* WebP >= 0.6.1 (tested through 1.1.0)
* WebP >= 0.6.1 (tested through 1.2.1)
* If you want support for OpenColorIO color transformations:
* OpenColorIO 1.1 or 2.0
* OpenColorIO >= 1.1 (tested through 2.2; 2.0+ is recommended)
* If you want support for Ptex:
* Ptex >= 2.3.1 (probably works for older; tested through 2.4.0)
* Ptex >= 2.3.1 (probably works for older; tested through 2.4.2)
* We use PugiXML for XML parsing. There is a version embedded in the OIIO
tree, but if you want to use an external, system-installed version (as
may be required by some software distrbutions with policies against
may be required by some software distributions with policies against
embedding other projects), then just build with `-DUSE_EXTERNAL_PUGIXML=1`.
Any PugiXML >= 1.8 should be fine (we have tested through 1.11).
Any PugiXML >= 1.8 should be fine (we have tested through 1.12).
@@ -82,6 +84,11 @@ Mac OS X, and Windows.
Our build system is based upon 'CMake'. If you don't already have it
installed on your system, you can get it from http://www.cmake.org
If certain dependencies (robin-map and fmtlib) are not found, their sources
will be retrieved and built into libraries, as part of the build process. The
sources of those dependencies are cloned from their Git repo, hence `git` must
be available as a command.
After you build OpenImageIO, if you compiled with the `EMBEDPLUGINS=0` flag
you will need to set the environment variable `OIIO_LIBRARY_PATH` to point
to the 'lib' directory where OpenImageIO is installed, or else it will
@@ -97,8 +104,10 @@ build options), maybe one of these packages managers will do it for you:
* vcpkg (https://github.com/Microsoft/vcpkg)
* https://github.com/Microsoft/vcpkg/tree/master/ports/openimageio
* `.\vcpkg install openimageio [tools]`
* For a full list of supported build features: `.\vcpkg search openimageio`
* `vcpkg install openimageio [tools]`
* For a full list of supported build features: `vcpkg search openimageio`
* Instructions for building a Python wheel on Windows:
https://github.com/Correct-Syntax/py-oiio
* homebrew (https://github.com/Homebrew/brew)
* https://formulae.brew.sh/formula/openimageio
* `brew install openimageio`
@@ -153,7 +162,7 @@ file format (jpeg, fits, png, etc.). This works both as a CMake variable and
also as an environment variable.
`ENABLE_PkgName=0` : Disables use of an *optional* dependency (such as
FFmpeg, Field3D, Webp, etc.) -- even if the dependency is found on the
FFmpeg, OpenVDB, Webp, etc.) -- even if the dependency is found on the
system. This will obviously disable any functionality that requires the
dependency. This works both as a CMake variable and
also as an environment variable.
@@ -259,8 +268,92 @@ Building on Windows
**Method 1 - from source**
I really need someone to write correct, modern docs about how to build
from source on Windows.
You will need to have Git, CMake and Visual Studio installed.
The minimal set of dependencies for OIIO is: Boost, zlib, libTIFF, OpenEXR, and libjpeg or libjpeg-turbo. If you have them built somewhere then you skip
the section below, and will only have to point OIIO build process so their locations.
* Boost: get the boost source archive, extract into `{BOOST_ROOT}`.
```
cd {BOOST_ROOT}
bootstrap
b2
```
* zlib: this will build it, and then delete the non-static library, so they don't get picked up:
```
cd {ZLIB_ROOT}
git clone https://github.com/madler/zlib .
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=. ..
cmake --build . --config Release --target install
del lib\zlib.lib
```
* libTIFF:
```
cd {TIFF_ROOT}
git clone https://gitlab.com/libtiff/libtiff.git .
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=. ..
cmake --build . --target install
```
* libjpeg-turbo:
```
cd {JPEG_ROOT}
git clone https://github.com/libjpeg-turbo/libjpeg-turbo .
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_SHARED=OFF -DCMAKE_INSTALL_PREFIX=. ..
cmake --build . --config Release --target install
```
* OpenEXR: you'll have to point it to your `{ZLIB_ROOT}` location from the above. If copy-pasting the multi-line command (with lines ending in `^`) into
cmd.exe prompt, make sure to copy all the lines at once.
```
cd {EXR_ROOT}
git clone https://github.com/AcademySoftwareFoundation/openexr .
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=dist ^
-DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DOPENEXR_BUILD_TOOLS=OFF ^
-DOPENEXR_INSTALL_TOOLS=OFF -DOPENEXR_INSTALL_EXAMPLES=OFF ^
-DZLIB_ROOT={ZLIB_ROOT}\build ..
cmake --build . --target install --config Release
```
Now get the OIIO source and do one-time CMake configuration step. Replace `{*_ROOT}` below with folders where you have put the 3rd party
dependencies.
```
cd {OIIO_ROOT}
git clone https://github.com/OpenImageIO/oiio .
mkdir build
cd build
cmake -DVERBOSE=ON -DCMAKE_BUILD_TYPE=Release ^
-DBoost_USE_STATIC_LIBS=ON -DBoost_NO_WARN_NEW_VERSIONS=ON -DBoost_ROOT={BOOST_ROOT} ^
-DZLIB_ROOT={ZLIB_ROOT}\build ^
-DTIFF_ROOT={TIFF_ROOT}\build ^
-DOpenEXR_ROOT={EXR_ROOT}\build\dist ^
-DImath_DIR={EXR_ROOT}\build\dist\lib\cmake\Imath ^
-DJPEG_ROOT={JPEG_ROOT}\build ^
-DUSE_PYTHON=0 -DUSE_QT=0 -DBUILD_SHARED_LIBS=0 -DLINKSTATIC=1 ..
```
This will produce `{OIIO_ROOT}/build/OpenImageIO.sln` that can be opened in Visual Studio IDE. Note that the solution will be
only for the Intel x64 architecture only; and will only target "min-spec" (SSE2) SIMD instruction set.
Optional packages that OIIO can use (e.g. libpng, Qt) can be build and pointed to OIIO build process in a similar way.
In Visual Studio, open `{OIIO_ROOT}/build/OpenImageIO.sln` and pick Release build configuration. If you pick Debug, you
might need to re-run the CMake command above with `-DCMAKE_BUILD_TYPE=Debug` and also have all the dependencies above built
with `Debug` config too.
The main project that builds the library is `OpenImageIO`. The library is built into `{OIIO_ROOT}/build/lib/{CONFIG}` folder.
The various OIIO command line tools (`oiiotool`, `iconvert` etc.) are projects under Tools subfolder in VS IDE solution explorer.
They all build into `{OIIO_ROOT}/build/bin/{CONFIG}` folder.
There's a `CMakePredefinedTargets/INSTALL` project that you can build to produce a `{OIIO_ROOT}/dist` folder with `bin`, `include`,
`lib`, `share` folders as an OIIO distribution.
The instructions above use options for building statically-linked OIIO library and tools. Adjust options passed to CMake to
produce a dynamic-linked version.
**Method 2 - Using vcpkg**
@@ -268,7 +361,7 @@ from source on Windows.
2. Follow vcpkg installation instructions and complete the install. Please note vcpkg has its own list of prerequisites listed on their page.
3. Execute the PowerShell command from where vcpkg is located in directory. ``.\vcpkg install openimageio``
3. Execute the PowerShell command from where vcpkg is located in directory. ``vcpkg install openimageio``
Test Images
-----------
+26 -26
View File
@@ -10,7 +10,7 @@
#
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
#########################################################################
@@ -21,15 +21,6 @@ working_dir := ${shell pwd}
# Figure out which architecture we're on
include ${working_dir}/src/make/detectplatform.mk
# Presence of make variables DEBUG and PROFILE cause us to make special
# builds, which we put in their own areas.
ifdef DEBUG
variant +=.debug
endif
ifdef PROFILE
variant +=.profile
endif
MY_MAKE_FLAGS ?=
MY_NINJA_FLAGS ?=
MY_CMAKE_FLAGS ?=
@@ -46,10 +37,8 @@ endif
# Set up variables holding the names of platform-dependent directories --
# set these after evaluating site-specific instructions
top_build_dir ?= build
build_dir ?= ${top_build_dir}/${platform}${variant}
top_dist_dir ?= dist
dist_dir ?= ${top_dist_dir}/${platform}${variant}
build_dir ?= build
dist_dir ?= dist
INSTALL_PREFIX ?= ${working_dir}/${dist_dir}
@@ -198,6 +187,10 @@ MY_CMAKE_FLAGS += -G Ninja
BUILDSENTINEL := build.ninja
endif
ifneq (${UNITY},)
MY_CMAKE_FLAGS += -DCMAKE_UNITY_BUILD=ON -DCMAKE_UNITY_BUILD_MODE=${UNITY}
endif
ifeq (${CODECOV},1)
CMAKE_BUILD_TYPE=Debug
MY_CMAKE_FLAGS += -DCODECOV:BOOL=${CODECOV}
@@ -245,7 +238,7 @@ endif
#########################################################################
# Top-level documented targets
all: dist
all: install
# 'make debug' is implemented via recursive make setting DEBUG
debug:
@@ -265,7 +258,7 @@ config:
cd ${build_dir} ; \
${CMAKE} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \
${MY_CMAKE_FLAGS} ../.. ; \
${MY_CMAKE_FLAGS} ${working_dir} ; \
fi)
@@ -303,7 +296,7 @@ clang-format: config
)
# 'make dist' is just a synonym for 'make install'
# DEPRECATED: 'make dist' is just a synonym for 'make install'
dist : install
TEST_FLAGS += --force-new-ctest-process --output-on-failure
@@ -319,7 +312,16 @@ test: build
cd ${build_dir} ; \
lcov -b . -d . -c -o cov.info ; \
lcov --remove cov.info "/usr*" -o cov.info ; \
genhtml -o ./cov -t "Test coverage" --num-spaces 4 cov.info ; \
lcov --remove cov.info "*/usr/incude" -o cov.info ; \
lcov --remove cov.info "/Library/Developer/*" -o cov.info ; \
lcov --remove cov.info "*/detail/pugixml/*" -o cov.info ; \
lcov --remove cov.info "*/detail/fmt/*" -o cov.info ; \
lcov --remove cov.info "*/detail/farmhash.h" -o cov.info ; \
lcov --remove cov.info "*/v1/*" -o cov.info ; \
lcov --remove cov.info "*/ext/robin-map/*" -o cov.info ; \
lcov --remove cov.info "*/kissfft.hh" -o cov.info ; \
lcov --remove cov.info "*/stb_sprintf.h" -o cov.info ; \
genhtml -o ../_coverage -t "Test coverage" --num-spaces 4 cov.info ; \
fi )
# 'make testall' does a full build and then runs all tests (even the ones
@@ -336,10 +338,8 @@ clean:
realclean: clean
${CMAKE} -E remove_directory ${dist_dir}
# 'make nuke' blows away the build and dist areas for all platforms
nuke:
${CMAKE} -E remove_directory ${top_build_dir}
${CMAKE} -E remove_directory ${top_dist_dir}
# DEPRECATED: 'make nuke' blows away the build and dist areas for all platforms
nuke: realclean
doxygen:
doxygen src/doc/Doxyfile
@@ -359,7 +359,6 @@ help:
@echo " make profile Build and install for profiling"
@echo " make clean Remove the temporary files in ${build_dir}"
@echo " make realclean Remove both ${build_dir} AND ${dist_dir}"
@echo " make nuke Remove ALL of build and dist (not just ${platform})"
@echo " make test Run tests"
@echo " make testall Run all tests, even broken ones"
@echo " make clang-format Run clang-format on all the source files"
@@ -370,12 +369,13 @@ help:
@echo " STOP_ON_WARNING=0 Do not stop building if compiler warns"
@echo " OPENIMAGEIO_SITE=xx Use custom site build mods"
@echo " MYCC=xx MYCXX=yy Use custom compilers"
@echo " CMAKE_CXX_STANDARD=14 Set the C++ standard (default is C++14)"
@echo " CMAKE_CXX_STANDARD=14 C++ standard to build with (default is 14)"
@echo " USE_LIBCPLUSPLUS=1 For clang, use libc++"
@echo " GLIBCXX_USE_CXX11_ABI=1 For gcc, use the new string ABI"
@echo " EXTRA_CPP_ARGS= Additional args to the C++ command"
@echo " USE_NINJA=1 Set up Ninja build (instead of make)"
@echo " USE_CCACHE=0 Disable ccache (even if available)"
@echo " UNITY=BATCH Do a 'Unity' build (BATCH or GROUP or nothing)"
@echo " CODECOV=1 Enable code coverage tests"
@echo " SANITIZE=name1,... Enable sanitizers (address, leak, thread)"
@echo " CLANG_TIDY=1 Run clang-tidy on all source (can be modified"
@@ -383,7 +383,7 @@ help:
@echo " CLANG_FORMAT_INCLUDES=... CLANG_FORMAT_EXCLUDES=..."
@echo " Customize files for 'make clang-format'"
@echo " Linking and libraries:"
@echo " SOVERSION=nn Include the specifed major version number "
@echo " SOVERSION=nn Include the specified major version number "
@echo " in the shared object metadata"
@echo " OIIO_LIBNAME_SUFFIX=name Optional name appended to library names"
@echo " BUILD_SHARED_LIBS=0 Build static library instead of shared"
@@ -392,7 +392,7 @@ help:
@echo " For each dependeny Foo, defining ENABLE_Foo=0 disables it, even"
@echo " if found. And you can hint where to find it with Foo_ROOT=path"
@echo " Note that it is case sensitive! The list of package names is:"
@echo " DCMTK FFmpeg Field3D Freetype GIF JPEGTurbo"
@echo " DCMTK FFmpeg Freetype GIF JPEGTurbo"
@echo " LibRaw OpenColorIO OpenCV OpenGL OpenJpeg OpenVDB"
@echo " PTex R3DSDK TBB TIFF Webp"
@echo " Finding and Using Dependencies:"
+5 -7
View File
@@ -30,7 +30,7 @@ OpenImageIO consists of:
* Plugins implementing I/O for several popular image file formats,
including TIFF, JPEG/JFIF, OpenEXR, PNG, HDR/RGBE, ICO, BMP, Targa,
JPEG-2000, RMan Zfile, FITS, DDS, Softimage PIC, PNM, DPX, Cineon,
IFF, Field3D, OpenVDB, Ptex, Photoshop PSD, Wavefront RLA, SGI, WebP,
IFF, OpenVDB, Ptex, Photoshop PSD, Wavefront RLA, SGI, WebP,
GIF, DICOM, HEIF/HEIC/AVIF, many "RAW" digital camera formats, and a variety
of movie formats (readable as individual frames). More are being developed
all the time.
@@ -136,12 +136,10 @@ detailed instructions.
Web Resources
-------------
Main web page: http://www.openimageio.org
* Main web page: http://www.openimageio.org
GitHub page: http://github.com/OpenImageIO/oiio
* GitHub page: http://github.com/OpenImageIO/oiio
Mail list subscriptions and archives:
* Developer mail list subscriptions and archives:
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
* Developer mail list: http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org
* Just release announcements: http://lists.openimageio.org/listinfo.cgi/oiio-announce-openimageio.org
+352
View File
@@ -0,0 +1,352 @@
<!-- SPDX-License-Identifier: CC-BY-4.0 -->
<!-- Copyright Contributors to the OpenImageIO Project. -->
# Release Procedures for OpenImageIO
## Version nomenclature and release cadence
### The meaning of the version parts
Our release numbers are of the form `MAJOR.MINOR.PATCH.TWEAK`, and we follow
an almost-semantic-versioning scheme.
MAJOR changes are those that break backward-compatibility of the public APIs,
requiring existing application code to change their source code where it calls
OIIO API functions in order to compile and work correctly.
MINOR changes guarantee API backward-compatibility with prior releases that
have the same major number, but can introduce ABI or link incompatibilities.
Applications using OIIO need to be recompiled to move to a new minor release,
but should not need to change their source code. Minor releases are allowed
to drop support for sufficiently old compilers and dependencies.
PATCH changes guarantee both API and ABI/link backward-compatibility with
prior releases that have the same minor number. Features and new public API
calls may be added (thus deviating from strict semantic versioning), but only
if they preserve ABI/link compatibility. This means that standalone functions
or static methods may be added, but existing functions will not change their
parameters, and no new virtual methods or struct data layouts change for patch
releases (for classes in public header files). Application code can be
re-linked to a new patch release without needing to be recompiled. We also
guarantee that any compilers or dependencies supported for the first release
of a minor series will continue to be supported for all patches to that minor
series.
TWEAK changes are restricted to critical bug fixes or build breaks that do
not alter public APIs in any way.
### Cadence of releases
Major (arbitrarily incompatible) releases happen rarely, usually with multiple
years between them.
Minor (API backward-compatible) releases are scheduled annually, targeted at
late summer (SIGGRAPH time) to be in beta, and early autumn for a full
release.
Patch (API and ABI backward-compatible) releases are scheduled monthly,
usually aiming for the first day of each month.
Tweak (fully forward and backward compatible) releases are not regularly
scheduled, and only happen sporadically, when a critical fix is needed in
between scheduled patch releases.
### Things are different in "master"
The "master" branch is where ongoing development occurs without any
compatibility guarantees. We don't always know if the next year's release from
master will turn out to be major (API breaking) or minor (only ABI breaking).
Some studios or products need the most up-to-date enhancements, and thus tend
to build OIIO from the "master" branch rather than using tagged releases. For
these users, we try to set version numbers and occasionally tag in master, to
send a signal about which points in master seem safe to rely on various
compatibility levels. However, the rules are slightly different than we use
for releases.
In the "master" branch:
- TWEAK changes within "master" only guarantee ABI back-compatibility, but may
have additions or non-bug-fix behavior changes (akin to patch releases
within a release branch).
- PATCH changes within "master" are allowed to break ABI or API (changes that
would require minor or major releases, if they were not in "master").
- Beware of unmarked breaks in compatibility of commits in master that are
in between developer preview tags.
---
## Branch and tag names
**Branches** are places where commits containing new development may be added
(and thus the branch markers will move over time). Branch names obey the
following conventions:
- `master` is the area for arbitrary changes intended for the next year's
major or minor release.
- `dev-1.2` are the areas for staging additions to the next month's patch
release for the designated minor version series.
- `release` is a special branch marker that is always set to the latest tag of
the currently supported, stable release family. People can count on
"release" always being the latest stable release, whatever that may be at
the time.
**Tags** indicate releases or developer previews, and once a commit is
tagged, it is permanent and will never be moved. Tag names obey the following
conventions:
- `v1.2.3.4` is a specific public stable release, corresponding to official
major, minor, public, or tweak releases.
- `v1.2.3.4-alpha`, `v1.2.3.4-beta`, or `v1.2.3.4-RC1` are pre-releases for an
upcoming public stable release, at the alpha, beta, or release candidate
stages, respectively.
- `v1.2.3.4-dev` is a "developer preview" within "master." It is not an official
supported release, and while the numbering may indicate compatibility versus
other recent developer previews, they should not be assumed to be compatible
with any prior official stable releases.
*Very* occasionally, other branch or tag names (with custom suffixes or
different naming schemes) may be used for special purposes by particular
developers or users, but should not be considered reliable or permanent, and
in general should be ignored by anyone who didn't make the tag or branch.
---
## Release Procedures
### Soft freeze for monthly tweak releases:
We freely backport *safe*, non-ABI-breaking changes by cherry-picking them
from master to the supported branch continually throughout most of the month.
In the seven days before the new month, we do a "soft freeze" where only
important bug fixes are backported. Hold on to any other patches you wish to
backport until after the monthly patch release (i.e., save them for the next
month's release so you never have a release that contains changes that are
only a few days old, and therefore not as well tested). You may, of course,
continue to backport fixes to documentation or other non-code parts of the
project during this soft freeze.
### Branching for annual major/minor releases
By mid-June (about 1-2 months before the beta of a new annual big release),
you should branch and mark it as an alpha.
At the tip of "master", create a new branch named `dev-MAJOR.MINOR` that will
be the staging area for the next release.
Customarily, at that point we add a commit to master (but not to the new
dev-MAJ.MIN branch) that bumps master's version to the next minor level, to
avoid any confusion between builds from master versus what will be the next
release branch. This starts the divergence between master and the release
branch, and henceforth, any big or compatibility-breaking changes will only be
committed to master and not backported to the release branch. (Though we are
loose about this rule during the alpha period and allow continued breaking
changes in the alpha, but by the time we call it beta, we allow no more
breaking changes.) Also at this stage, the master branch's CHANGES.md should
have a heading added at the top for the *next* version.
### Prior to a release
1. Update CI dependencies: Ensure that the "latest" CI test specifies the
current releases of the dependencies and compilers (check their home
pages), and that the [INSTALL.md](../INSTALL.md) file correctly documents
the version ranges that we expect to work and that we actively test.
2. Release notes: [CHANGES.md](../CHANGES.md) should be updated to reflect
all the new features and fixes. Looking at the notes from older releases
should provide a good example of what we're aiming for.
- Patch and tweak releases can be brief one-line descriptions (often the
first line of the commit messages involved), presented in a single
section in either chronological or any other order that seems right.
- Minor or major releases have a much more extensive, prose-based
description of all changes since the last minor release, broken into
sections (dependency changes, major new features, enhancements and fixes,
internals and developer goodies, testing/CI/ports, etc.) and ordered for
readability and relevance.
3. Ensure docs are up to date:
- Actually read the [README.md](README.md), [INSTALL.md](INSTALL.md),
and other repository docs and make sure all the information is up to
date. Check the [CREDITS.md](CREDITS.md) against the recent repo history
to be sure new contributors are listed.
- Skim the primary user documentation to look for any obvious errors,
especially the parts that describe new features.
- If we are using any online docs (like readthedocs), make sure it is
building and looks correct on the web site.
4. Make sure the the top-level CMakeLists.txt file is updated:
- The `OpenImageIO_VERSION` should be correct.
- The `PROJECT_VERSION_RELEASE_TYPE` variable should be set to "alpha" or
"beta" if appropriate, "RC" for release candidate, or empty string `""`
for most supported releases, and "dev" only for the master branch or
developer previews.
- The `${PROJECT_NAME}_SUPPORTED_RELEASE` variable should be `ON` for any
release branch, `OFF` for master.
5. In the https://github.com/OpenImageIO/oiio-images project, create a branch
`RB-x.y` for the major/minor branch, and in the main oiio repo, update
src/build-scripts/install_test_images.bash to specify `-b RB-x.y` in the
checkout of oiio-images to ensure CI tests are against the set of test
images corresponding to that major/minor release (just in the branch, not
in master!).
6. Make sure everything passes the usual CI workflow. Also check the daily or
weekly "analysis" workflows to make sure there aren't any important
warnings that should be fixed.
### Staging alpha / beta / release candidate (annual minor/major releases only)
For monthly patch releases, we don't have any formal alpha/beta/RC stages.
For the annual minor or major releases we have a staged release:
- `alpha` is everything after we have branched, in which we think all the big
new features have been added, and while we will make continued changes and
fixes, we are aiming for increased stability and to minimize additional
breaking changes prior to the release.
- `beta` should be about one month prior to the final release date. We create
a tag `v1.2.3.4-beta` and announce the beta (see below "Making the
release"). Once we tag a beta, we try very hard not to allow any further
changes that change the API or are not ABI-compatible (i.e., safe fixes
only).
- `RC` or release candidates around one week prior to the final release date.
This is a trial run, hopefully identical to the final release (except for
removing the RC label and making a new tag). The only changes allowed after
RC are fixes to the most critical bugs or build breaks that would be bad for
users to encounter. If critical problems are found with RC1, they should be
fixed and immediately re-tagged as RC2, etc. All other fixes should be
postponed until the next month's patch release.
### Making the release
A final release is made on the scheduled date, provided the latest RC has
survived for at least a few days of testing without finding any critical
problems. Don't make the release final until you are sure there are no
truly critical bugs or build breaks that users will encounter.
The following are the steps for making the release:
1. Edit the top-level CMakeLists.txt to remove any RC designation
(i.e., `PROJECT_VERSION_RELEASE_TYPE` should be set to `""`).
2. Edit CHANGES.md to reflect the correct date of the release and ensure it
includes any last-minute changes that were made during beta or release
candidate stages.
3. Push it to **your** GitHub, make sure it passes CI.
4. Tag the release: `git tag v1.2.3.4` (no more beta, RC, or dev suffix).
5. If this will now be the recommended stable release, move the `release`
branch marker to the same position.
6. Push it to GitHub: `git push OpenImageIO release --tags`
(This example assumes "OpenImageIO" is the name of the remote for the
GitHub `OpenImageIO/oiio` repo.)
7. Draft a release on GitHub: On https://github.com/OpenImageIO/oiio/releases
select "Draft a new release." Choose the new tag you just pushed. Make the
release title "OpenImageIO v1.2.3.4" (and beta, etc., designation
if applicable). In the description, paste the release notes for this
release (from CHANGES.md). If this is a beta or release candidate, check
"this is a pre-release" box at the bottom.
8. Announce the release on the [oiio-dev mail list](http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org)
with the subject "Release: OpenImageIO v1.2.3.4" and using one of these
templates for the body of the email.
For a monthly patch release:
> We have tagged v1.2.3.4 as the latest production release and moved the
> "release" branch marker to that point. This is guaranteed to be API,
> ABI, and link back-compatible with prior 1.2 releases. Release notes
> are below.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
For an annual major/minor release:
> OpenImageIO version 1.2 has been released! Officially tagged as
> "v1.2.3.4", we have also moved the "release" branch tag to this
> position. Henceforth, 1.2 is the supported production release family.
> The API is now frozen -- we promise that subsequent 1.2.x releases
> (which should happen monthly) will not break back-compatibility of API,
> ABI, or linkage, compared to this release. Please note that this release
> is *not* ABI or link compatible with 1.1 or older releases.
>
> Release notes for 1.2 outlining all the changes since last year's
> release are below.
>
> Please note that a few of the build and runtime dependencies have
> changed their minimum supported versions. (List here any important
> changes to dependencies, compilers, or C++ standard that users should be
> aware of.)
>
> (List here anything else that people should know about this release
> family that may be surprising if they haven't followed the last year of
> development closely, or that they must know even if they are too lazy to
> read the release notes. If this is a major release that is not
> backward-compatible with prior versions, warn about that here.)
>
> Enjoy, and please report any problems. We will continue to make patch
> releases to the 1.2 family roughly monthly, which will contain bug fixes
> and non-breaking enhancements.
>
> The older 1.1 series of releases is now considered obsolete. We will
> continue for now to make 1.1 patch releases, but over time, these will
> become less frequent and be reserved for only the most critical bug
> fixes.
>
> The "master" branch is now progressing toward an eventual 1.3 release next
> summer. As usual, you are welcome to use master for real work, but we do
> not make any compatibility guarantees and don't guarantee continuing API
> compatibility in master.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
For a beta leading up to the annual major/minor release:
> OpenImageIO version 1.2 is now in beta, tagged as "v1.2.3.4-beta". We
> will try very hard not to make any further API or ABI changes between
> now and the final release (unless it is absolutely necessary to fix
> an important problem identified during beta testing). The final 1.2
> release is scheduled for [DATE GOES HERE], so please try building and
> testing the beta so we are sure to find any problems.
>
> Release notes for 1.2 outlining all the changes since last year's
> release are below.
>
> (Paste the full set of 1.2 changes here, just copy the appropriate
> part of CHANGES.md)
### After the release
Odds and ends to do after the tag is pushed and the announcements are sent:
- Re-read RELEASING.md and ensure that the instructions match what you
have done. Update as necessary.
- Go to readthedocs.org, and ensure that the new release is built and visible
and is the default release shown (specified in the Admin section). I tend to
keep the latest patch of each minor release available for reference
indefinitely, but hide the docs for earlier patch releases within that minor
release series.
- Edit the top-level CMakeList.txt to update the version to the *next*
anticipated release on the branch, in order to ensure that anybody building
from subsequent patches won't get a release number that advertises itself
incorrectly as a prior tagged release. Also edit CHANGES.md to add a new
(blank) heading for the next patch or release.
+25
View File
@@ -0,0 +1,25 @@
# Security Policy
## Supported Versions
This gives guidance about which branches are supported with patches to
security vulnerabilities.
| Version / branch | Supported |
| ----------------- | ---------------------------------------------------- |
| master | :white_check_mark: :construction: ALL fixes immediately, but this is a branch under development with a frequently unstable ABI and occasionally unstable API. |
| 2.3.x | :white_check_mark: All fixes that can be backported without breaking ABI compatibility. New tagged releases monthly. |
| 2.2.x | :x: Only receives occasional critical fixes, upon request. |
| <= 2.1.x | :x: No longer receiving patches of any kind. |
## Reporting a Vulnerability
If you think you've found a potential vulnerability in OpenImageIO, please
report it by emailing security@openimageio.org. Only the project administrator
has access to these messages. Include detailed steps to reproduce the issue,
and any other information that could aid an investigation. Our policy is to
respond to vulnerability reports within 14 days.
Our policy is to address critical security vulnerabilities rapidly and post
patches as quickly as possible.
+17 -6
View File
@@ -21,12 +21,24 @@ SPDX-License-Identifier: BSD-3-Clause
OIIO, but since some elements are derived from that, we still acknowledge
the original copyright here.
* Open Shading Language. Copyright Sony Pictures Imageworks Inc.
* Open Shading Language. Copyright contributors to the OSL project.
https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
A few parts here and there, notably parts of fmath.h and many of the CMake
files, contain code that was originally developed for Open Shading
Language but subsequently moved to OIIO.
* OpenColorIO (c) Copyright contributors to the OpenColorIO Project.
https://github.com/AcademySoftwareFoundation/OpenColorIO
The sample OpenColorIO configurations in our testsuite are borrowed from
this ASWF project, also BSD-3-Clause licensed.
* OpenEXR/Imath (c) Copyright contributors to the OpenEXR Project.
https://github.com/AcademySoftwareFoundation/Imath
Some templates in vecparam.h were first developed for Imath.
* DPX reader/writer (c) Copyright 2009 Patrick A. Palmer.
https://github.com/patrickpalmer/dpx
@@ -102,10 +114,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
MIT License
SPDX-License-Identifier: MIT
* Squish
Copyright 2006 Simon Brown si@sjbrown.co.uk
http://sjbrown.co.uk/?code=squish
* PugiXML http://pugixml.org/ https://github.com/zeux/pugixml
Copyright (c) 2006-2018 Arseny Kapoulkine
@@ -242,6 +250,9 @@ SPDX-License-Identifier: Unlicense
* gif.h by Charlie Tangora. Public domain / Unlicense.
https://github.com/ginsweater/gif-h
* bcdec.h by Sergii "iOrange" Kudlai. MIT or Unlicense.
https://github.com/iOrange/bcdec
This is free and unencumbered software released into the public domain.
@@ -275,7 +286,7 @@ Public domain
* lookup3 code by Bob Jenkins, Public Domain.
http://burtleburtle.net/bob/c/lookup3.c
* The SHA-1 implemenation we use is public domain by Dominik Reichl.
* The SHA-1 implementation we use is public domain by Dominik Reichl.
http://www.dominik-reichl.de
-------------------------------------------------------------------------
-2
View File
@@ -18,13 +18,11 @@ tbb/2020.0
# pybind11/2.4.3 - conan doesn't have this minimum version
# dcmtk
# ffmpeg
# field3d
# libheif
# libraw
# openvdb
# ptex
# qt5
# libsquish
[generators]
+28 -160
View File
@@ -3,32 +3,16 @@ ifneq (${VERBOSE},)
$(info Including spi/Makefile-bits)
endif
# For SpComp2 builds, do:
#
# make OIIO_SPCOMP2=1 spcomp2_install
# or
# make OIIO_SPCOMP2=1 SPCOMP2_LOCAL_PATH=/test/path spcomp2_install_local
#
# For Arnold builds, do:
#
# make OIIO_ARNOLD=1
#
# Otherwise a default 'make' will make a fully generic OIIO build.
OIIO_SPCOMP2 ?= 0
OIIO_ARNOLD ?= 0
OIIO_VERS = $(shell grep "OpenImageIO VERSION" CMakeLists.txt | egrep -o "[0-9.]+")
ONEVERS = $(shell site/spi/format_version.py ${OIIO_VERS})
OPENIMAGEIO_SPCOMP2_VERSION ?= ${ONEVERS}
ifeq (${OIIO_SPCOMP2},1)
$(info Building for SpComp2)
OIIO_ARNOLD := 0
NAMESPACE ?= 'OpenImageIO_SpComp2'
SOVERSION ?= ${OPENIMAGEIO_SPCOMP2_VERSION}
PYLIB_LIB_PREFIX ?= 1
PYLIB_INCLUDE_SONAME ?= 1
else ifeq (${OIIO_ARNOLD},1)
ifeq (${OIIO_ARNOLD},1)
$(info Building for Arnold)
NAMESPACE ?= 'OpenImageIO_Arnold'
$(info Building generic OpenImageIO)
@@ -46,10 +30,9 @@ ifeq (${SP_OS}, rhel7)
ifeq (${SPI_COMPILER_PLATFORM},gcc-6.3)
SPCOMP2_COMPILER ?= gcc63
CMAKE_CXX_STANDARD ?= 14
LLVM_VERSION ?= 11.0.1
LLVM_VERSION ?= 12.0.1
endif
SP_PLATFORM ?= linux
SP_PROC ?= x86_64
else ifeq (${platform}, macosx)
# Generic OSX machines (including LG's laptop)
COMPILER ?= clang
@@ -57,17 +40,16 @@ else ifeq (${platform}, macosx)
CMAKE_CXX_STANDARD ?= 14
SP_OS ?= macosx
SP_PLATFORM ?= macosx
SP_PROC ?= x86_64
else
$(error Unknown SP_OS=${SP_OS} platform=${platform})
endif # endif ${SP_OS}
MY_CMAKE_FLAGS += -DSP_OS=${SP_OS} -DSP_PLATFORM=${SP_PLATFORM}
MY_CMAKE_FLAGS += -DSP_PROC=${SP_PROC}
MY_CMAKE_FLAGS += -DSPI_COMPILER_PLATFORM=${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DEXTRA_CPP_ARGS:STRING="-DOIIO_SPI=1" -DOIIO_SITE:STRING=spi
MY_CMAKE_FLAGS += -DSPI_TESTS=1
MY_CMAKE_FLAGS += -DSPI_TESTS=1 -DPROJECT_VERSION_RELEASE_TYPE=spi
MY_CMAKE_FLAGS += -DOIIO_NAMESPACE_INCLUDE_PATCH=1
MY_CMAKE_FLAGS += -DCMAKE_DEBUG_POSTFIX=${CMAKE_DEBUG_POSTFIX:-_d}
REZ_PACKAGE_ROOT ?= /shots/spi/home/software/packages
SPCOMP2_ROOT ?= /shots/spi/home/lib/SpComp2
@@ -96,15 +78,15 @@ ifeq (${SP_OS}, rhel7)
#
# A variety of tags can be used to try specific versions of gcc or
# clang from the site-specific places we have installed them.
LLVM_DIRECTORY ?= /shots/spi/home/software/packages/llvm/${LLVM_VERSION}/${SPI_COMPILER_PLATFORM}
LLVM_DIRECTORY ?= ${REZ_PACKAGE_ROOT}/llvm/${LLVM_VERSION}/${SPI_COMPILER_PLATFORM}
ifeq (${COMPILER},clang9)
LLVM_DIRECTORY := /shots/spi/home/software/packages/llvm/9.0.1-1/${SPI_COMPILER_PLATFORM}
LLVM_DIRECTORY := ${REZ_PACKAGE_ROOT}/llvm/9.0.1-1/${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang -DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
else ifeq (${COMPILER},clang10)
LLVM_DIRECTORY := /shots/spi/home/software/packages/llvm/10.0.0-1/${SPI_COMPILER_PLATFORM}
LLVM_DIRECTORY := ${REZ_PACKAGE_ROOT}/llvm/10.0.0-1/${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang -DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
else ifeq (${COMPILER},clang11)
LLVM_DIRECTORY := /shots/spi/home/software/packages/llvm/11.0.0/${SPI_COMPILER_PLATFORM}
LLVM_DIRECTORY := ${REZ_PACKAGE_ROOT}/llvm/11.0.0/${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=${LLVM_DIRECTORY}/bin/clang -DCMAKE_CXX_COMPILER=${LLVM_DIRECTORY}/bin/clang++
else ifeq (${COMPILER},clang)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
@@ -163,11 +145,11 @@ ifeq (${SP_OS}, rhel7)
MY_CMAKE_FLAGS += \
-DPYTHON_INCLUDE_DIR:STRING=${PYTHON_INCLUDE_DIR} \
-DPYTHON_LIBRARY:STRING=${PYTHON_LIBRARY} \
-Dpybind11_ROOT:STRING=${REZ_PACKAGE_ROOT}/pybind11/2.4.3/python-${PYTHON_VERSION}
-Dpybind11_ROOT:STRING=${REZ_PACKAGE_ROOT}/pybind11/2.6.2/python-${PYTHON_VERSION}
# Set our preferred OpenEXR path, but allow env variable to override
# with custom/test version.
OPENEXR_VERSION ?= 2.4.1-2
OPENEXR_VERSION ?= 2.4.3
OpenEXR_ROOT ?= ${REZ_PACKAGE_ROOT}/OpenEXR/${OPENEXR_VERSION}/${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DOpenEXR_ROOT=${OpenEXR_ROOT}
@@ -177,24 +159,16 @@ ifeq (${SP_OS}, rhel7)
NUKE_VERSION ?= 11.2v3
SPCOMP2_FULLBOOST_SUFFIX = ${SP_OS}-${SPCOMP2_COMPILER}-boost${shell echo ${BOOSTVERS} | sed "s/\\.//"}
# $(info SPCOMP2_FULLBOOST_SUFFIX ${SPCOMP2_FULLBOOST_SUFFIX})
ifeq (${OIIO_SPCOMP2},1)
OCIO_SPCOMP_VERSION ?= 2
OpenColorIO_ROOT ?= ${SPCOMP2_ROOT}/OpenColorIO/${SP_OS}-${SPCOMP2_COMPILER}/v${OCIO_SPCOMP_VERSION}
else
OPENCOLORIO_VERSION ?= 1.1.1-1
OpenColorIO_ROOT ?= ${REZ_PACKAGE_ROOT}/OpenColorIO/${OPENCOLORIO_VERSION}/${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DOPENCOLORIO_LIBRARY=${OpenColorIO_ROOT}/lib/libOpenColorIO_SPI.so
# Anybody remember why we needed Field3d disabled for SpComp2?
Field3D_ROOT ?= ${SPCOMP2_ROOT}/Field3D/${SPCOMP2_FULLBOOST_SUFFIX}/v412
endif
OPENVDB_VERSION ?= 6.2.2-3
OPENCOLORIO_VERSION ?= 2.1.0
OpenColorIO_ROOT ?= ${REZ_PACKAGE_ROOT}/OpenColorIO/${OPENCOLORIO_VERSION}/${SPI_COMPILER_PLATFORM}/python-${PYTHON_VERSION}
#MY_CMAKE_FLAGS += -DOPENCOLORIO_LIBRARY=${OpenColorIO_ROOT}/lib/libOpenColorIO_SPI.so
OPENVDB_VERSION ?= 8.0.0-2
OpenVDB_ROOT ?= ${REZ_PACKAGE_ROOT}/OpenVDB/${OPENVDB_VERSION}/${SPI_COMPILER_PLATFORM}/python-${PYTHON_VERSION}/boost-${BOOSTVERS}
TBB_ROOT ?= /net/apps/rhel7/intel/tbb
TBB_LIBRARY ?= /net/apps/rhel7/intel/tbb/lib/intel64/gcc4.7
Libheif_ROOT=/shots/spi/home/lib/arnold/rhel7/libheif-1.3.2
Libheif_ROOT ?= /shots/spi/home/lib/arnold/rhel7/libheif-1.3.2
MY_CMAKE_FLAGS += \
-DOpenColorIO_ROOT=${OpenColorIO_ROOT} \
-DField3D_ROOT=${Field3D_ROOT} \
-DOpenVDB_ROOT=${OpenVDB_ROOT} \
-DTBB_ROOT=${TBB_ROOT} \
-DTBB_LIBRARY=${TBB_LIBRARY} \
@@ -209,10 +183,12 @@ ifeq (${SP_OS}, rhel7)
-DVISIBILITY_MAP_FILE:STRING="${working_dir}/site/spi/hidesymbols.map"
# LibRaw
LibRaw_ROOT ?= /shots/spi/home/software/packages/LibRaw/0.20.0-dev3/${SPI_COMPILER_PLATFORM}
LibRaw_ROOT ?= ${REZ_PACKAGE_ROOT}/LibRaw/0.21.0.0/${SPI_COMPILER_PLATFORM}
MY_CMAKE_FLAGS += -DLibRaw_ROOT=${LibRaw_ROOT}
LIBRAW_LIBDIR = ${LibRaw_ROOT}/lib
MY_CMAKE_FLAGS += -DWebP_ROOT=${REZ_PACKAGE_ROOT}/webp/1.2.1/${SPI_COMPILER_PLATFORM}
# Use libtiff I built myself, static, and try to hide its symbols.
MY_CMAKE_FLAGS += \
-DTIFF_INCLUDE_DIR:STRING=/usr/include \
@@ -226,7 +202,7 @@ else ifeq (${platform}, macosx)
USE_SIMD ?= sse4.2
MY_CMAKE_FLAGS += \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=1 \
-DCMAKE_INSTALL_NAME_DIR="${working_dir}/dist/${platform}${variant}/lib"
-DCMAKE_INSTALL_NAME_DIR="${working_dir}/dist/lib"
# A variety of tags can be used to try specific versions of gcc or
# clang from the site-specific places we have installed them.
@@ -246,12 +222,15 @@ else ifeq (${platform}, macosx)
MY_CMAKE_FLAGS += \
-DCMAKE_C_COMPILER=gcc-11 -DCMAKE_CXX_COMPILER=g++-11
USE_LIBCPLUSPLUS := 0
else ifeq (${COMPILER},clang9)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@9/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@9/bin/clang++
else ifeq (${COMPILER},clang11)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@11/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@11/bin/clang++
else ifeq (${COMPILER},clang13)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@13/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@13/bin/clang++
else ifeq (${COMPILER},clang14)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@14/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@14/bin/clang++
else ifeq (${COMPILER},clang15)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=/usr/local/opt/llvm@15/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/local/opt/llvm@15/bin/clang++
else ifeq (${COMPILER},clang)
MY_CMAKE_FLAGS += -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
else ifeq (${COMPILER},gcc)
@@ -275,114 +254,3 @@ ifneq (${VERBOSE},)
$(info MY_CMAKE_FLAGS: $(MY_CMAKE_FLAGS))
endif
############################################################################
# SpComp2 magic incantations follow. Here be dragons.
############################################################################
CPPSTDSUFFIX=
SPCOMP2_INSTALL_ROOT ?= $(SPCOMP2_ROOT)
SPARCH=${SP_OS}-$(SPCOMP2_COMPILER)$(CPPSTDSUFFIX)-boost$(subst .,,$(BOOSTVERS))
OIIO_SPCOMP2_PATH := ${SPCOMP2_INSTALL_ROOT}/OpenImageIO/${SPARCH}/v${OPENIMAGEIO_SPCOMP2_VERSION}
# $(info New rhel7 OIIO_SPCOMP2_PATH is ${OIIO_SPCOMP2_PATH})
PYVERNOSPACE=${shell echo ${PYTHON_VERSION} | sed "s/\\.//"}
SPPYARCH=$(SPARCH)-py$(PYVERNOSPACE)
all: dist
local: dist
.PHONY: spcomp2_install spcomp2_install_local spi clean all
spi: MY_CMAKE_FLAGS += -DCMAKE_DEBUG_POSTFIX=_d
spi: debug dist
comma:= ,
empty:=
space:= $(empty) $(empty)
INSTALL_SPCOMP2_CURRENT = $(SPCOMP2_INSTALL_ROOT)/OpenImageIO/$(SPARCH)/v$(OPENIMAGEIO_SPCOMP2_VERSION)
INSTALL_BIN_LOCATION = $(INSTALL_SPCOMP2_CURRENT)/bin
SPCOMP2_LOCAL_PATH ?= /net/soft_scratch/users/$(USER)/SpComp2_test
spcomp2_install_local: SPCOMP2_INSTALL_ROOT = $(SPCOMP2_LOCAL_PATH)
spcomp2_install_local: INSTALL_BIN_LOCATION = $(INSTALL_SPCOMP2_CURRENT)/bin
spcomp2_install_local: spcomp2_install
SPCOMP2_RPATH_OPT ?= ${OpenEXR_ROOT}/lib:${OpenColorIO_ROOT}/lib:${Field3D_ROOT}/lib:${LIBRAW_LIBDIR}:${OpenVDB_ROOT}/lib:${Libheif_ROOT}/lib:shots/spi/home/lib/arnold/rhel7/libde265-1.0.3/lib:${TBB_ROOT}/lib/intel64/gcc4.7:${SPBOOST_LIB_DIR}
SPCOMP2_RPATH_DEBUG ?= ${OpenEXR_ROOT}/lib:${OpenColorIO_ROOT}/lib:${Field3D_ROOT}/lib/debug:${LIBRAW_LIBDIR}:${OpenVDB_ROOT}/lib/debug:${Libheif_ROOT}/lib:shots/spi/home/lib/arnold/rhel7/libde265-1.0.3/lib:${TBB_ROOT}/lib/intel64/gcc4.7:${SPBOOST_LIB_DIR}
PYSPCOMP2_RPATH_OPT ?= ${SPCOMP2_RPATH_OPT}:${OIIO_SPCOMP2_PATH}/lib:${PYTHON_LIBRARY_DIR}
PYSPCOMP2_RPATH_DEBUG ?= ${SPCOMP2_RPATH_DEBUG}:${OIIO_SPCOMP2_PATH}/lib/debug:${PYTHON_LIBRARY_DIR}
spcomp2: MY_CMAKE_FLAGS += \
-DCMAKE_SKIP_BUILD_RPATH:BOOL=OFF \
-DCMAKE_INSTALL_RPATH=$(SPCOMP2_INSTALL_ROOT)/OpenImageIO/$(SPARCH)/v$(OPENIMAGEIO_SPCOMP2_VERSION)/lib \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=ON \
-DPYLIB_INCLUDE_SONAME:BOOL=ON \
-DPYLIB_LIB_PREFIX:BOOL=ON \
-DPYMODULE_SUFFIX="V${OPENIMAGEIO_SPCOMP2_VERSION}"
spcomp2: dist
spcomp2_debug: MY_CMAKE_FLAGS += \
-DCMAKE_SKIP_BUILD_RPATH:BOOL=OFF \
-DCMAKE_INSTALL_RPATH=$(SPCOMP2_INSTALL_ROOT)/OpenImageIO/$(SPARCH)/v$(OPENIMAGEIO_SPCOMP2_VERSION)/lib \
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=ON \
-DPYLIB_INCLUDE_SONAME:BOOL=ON \
-DPYLIB_LIB_PREFIX:BOOL=ON \
-DPYMODULE_SUFFIX="V${OPENIMAGEIO_SPCOMP2_VERSION}"
spcomp2_debug: debug
spcomp2_install_fixup_rhel7: spcomp2 spcomp2_debug
echo $(SPCOMP2_INSTALL_ROOT)
patchelf --set-rpath ${SPCOMP2_RPATH_OPT} ${dist_dir}/lib/libOpenImageIO$(OIIO_LIBNAME_SUFFIX).so
patchelf --set-rpath ${SPCOMP2_RPATH_DEBUG} ${dist_dir}.debug/lib/libOpenImageIO$(OIIO_LIBNAME_SUFFIX).so
patchelf --set-rpath ${SPCOMP2_RPATH_OPT} ${dist_dir}/lib/libOpenImageIO_Util$(OIIO_LIBNAME_SUFFIX).so
patchelf --set-rpath ${SPCOMP2_RPATH_DEBUG} ${dist_dir}.debug/lib/libOpenImageIO_Util$(OIIO_LIBNAME_SUFFIX).so
patchelf --set-rpath ${PYSPCOMP2_RPATH_OPT} ${dist_dir}/python/libPyOpenImageIO.so
patchelf --set-rpath ${PYSPCOMP2_RPATH_DEBUG} ${dist_dir}.debug/python/libPyOpenImageIO.so
# This goal can't start with 'install' because something elsewhere picks
# it up and starts doing bad things
spcomp2_install: spcomp2_install_fixup_${SP_OS}
perl -I/usr/local/spi/lib/make /usr/local/spi/bin/spcomp_install.pl -m installhost \
--project=OpenImageIO \
--version=$(OPENIMAGEIO_SPCOMP2_VERSION) \
--root=$(SPCOMP2_INSTALL_ROOT) \
--arch=$(SPARCH) \
--headers=$(subst $(space),$(comma),$(wildcard ${dist_dir}/include/OpenImageIO/*)) \
--cflags= --static_lflags="$(LINK_BOOST) $(LINK_OPENEXR) -lpthread" \
--namespace=${NAMESPACE} \
--srcdir=${dist_dir}/lib \
--builddir_o=${dist_dir}/lib \
--builddir_d=${dist_dir}.debug/lib
perl -I/usr/local/spi/lib/make /usr/local/spi/bin/spcomp_install.pl -m installhost \
--project=OpenImageIO_Util \
--version=$(OPENIMAGEIO_SPCOMP2_VERSION) \
--root=$(SPCOMP2_INSTALL_ROOT) \
--arch=$(SPARCH) \
--headers=$(subst $(space),$(comma),$(wildcard ${dist_dir}/include/OpenImageIO/*)) \
--cflags= --static_lflags="$(LINK_BOOST) $(LINK_OPENEXR) -lpthread" \
--namespace=${NAMESPACE} \
--srcdir=${dist_dir}/lib \
--builddir_o=${dist_dir}/lib \
--builddir_d=${dist_dir}.debug/lib
perl -I/usr/local/spi/lib/make /usr/local/spi/bin/spcomp_install.pl -m installhost \
--project=PyOpenImageIO \
--version=$(OPENIMAGEIO_SPCOMP2_VERSION) \
--root=$(SPCOMP2_INSTALL_ROOT) \
--arch=$(SPPYARCH) \
--cflags= --static_lflags="$(LINK_BOOST) $(LINK_OPENEXR) -lpthread"\
--namespace=${NAMESPACE} \
--srcdir=${dist_dir}/python \
--builddir_o=${dist_dir}/python \
--builddir_d=${dist_dir}.debug/python
-9
View File
@@ -2,15 +2,6 @@ option (${PROJ_NAME}_SPIREZ "Enable extra bits for building for SPI Rez install"
set (${PROJ_NAME}_REZ_PACKAGE_NAME CACHE STRING "${PROJECT_NAME}")
if (${PROJ_NAME}_SPIREZ)
# message (STATUS "Creating package.py from package.py.in")
# configure_file ("${PROJECT_SOURCE_DIR}/site/spi/rez/package.py.in" "${CMAKE_BINARY_DIR}/package.py")
set (appcfg_filename "${CMAKE_BINARY_DIR}/${PROJECT_NAME}_${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK}.xml")
configure_file ("${PROJECT_SOURCE_DIR}/site/spi/appcfg.xml.in" "${appcfg_filename}")
# install (FILES ${CMAKE_BINARY_DIR}/package.py
# "${PROJECT_SOURCE_DIR}/site/spi/rez/CMakeLists.txt"
# ${appcfg_filename}
# DESTINATION ${CMAKE_INSTALL_PREFIX}
# COMPONENT developer)
endif ()
-18
View File
@@ -1,18 +0,0 @@
#!/usr/bin/env python
# This helper script takes a major.minor.patch semantic version string
# ("2.1.1") and reformats it into the dot-less zero-padded version like
# "20101". This is necessary to turn external release designations into
# integer SpComp2 version numbers.
from __future__ import print_function
from __future__ import absolute_import
import sys
if len(sys.argv) != 2 :
print('Need 1 argument: version number with dots')
exit(1)
vers = sys.argv[1]
parts = vers.split('.')
print ('{:d}{:02d}{:02d}'.format(int(parts[0]), int(parts[1]), int(parts[2])))
+25
View File
@@ -0,0 +1,25 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright Contributors to the OpenImageIO Project.
sonar.host.url=https://sonarcloud.io
# Required metadata
sonar.organization=openimageio
sonar.projectName=OpenImageIO
sonar.projectVersion=1.0
sonar.projectKey=OpenImageIO_oiio
# Source properties
sonar.sources=src
sonar.exclusions=src/doc/**,src/include/OpenImageIO/detail/pugixml/**,src/libutil/stb_sprintf.h,src/libutil/xxhash.cpp,src/include/OpenImageIO/detail/farmhash.h,src/libutil/farmhash.cpp
sonar.sourceEncoding=UTF-8
# C/C++ analyzer properties
sonar.cfamily.build-wrapper-output=build/bw_output
sonar.cfamily.gcov.reportsPath=_coverage
sonar.coverage.exclusions=src/iv/**,src/include/OpenImageIO/detail/pugixml/**,src/include/OpenImageIO/detail/fmt/**,src/libOpenImageIO/kissfft.hh
sonar.cfamily.cache.enabled=true
sonar.cfamily.cache.path=/tmp/sonarcache
sonar.verbose=false
+1 -1
View File
@@ -1,5 +1,5 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
add_oiio_plugin (bmpinput.cpp bmpoutput.cpp bmp_pvt.cpp)
+33 -26
View File
@@ -1,10 +1,9 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#include <cstdio>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
@@ -18,23 +17,21 @@ namespace bmp_pvt {
/// Helper - write, with error detection
template<class T>
bool
fwrite(FILE* fd, const T* buf)
fwrite(Filesystem::IOProxy* fd, const T* buf)
{
size_t n = std::fwrite(buf, sizeof(T), 1, fd);
return n == 1;
return fd->write(buf, sizeof(T)) == sizeof(T);
}
/// Helper - read, with error detection
template<class T>
bool
fread(FILE* fd, T* buf, size_t itemsize = sizeof(T))
fread(Filesystem::IOProxy* fd, T* buf, size_t itemsize = sizeof(T))
{
size_t n = std::fread(buf, itemsize, 1, fd);
return n == 1;
return fd->read(buf, itemsize) == itemsize;
}
bool
BmpFileHeader::read_header(FILE* fd)
BmpFileHeader::read_header(Filesystem::IOProxy* fd)
{
if (!fread(fd, &magic) || !fread(fd, &fsize) || !fread(fd, &res1)
|| !fread(fd, &res2) || !fread(fd, &offset)) {
@@ -49,7 +46,7 @@ BmpFileHeader::read_header(FILE* fd)
bool
BmpFileHeader::write_header(FILE* fd)
BmpFileHeader::write_header(Filesystem::IOProxy* fd)
{
if (bigendian())
swap_endian();
@@ -73,8 +70,8 @@ BmpFileHeader::isBmp() const
case MAGIC_CI:
case MAGIC_CP:
case MAGIC_PT: return true;
default: return false;
}
return false;
}
@@ -90,12 +87,13 @@ BmpFileHeader::swap_endian(void)
bool
DibInformationHeader::read_header(FILE* fd)
DibInformationHeader::read_header(Filesystem::IOProxy* fd)
{
if (!fread(fd, &size))
return false;
if (size == WINDOWS_V3 || size == WINDOWS_V4 || size == WINDOWS_V5) {
if (size == WINDOWS_V3 || size == WINDOWS_V4 || size == WINDOWS_V5
|| size == UNDOCHEADER52 || size == UNDOCHEADER56) {
if (!fread(fd, &width) || !fread(fd, &height) || !fread(fd, &cplanes)
|| !fread(fd, &bpp) || !fread(fd, &compression)
|| !fread(fd, &isize) || !fread(fd, &hres) || !fread(fd, &vres)
@@ -103,16 +101,25 @@ DibInformationHeader::read_header(FILE* fd)
return false;
}
if ((size == WINDOWS_V3 && bpp == 16 && compression == 3)
|| size == WINDOWS_V4 || size == WINDOWS_V5 || size == UNDOCHEADER52
|| size == UNDOCHEADER56) {
if (!fread(fd, &red_mask) || !fread(fd, &green_mask)
|| !fread(fd, &blue_mask)) {
return false;
}
if (size != UNDOCHEADER52 && !fread(fd, &alpha_mask)) {
return false;
}
}
if (size == WINDOWS_V4 || size == WINDOWS_V5) {
if (!fread(fd, &red_mask) || !fread(fd, &blue_mask)
|| !fread(fd, &green_mask) || !fread(fd, &alpha_mask)
|| !fread(fd, &cs_type) || !fread(fd, &red_x)
|| !fread(fd, &red_y) || !fread(fd, &red_z)
|| !fread(fd, &green_x) || !fread(fd, &green_y)
|| !fread(fd, &green_z) || !fread(fd, &blue_x)
|| !fread(fd, &blue_y) || !fread(fd, &blue_z)
|| !fread(fd, &gamma_x) || !fread(fd, &gamma_y)
|| !fread(fd, &gamma_z)) {
if (!fread(fd, &cs_type) || !fread(fd, &red_x) || !fread(fd, &red_y)
|| !fread(fd, &red_z) || !fread(fd, &green_x)
|| !fread(fd, &green_y) || !fread(fd, &green_z)
|| !fread(fd, &blue_x) || !fread(fd, &blue_y)
|| !fread(fd, &blue_z) || !fread(fd, &gamma_x)
|| !fread(fd, &gamma_y) || !fread(fd, &gamma_z)) {
return false;
}
}
@@ -124,7 +131,7 @@ DibInformationHeader::read_header(FILE* fd)
}
}
} else if (size == OS2_V1) {
// some of theses fields are smaller than in WINDOWS_Vx headers,
// some of these fields are smaller than in WINDOWS_Vx headers,
// so we read into 16 bit ints and copy.
uint16_t width16 = 0;
uint16_t height16 = 0;
@@ -143,7 +150,7 @@ DibInformationHeader::read_header(FILE* fd)
bool
DibInformationHeader::write_header(FILE* fd)
DibInformationHeader::write_header(Filesystem::IOProxy* fd)
{
if (bigendian())
swap_endian();
@@ -156,7 +163,7 @@ DibInformationHeader::write_header(FILE* fd)
return false;
}
return (true);
return true;
}
+44 -31
View File
@@ -1,22 +1,29 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#pragma once
OIIO_PLUGIN_NAMESPACE_BEGIN
// Docs reminders:
// https://en.wikipedia.org/wiki/BMP_file_format
// https://web.archive.org/web/20150127132443/https://forums.adobe.com/message/3272950
namespace bmp_pvt {
// size of the BMP file header (the first header that occur in BMP file)
const int BMP_HEADER_SIZE = 14;
// sizes of various DIB haders
const int OS2_V1 = 12;
const int WINDOWS_V3 = 40;
const int WINDOWS_V4 = 108;
const int WINDOWS_V5 = 124;
// sizes of various DIB headers
const int OS2_V1 = 12;
const int WINDOWS_V3 = 40;
const int UNDOCHEADER52 = 52; // 0x34
const int UNDOCHEADER56 = 56; // 0x38
const int WINDOWS_V4 = 108;
const int WINDOWS_V5 = 124;
// bmp magic numbers
const int16_t MAGIC_BM = 0x4D42;
@@ -29,16 +36,22 @@ const int32_t NO_COMPRESSION = 0; // BI_RGB
const int32_t RLE8_COMPRESSION = 1; // BI_RLE8
const int32_t RLE4_COMPRESSION = 2; // BI_RLE4
enum class CSType {
CalibratedRGB = 0,
DeviceDependentRGB = 1,
DeviceDependentCMYK = 2
};
// store informations about BMP file
// store information about BMP file
class BmpFileHeader {
public:
// reads informations about BMP file
bool read_header(FILE* fd);
// reads information about BMP file
bool read_header(Filesystem::IOProxy* fd);
// writes information about bmp file to given file
bool write_header(FILE* fd);
bool write_header(Filesystem::IOProxy* fd);
// return true if given file is BMP file
bool isBmp() const;
@@ -55,11 +68,11 @@ private:
// stores information about bitmap
class DibInformationHeader {
public:
// reads informations about bitmap
bool read_header(FILE* fd);
// reads information about bitmap
bool read_header(Filesystem::IOProxy* fd);
// writes informations about bitmap
bool write_header(FILE* fd);
// writes information about bitmap
bool write_header(Filesystem::IOProxy* fd);
int32_t size; // size of the header
int32_t width; // bitmap width in pixels
@@ -78,23 +91,23 @@ public:
// in most cases ignored
// added in Version 4 of the format
int32_t red_mask;
int32_t blue_mask;
int32_t green_mask;
int32_t alpha_mask;
int32_t cs_type; //color space type
int32_t red_x;
int32_t red_y;
int32_t red_z;
int32_t green_x;
int32_t green_y;
int32_t green_z;
int32_t blue_x;
int32_t blue_y;
int32_t blue_z;
int32_t gamma_x;
int32_t gamma_y;
int32_t gamma_z;
int32_t red_mask = 0;
int32_t blue_mask = 0;
int32_t green_mask = 0;
int32_t alpha_mask = 0;
int32_t cs_type = 0; // color space type
int32_t red_x = 0;
int32_t red_y = 0;
int32_t red_z = 0;
int32_t green_x = 0;
int32_t green_y = 0;
int32_t green_z = 0;
int32_t blue_x = 0;
int32_t blue_y = 0;
int32_t blue_z = 0;
int32_t gamma_x = 0;
int32_t gamma_y = 0;
int32_t gamma_z = 0;
// added in Version 5 of the format
int32_t intent;
+190 -94
View File
@@ -1,6 +1,6 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#include <cstdio>
@@ -17,48 +17,61 @@ using namespace bmp_pvt;
class BmpInput final : public ImageInput {
public:
BmpInput() { init(); }
virtual ~BmpInput() { close(); }
virtual const char* format_name(void) const override { return "bmp"; }
virtual bool valid_file(const std::string& filename) const override;
virtual bool open(const std::string& name, ImageSpec& newspec) override;
virtual bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
virtual bool close(void) override;
virtual bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
~BmpInput() override { close(); }
const char* format_name(void) const override { return "bmp"; }
int supports(string_view feature) const override
{
return feature == "ioproxy";
}
bool valid_file(const std::string& filename) const override;
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config) override;
bool close(void) override;
bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
private:
int64_t m_padded_scanline_size;
int m_pad_size;
FILE* m_fd;
bmp_pvt::BmpFileHeader m_bmp_header;
bmp_pvt::DibInformationHeader m_dib_header;
std::string m_filename;
std::vector<bmp_pvt::color_table> m_colortable;
std::vector<unsigned char> fscanline; // temp space: read from file
std::vector<unsigned char> m_uncompressed; // uncompressed palette image
uint32_t m_right_shifts[3];
uint32_t m_bit_counts[3];
bool m_allgray;
void init(void)
{
m_padded_scanline_size = 0;
m_pad_size = 0;
m_fd = NULL;
m_filename.clear();
m_colortable.clear();
m_allgray = false;
fscanline.shrink_to_fit();
m_uncompressed.shrink_to_fit();
ioproxy_clear();
}
bool read_color_table();
bool color_table_is_all_gray();
bool read_rle_image();
bool ioeof() { return size_t(ioproxy()->tell()) == ioproxy()->size(); }
// Safe, clamped access to color table
const bmp_pvt::color_table& colortable(int i)
{
return m_colortable[clamp(i, 0, int(m_colortable.size() - 1))];
}
};
// Obligatory material to make this a recognizeable imageio plugin
// Obligatory material to make this a recognizable imageio plugin
OIIO_PLUGIN_EXPORTS_BEGIN
OIIO_EXPORT int bmp_imageio_version = OIIO_PLUGIN_VERSION;
@@ -83,13 +96,9 @@ OIIO_PLUGIN_EXPORTS_END
bool
BmpInput::valid_file(const std::string& filename) const
{
FILE* fd = Filesystem::fopen(filename, "rb");
if (!fd)
return false;
bmp_pvt::BmpFileHeader bmp_header;
bool ok = bmp_header.read_header(fd) && bmp_header.isBmp();
fclose(fd);
return ok;
bmp_pvt::BmpFileHeader header;
Filesystem::IOFile file(filename, Filesystem::IOProxy::Read);
return file.opened() && header.read_header(&file) && header.isBmp();
}
@@ -101,6 +110,28 @@ BmpInput::open(const std::string& name, ImageSpec& newspec)
return open(name, newspec, emptyconfig);
}
inline void
calc_shifts(uint32_t mask, uint32_t& count, uint32_t& right)
{
if (mask == 0) {
count = right = 0;
return;
}
uint32_t i;
for (i = 0; i < 32; i++, mask >>= 1) {
if (mask & 1)
break;
}
right = i;
for (i = 0; i < 32; i++, mask >>= 1) {
if (!(mask & 1))
break;
}
count = i;
}
bool
@@ -117,29 +148,36 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
// this behavior off.
bool monodetect = config["bmp:monochrome_detect"].get<int>(1);
m_fd = Filesystem::fopen(m_filename, "rb");
if (!m_fd) {
errorf("Could not open file \"%s\"", name);
ioproxy_retrieve_from_config(config);
if (!ioproxy_use_or_open(name))
return false;
}
ioseek(0);
// we read header of the file that we think is BMP file
if (!m_bmp_header.read_header(m_fd)) {
errorf("\"%s\": wrong bmp header size", m_filename);
if (!m_bmp_header.read_header(ioproxy())) {
errorfmt("\"{}\": wrong bmp header size", name);
close();
return false;
}
if (!m_bmp_header.isBmp()) {
errorf("\"%s\" is not a BMP file, magic number doesn't match",
m_filename);
errorfmt("\"{}\" is not a BMP file, magic number doesn't match", name);
close();
return false;
}
if (!m_dib_header.read_header(m_fd)) {
errorf("\"%s\": wrong bitmap header size", m_filename);
// Strutil::print(
// "Header: magic={:x} {}{} fsize={} res1={} res2={} offset={}\n",
// m_bmp_header.magic, char(m_bmp_header.magic & 0xff),
// char(m_bmp_header.magic >> 8), m_bmp_header.fsize, m_bmp_header.res1,
// m_bmp_header.res2, m_bmp_header.offset);
if (!m_dib_header.read_header(ioproxy())) {
errorfmt("\"{}\": wrong bitmap header size", name);
close();
return false;
}
// Strutil::print(
// "Header: size={}(0x{:02x}) width={} height={} cplanes={} bpp={}\n",
// m_dib_header.size, m_dib_header.size, m_dib_header.width,
// m_dib_header.height, m_dib_header.cplanes, m_dib_header.bpp);
const int nchannels = (m_dib_header.bpp == 32) ? 4 : 3;
const int height = (m_dib_header.height >= 0) ? m_dib_header.height
@@ -150,6 +188,26 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
m_spec.attribute("YResolution", (int)m_dib_header.vres);
m_spec.attribute("ResolutionUnit", "m");
}
if (m_spec.width < 1 || m_spec.height < 1 || m_spec.nchannels < 1
|| m_spec.image_bytes() < 1
|| m_spec.image_pixels() > std::numeric_limits<uint32_t>::max()) {
errorfmt(
"Invalid image size {} x {} ({} chans, {}), is likely corrupted",
m_spec.width, m_spec.height, m_spec.nchannels, m_spec.format);
close();
return false;
}
// Compute channel shifts & masks (only relevant for 16bpp case)
if (m_dib_header.red_mask == 0 || m_dib_header.green_mask == 0
|| m_dib_header.blue_mask == 0) {
m_dib_header.red_mask = 0b111110000000000;
m_dib_header.green_mask = 0b000001111100000;
m_dib_header.blue_mask = 0b000000000011111;
}
calc_shifts(m_dib_header.red_mask, m_bit_counts[0], m_right_shifts[0]);
calc_shifts(m_dib_header.green_mask, m_bit_counts[1], m_right_shifts[1]);
calc_shifts(m_dib_header.blue_mask, m_bit_counts[2], m_right_shifts[2]);
// computing size of one scanline - this is the size of one scanline that
// is stored in the file, not in the memory
@@ -161,7 +219,7 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
break;
case 16:
m_padded_scanline_size = ((m_spec.width << 1) + 3) & ~3;
m_spec.attribute("oiio:BitsPerSample", 4);
m_spec.attribute("oiio:BitsPerSample", m_bit_counts[0]);
break;
case 8:
m_padded_scanline_size = (m_spec.width + 3) & ~3;
@@ -185,6 +243,9 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
if (!read_color_table())
return false;
break;
default:
errorfmt("Unsupported BMP bit depth: {}", m_dib_header.bpp);
return false;
}
if (m_dib_header.bpp <= 16)
m_spec.attribute("bmp:bitsperpixel", m_dib_header.bpp);
@@ -195,6 +256,25 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
case WINDOWS_V5: m_spec.attribute("bmp:version", 5); break;
}
// Default presumption is that a BMP file is meant to look reasonable on a
// display, so assume it's sRGB. This is not really correct -- see the
// comments below.
m_spec.attribute("oiio:ColorSpace", "sRGB");
#if 0
if (m_dib_header.size >= WINDOWS_V4
&& m_dib_header.cs_type == CSType::CalibratedRGB) {
// FIXME: V4 and newer BMP files have color primary information, but
// we currently ignore it and presume sRGB. I don't know how
// frequently the color primaries are reliable or if anybody cares for
// this ancient format. We may come back to this later.
}
if (m_dib_header.size >= WINDOWS_V4
&& m_dib_header.cs_type == CSType::DeviceDependentCMYK) {
// FIXME: I've never encountered a BMP file that holds CMYK data. If
// this is a problem for people, we can return to fix this later.
}
#endif
// Bite the bullet and uncompress now, for simplicity
if (m_dib_header.compression == RLE4_COMPRESSION
|| m_dib_header.compression == RLE8_COMPRESSION) {
@@ -205,13 +285,6 @@ BmpInput::open(const std::string& name, ImageSpec& newspec,
}
}
if (m_spec.width < 1 || m_spec.height < 1 || m_spec.nchannels < 1
|| m_spec.image_bytes() < 1) {
errorfmt("Invalid image size {} x {} ({} chans, {})", m_spec.width,
m_spec.height, m_spec.nchannels, m_spec.format);
return false;
}
newspec = m_spec;
return true;
}
@@ -222,16 +295,25 @@ bool
BmpInput::read_rle_image()
{
int rletype = m_dib_header.compression == RLE4_COMPRESSION ? 4 : 8;
m_spec.attribute("bmp:compression", rletype == 4 ? "rle4" : "rle8");
m_spec.attribute("compression", rletype == 4 ? "rle4" : "rle8");
m_uncompressed.clear();
m_uncompressed.resize(m_spec.height * m_spec.width);
// Note: the clear+resize zeroes out the buffer
bool err = false;
bool ok = true;
int y = 0, x = 0;
while (!err && !feof(m_fd)) {
while (ok) {
// Strutil::print("currently at {},{}\n", x, y);
unsigned char rle_pair[2];
if (fread(rle_pair, 1, 2, m_fd) != 2) {
err = true;
if (!ioread(rle_pair, 2)) {
ok = false;
// Strutil::print("hit end of file at {},{}\n", x, y);
break;
}
if (y >= m_spec.height) { // out of y bounds
errorfmt(
"BMP might be corrupted, it is referencing an out-of-bounds pixel coordinte ({},{})",
x, y);
ok = false;
break;
}
int npixels = rle_pair[0];
@@ -240,26 +322,31 @@ BmpInput::read_rle_image()
// [0,0] is end of line marker
x = 0;
++y;
// Strutil::print("end of line, moving to {},{}\n", x, y);
} else if (npixels == 0 && value == 1) {
// [0,1] is end of bitmap marker
// Strutil::print("end of bitmap\n");
break;
} else if (npixels == 0 && value == 2) {
// [0,2] is a "delta" -- two more bytes reposition the
// current pixel position that we're reading.
unsigned char offset[2];
err |= (fread(offset, 1, 2, m_fd) != 2);
ok &= ioread(offset, 2);
x += offset[0];
y += offset[1];
// Strutil::print("offset by {:d},{:d} to {},{}\n", offset[0],
// offset[1], x, y);
} else if (npixels == 0) {
// [0,n>2] is an "absolute" run of pixel data.
// n is the number of pixel indices that follow, but note
// that it pads to word size.
int npixels = value;
int nbytes = (rletype == 4)
? round_to_multiple((npixels + 1) / 2, 2)
: round_to_multiple(npixels, 2);
npixels = value;
int nbytes = (rletype == 4)
? round_to_multiple((npixels + 1) / 2, 2)
: round_to_multiple(npixels, 2);
// Strutil::print("rle of {} pixels at {},{}\n", npixels, x, y);
unsigned char absolute[256];
err |= (fread(absolute, 1, nbytes, m_fd) != size_t(nbytes));
ok &= ioread(absolute, nbytes);
for (int i = 0; i < npixels; ++i, ++x) {
if (rletype == 4)
value = (i & 1) ? (absolute[i / 2] & 0x0f)
@@ -271,6 +358,7 @@ BmpInput::read_rle_image()
}
} else {
// [n>0,p] is a run of n pixels.
// Strutil::print("direct read {} pixels at {},{}\n", npixels, x, y);
for (int i = 0; i < npixels; ++i, ++x) {
int v;
if (rletype == 4)
@@ -282,7 +370,7 @@ BmpInput::read_rle_image()
}
}
}
return !err;
return ok;
}
@@ -304,9 +392,10 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
|| m_dib_header.compression == RLE8_COMPRESSION) {
for (int x = 0; x < m_spec.width; ++x) {
int p = m_uncompressed[(m_spec.height - 1 - y) * m_spec.width + x];
mscanline[3 * x] = m_colortable[p].r;
mscanline[3 * x + 1] = m_colortable[p].g;
mscanline[3 * x + 2] = m_colortable[p].b;
auto& c = colortable(p);
mscanline[3 * x] = c.r;
mscanline[3 * x + 1] = c.g;
mscanline[3 * x + 2] = c.b;
}
return true;
}
@@ -317,13 +406,8 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
const int64_t scanline_off = y * m_padded_scanline_size;
fscanline.resize(m_padded_scanline_size);
Filesystem::fseek(m_fd, m_bmp_header.offset + scanline_off, SEEK_SET);
size_t n = fread(fscanline.data(), 1, m_padded_scanline_size, m_fd);
if (n != (size_t)m_padded_scanline_size) {
if (feof(m_fd))
errorf("Hit end of file unexpectedly");
else
errorf("read error");
ioseek(m_bmp_header.offset + scanline_off);
if (!ioread(fscanline.data(), m_padded_scanline_size)) {
return false; // Read failed
}
@@ -339,43 +423,56 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
}
if (m_dib_header.bpp == 16) {
const uint16_t RED = 0x7C00;
const uint16_t GREEN = 0x03E0;
const uint16_t BLUE = 0x001F;
for (unsigned int i = 0, j = 0; j < scanline_bytes; i += 2, j += 3) {
uint16_t pixel = (uint16_t) * (&fscanline[i]);
mscanline[j] = (uint8_t)((pixel & RED) >> 8);
mscanline[j + 1] = (uint8_t)((pixel & GREEN) >> 4);
mscanline[j + 2] = (uint8_t)(pixel & BLUE);
uint16_t pixel = *(uint16_t*)&fscanline[i];
mscanline[j + 0]
= (uint8_t)bit_range_convert((pixel & m_dib_header.red_mask)
>> m_right_shifts[0],
m_bit_counts[0], 8);
mscanline[j + 1]
= (uint8_t)bit_range_convert((pixel & m_dib_header.green_mask)
>> m_right_shifts[1],
m_bit_counts[1], 8);
mscanline[j + 2]
= (uint8_t)bit_range_convert((pixel & m_dib_header.blue_mask)
>> m_right_shifts[2],
m_bit_counts[2], 8);
}
}
if (m_dib_header.bpp == 8) {
if (m_allgray) {
// Keep it as 1-channel image because all colors are gray
for (unsigned int i = 0; i < scanline_bytes; ++i) {
mscanline[i] = m_colortable[fscanline[i]].r;
mscanline[i] = colortable(fscanline[i]).r;
}
} else {
// Expand palette image into 3-channel RGB (existing code)
for (unsigned int i = 0, j = 0; j < scanline_bytes; ++i, j += 3) {
mscanline[j] = m_colortable[fscanline[i]].r;
mscanline[j + 1] = m_colortable[fscanline[i]].g;
mscanline[j + 2] = m_colortable[fscanline[i]].b;
auto& c = colortable(fscanline[i]);
mscanline[j] = c.r;
mscanline[j + 1] = c.g;
mscanline[j + 2] = c.b;
}
}
}
if (m_dib_header.bpp == 4) {
for (unsigned int i = 0, j = 0; j < scanline_bytes; ++i, j += 6) {
uint8_t mask = 0xF0;
mscanline[j] = m_colortable[(fscanline[i] & mask) >> 4].r;
mscanline[j + 1] = m_colortable[(fscanline[i] & mask) >> 4].g;
mscanline[j + 2] = m_colortable[(fscanline[i] & mask) >> 4].b;
uint8_t mask = 0xF0;
{
auto& c = colortable((fscanline[i] & mask) >> 4);
mscanline[j] = c.r;
mscanline[j + 1] = c.g;
mscanline[j + 2] = c.b;
}
if (j + 3 >= scanline_bytes)
break;
mask = 0x0F;
mscanline[j + 3] = m_colortable[fscanline[i] & mask].r;
mscanline[j + 4] = m_colortable[fscanline[i] & mask].g;
mscanline[j + 5] = m_colortable[fscanline[i] & mask].b;
mask = 0x0F;
{
auto& c = colortable(fscanline[i] & mask);
mscanline[j + 3] = c.r;
mscanline[j + 4] = c.g;
mscanline[j + 5] = c.b;
}
}
}
if (m_dib_header.bpp == 1) {
@@ -386,9 +483,10 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
int index = 0;
if (fscanline[i] & (1 << j))
index = 1;
mscanline[k] = m_colortable[index].r;
mscanline[k + 1] = m_colortable[index].g;
mscanline[k + 2] = m_colortable[index].b;
auto& c = colortable(index);
mscanline[k] = c.r;
mscanline[k + 1] = c.g;
mscanline[k + 2] = c.b;
}
}
}
@@ -397,12 +495,9 @@ BmpInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
bool inline BmpInput::close(void)
bool
BmpInput::close(void)
{
if (m_fd) {
fclose(m_fd);
m_fd = NULL;
}
init();
return true;
}
@@ -418,7 +513,7 @@ BmpInput::read_color_table(void)
// m_dib_header.cpalete entries
if (m_dib_header.cpalete < 0
|| m_dib_header.cpalete > (1 << m_dib_header.bpp)) {
errorf("Possible corrupted header, invalid palette size");
errorfmt("Possible corrupted header, invalid palette size");
return false;
}
const int32_t colors = (m_dib_header.cpalete) ? m_dib_header.cpalete
@@ -429,20 +524,21 @@ BmpInput::read_color_table(void)
entry_size = 3;
m_colortable.resize(colors);
for (int i = 0; i < colors; i++) {
size_t n = fread(&m_colortable[i], 1, entry_size, m_fd);
if (n != entry_size) {
if (feof(m_fd))
if (!ioread(&m_colortable[i], entry_size)) {
if (ioeof())
errorfmt(
"Hit end of file unexpectedly while reading color table on color {}/{} (read {}, expected {})",
i, colors, n, entry_size);
"Hit end of file unexpectedly while reading color table on color {}/{})",
i, colors);
else
errorf("read error while reading color table");
errorfmt("read error while reading color table");
return false; // Read failed
}
}
return true; // ok
}
bool
BmpInput::color_table_is_all_gray(void)
{
+49 -61
View File
@@ -1,6 +1,6 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#include <cstdio>
@@ -18,21 +18,20 @@ using namespace bmp_pvt;
class BmpOutput final : public ImageOutput {
public:
BmpOutput() { init(); }
virtual ~BmpOutput() { close(); }
virtual const char* format_name(void) const override { return "bmp"; }
virtual int supports(string_view feature) const override;
virtual bool open(const std::string& name, const ImageSpec& spec,
OpenMode mode) override;
virtual bool close(void) override;
virtual bool write_scanline(int y, int z, TypeDesc format, const void* data,
stride_t xstride) override;
virtual bool write_tile(int x, int y, int z, TypeDesc format,
const void* data, stride_t xstride,
stride_t ystride, stride_t zstride) override;
~BmpOutput() override { close(); }
const char* format_name(void) const override { return "bmp"; }
int supports(string_view feature) const override;
bool open(const std::string& name, const ImageSpec& spec,
OpenMode mode) override;
bool close(void) override;
bool write_scanline(int y, int z, TypeDesc format, const void* data,
stride_t xstride) override;
bool write_tile(int x, int y, int z, TypeDesc format, const void* data,
stride_t xstride, stride_t ystride,
stride_t zstride) override;
private:
int64_t m_padded_scanline_size;
FILE* m_fd;
std::string m_filename;
bmp_pvt::BmpFileHeader m_bmp_header;
bmp_pvt::DibInformationHeader m_dib_header;
@@ -45,8 +44,8 @@ private:
void init(void)
{
m_padded_scanline_size = 0;
m_fd = NULL;
m_filename.clear();
ioproxy_clear();
}
void create_and_write_file_header(void);
@@ -56,7 +55,7 @@ private:
// Obligatory material to make this a recognizeable imageio plugin
// Obligatory material to make this a recognizable imageio plugin
OIIO_PLUGIN_EXPORTS_BEGIN
OIIO_EXPORT ImageOutput*
@@ -74,7 +73,7 @@ OIIO_PLUGIN_EXPORTS_END
int
BmpOutput::supports(string_view feature) const
{
return (feature == "alpha");
return (feature == "alpha" || feature == "ioproxy");
}
@@ -82,21 +81,11 @@ BmpOutput::supports(string_view feature) const
bool
BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
{
if (mode != Create) {
errorf("%s does not support subimages or MIP levels", format_name());
if (!check_open(mode, spec, { 0, 65535, 0, 65535, 0, 1, 0, 4 },
uint64_t(OpenChecks::Disallow2Channel)))
return false;
}
// saving 'name' and 'spec' for later use
m_filename = name;
m_spec = spec;
if (m_spec.nchannels != 1 && m_spec.nchannels != 3
&& m_spec.nchannels != 4) {
errorf("%s does not support %d-channel images\n", format_name(),
m_spec.nchannels);
return false;
}
// Only support 8 bit channels for now.
m_spec.set_format(TypeDesc::UINT8);
@@ -104,15 +93,13 @@ BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
int64_t file_size = m_spec.image_bytes() + BMP_HEADER_SIZE + WINDOWS_V3;
if (file_size >= int64_t(1) << 32) {
errorf("%s does not support files over 4GB in size\n", format_name());
errorfmt("{} does not support files over 4GB in size\n", format_name());
return false;
}
m_fd = Filesystem::fopen(m_filename, "wb");
if (!m_fd) {
errorf("Could not open \"%s\"", m_filename);
ioproxy_retrieve_from_config(m_spec);
if (!ioproxy_use_or_open(name))
return false;
}
// Scanline size is rounded up to align to 4-byte boundary
m_padded_scanline_size = round_to_multiple(m_spec.scanline_bytes(), 4);
@@ -120,7 +107,7 @@ BmpOutput::open(const std::string& name, const ImageSpec& spec, OpenMode mode)
create_and_write_file_header();
create_and_write_bitmap_header();
m_image_start = Filesystem::ftell(m_fd);
m_image_start = iotell();
// If user asked for tiles -- which this format doesn't support, emulate
// it by buffering the whole image.
@@ -136,16 +123,22 @@ bool
BmpOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
stride_t xstride)
{
if (y > m_spec.height) {
errorf("Attempt to write too many scanlines to %s", m_filename);
if (!ioproxy_opened()) {
errorfmt("write_scanline called but file is not open.");
return false;
}
if (y > m_spec.y + m_spec.height) {
errorfmt("Attempt to write too many scanlines to {}", m_filename);
close();
return false;
}
y -= m_spec.y;
if (m_spec.width >= 0)
y = (m_spec.height - y - 1);
int64_t scanline_off = y * m_padded_scanline_size;
Filesystem::fseek(m_fd, m_image_start + scanline_off, SEEK_SET);
ioseek(m_image_start + scanline_off);
m_scratch.clear();
data = to_native_scanline(format, data, xstride, m_scratch, m_dither, y, z);
@@ -159,8 +152,7 @@ BmpOutput::write_scanline(int y, int z, TypeDesc format, const void* data,
i += m_spec.nchannels)
std::swap(m_buf[i], m_buf[i + 2]);
size_t byte_count = fwrite(&m_buf[0], 1, m_buf.size(), m_fd);
return byte_count == m_buf.size(); // true if wrote all bytes (no error)
return iowrite(&m_buf[0], m_buf.size());
}
@@ -169,9 +161,14 @@ bool
BmpOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
stride_t xstride, stride_t ystride, stride_t zstride)
{
if (!ioproxy_opened()) {
errorfmt("write_tile called but file is not open.");
return false;
}
// Emulate tiles by buffering the whole image
return copy_tile_to_image_buffer(x, y, z, format, data, xstride, ystride,
zstride, &m_tilebuffer[0]);
zstride, m_tilebuffer.data());
}
@@ -179,22 +176,21 @@ BmpOutput::write_tile(int x, int y, int z, TypeDesc format, const void* data,
bool
BmpOutput::close(void)
{
if (!m_fd) { // already closed
if (!ioproxy_opened()) { // already closed
init();
return true;
}
bool ok = true;
if (m_spec.tile_width) {
if (m_spec.tile_width && m_tilebuffer.size()) {
// Handle tile emulation -- output the buffered pixels
OIIO_DASSERT(m_tilebuffer.size());
ok &= write_scanlines(m_spec.y, m_spec.y + m_spec.height, 0,
m_spec.format, &m_tilebuffer[0]);
m_spec.format, m_tilebuffer.data());
std::vector<unsigned char>().swap(m_tilebuffer);
}
fclose(m_fd);
m_fd = NULL;
init();
return ok;
}
@@ -211,7 +207,7 @@ BmpOutput::create_and_write_file_header(void)
m_bmp_header.res2 = 0;
m_bmp_header.offset = BMP_HEADER_SIZE + WINDOWS_V3 + palettesize;
m_bmp_header.write_header(m_fd);
m_bmp_header.write_header(ioproxy());
}
@@ -240,28 +236,20 @@ BmpOutput::create_and_write_bitmap_header(void)
m_dib_header.hres = 0;
m_dib_header.vres = 0;
ParamValue* p = m_spec.find_attribute("ResolutionUnit", TypeDesc::STRING);
if (p && p->data()) {
std::string res_units = *(char**)p->data();
if (Strutil::iequals(res_units, "m")
|| Strutil::iequals(res_units, "pixel per meter")) {
ParamValue *resx = NULL, *resy = NULL;
resx = m_spec.find_attribute("XResolution", TypeDesc::INT32);
if (resx && resx->data())
m_dib_header.hres = *(int*)resx->data();
resy = m_spec.find_attribute("YResolution", TypeDesc::INT32);
if (resy && resy->data())
m_dib_header.vres = *(int*)resy->data();
}
string_view res_units = m_spec.get_string_attribute("ResolutionUnit");
if (Strutil::iequals(res_units, "m")
|| Strutil::iequals(res_units, "pixel per meter")) {
m_dib_header.hres = m_spec.get_int_attribute("XResolution");
m_dib_header.vres = m_spec.get_int_attribute("YResolution");
}
m_dib_header.write_header(m_fd);
m_dib_header.write_header(ioproxy());
// Write palette, if there is one. This is only used for grayscale
// images, and the palette is just the 256 possible gray values.
for (int i = 0; i < m_dib_header.cpalete; ++i) {
unsigned char val[4] = { uint8_t(i), uint8_t(i), uint8_t(i), 255 };
fwrite(&val, 1, 4, m_fd);
iowrite(&val, 4);
}
}
-266
View File
@@ -1,266 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT (openexr)
SET(OPENEXR_VERSION_MAJOR "2")
SET(OPENEXR_VERSION_MINOR "2")
SET(OPENEXR_VERSION_PATCH "0")
SET(OPENEXR_VERSION ${OPENEXR_VERSION_MAJOR}.${OPENEXR_VERSION_MINOR}.${OPENEXR_VERSION_PATCH})
SET(OPENEXR_VERSION_API ${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR})
# enable the tests
ENABLE_TESTING()
# distro building
SET(CPACK_PACKAGE_VERSION_MAJOR "${OPENEXR_VERSION_MAJOR}")
SET(CPACK_PACKAGE_VERSION_MINOR "${OPENEXR_VERSION_MINOR}")
SET(CPACK_PACKAGE_VERSION_PATCH "${OPENEXR_VERSION_PATCH}")
SET(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_PACKAGE_FILE_NAME
"${CMAKE_PROJECT_NAME}-${OPENEXR_VERSION}"
)
set(CPACK_SOURCE_IGNORE_FILES
"/.git*;/.cvs*;${CPACK_SOURCE_IGNORE_FILES}")
INCLUDE ( CPack )
# Allow the developer to select if Dynamic or Static libraries are built
OPTION (BUILD_SHARED_LIBS "Build Shared Libraries" ON)
OPTION (USE_ZLIB_WINAPI "Use ZLib Win API" OFF)
OPTION (NAMESPACE_VERSIONING "Use Namespace Versioning" ON)
OPTION (BUILD_UTILS "Build the binary/utility programs" ON)
OPTION (BUILD_TESTS "Build the tests" ON)
# Setup osx rpathing
SET (CMAKE_MACOSX_RPATH 1)
SET (BUILD_WITH_INSTALL_RPATH 1)
ADD_DEFINITIONS ( -DHAVE_CONFIG_H -DILM_IMF_TEST_IMAGEDIR="${CMAKE_SOURCE_DIR}/IlmImfTest/" )
INCLUDE_DIRECTORIES (
${CMAKE_CURRENT_BINARY_DIR}/config
IlmImf
IlmImfUtil
exrmaketiled
exrenvmap
exrmakepreview
exrmultiview
IlmImfFuzzTest
)
FIND_PACKAGE(ZLIB REQUIRED)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
IF (NOT WIN32)
SET ( PTHREAD_LIB pthread )
ENDIF()
INCLUDE_DIRECTORIES ( ${ILMBASE_PACKAGE_PREFIX}/include/OpenEXR )
LINK_DIRECTORIES ( ${ILMBASE_PACKAGE_PREFIX}/lib )
MESSAGE ( "ILMBASE_PACKAGE_PREFIX = " ${ILMBASE_PACKAGE_PREFIX})
SET (LIB_TYPE STATIC)
IF (BUILD_SHARED_LIBS)
# User wants to build Dynamic Libraries, so change the LIB_TYPE variable to CMake keyword 'SHARED'
SET (LIB_TYPE SHARED)
IF (WIN32)
ADD_DEFINITIONS(-DOPENEXR_DLL)
ENDIF ()
ENDIF ()
IF (USE_ZLIB_WINAPI)
ADD_DEFINITIONS(-DZLIB_WINAPI)
ENDIF ()
# Test for GCC-style inline asm support with AVX instructions
INCLUDE (CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES (
"
int main()
{
#if defined(__GNUC__) && defined(__SSE2__)
int n = 0;
int eax = 0;
int edx = 0;
__asm__(
\"xgetbv ;\"
\"vzeroupper \"
: \"=a\"(eax), \"=d\"(edx) : \"c\"(n) : );
#else
#error No GCC style inline asm supported for AVX instructions
#endif
}
" HAVE_GCC_INLINE_ASM_AVX)
# Check if sysconf(_SC_NPROCESSORS_ONLN) can be used for CPU count
CHECK_CXX_SOURCE_COMPILES (
"
#include <unistd.h>
int main()
{
sysconf(_SC_NPROCESSORS_ONLN);
}
" HAVE_SYSCONF_NPROCESSORS_ONLN)
##########################
# OpenEXRConfig.h generation
##########################
IF (WIN32)
FILE ( WRITE ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_COMPLETE_IOMANIP 1\n" )
ELSEIF (APPLE)
FILE ( WRITE ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_DARWIN 1\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_COMPLETE_IOMANIP 1\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#include <string.h>\n" )
ELSE ()
# Linux
FILE ( WRITE ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_LINUX_PROCFS 1\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_COMPLETE_IOMANIP 1\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_LARGE_STACK 1\n" )
ENDIF()
IF (NAMESPACE_VERSIONING)
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM 1\n")
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_NAMESPACE Imf\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_INTERNAL_NAMESPACE Imf_${OPENEXR_VERSION_API}\n\n" )
ELSE ()
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM 0\n")
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_NAMESPACE Imf\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_INTERNAL_NAMESPACE Imf\n\n" )
ENDIF ()
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_VERSION_STRING \"${OPENEXR_VERSION}\"\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_PACKAGE_STRING \"OpenEXR ${OPENEXR_VERSION}\"\n" )
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "
#define OPENEXR_VERSION_MAJOR ${OPENEXR_VERSION_MAJOR}
#define OPENEXR_VERSION_MINOR ${OPENEXR_VERSION_MINOR}
#define OPENEXR_VERSION_PATCH ${OPENEXR_VERSION_PATCH}
")
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "
// Version as a single hex number, e.g. 0x01000300 == 1.0.3
#define OPENEXR_VERSION_HEX ((OPENEXR_VERSION_MAJOR << 24) | \\
(OPENEXR_VERSION_MINOR << 16) | \\
(OPENEXR_VERSION_PATCH << 8))\n
")
IF (HAVE_GCC_INLINE_ASM_AVX)
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX 1\n" )
ENDIF()
IF (HAVE_SYSCONF_NPROCESSORS_ONLN)
FILE ( APPEND ${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h "#define OPENEXR_IMF_HAVE_SYSCONF_NPROCESSORS_ONLN 1\n" )
ENDIF()
SET (OPENEXR_LIBSUFFIX "")
SET (ILMBASE_LIBSUFFIX "")
IF (NAMESPACE_VERSIONING)
SET ( OPENEXR_LIBSUFFIX "-${OPENEXR_VERSION_API}" )
# assume same NAMESPACE_VERSION setting for IlmBase for now
SET ( ILMBASE_LIBSUFFIX "-${OPENEXR_VERSION_API}" )
ENDIF ()
##########################
# IlmImf library
##########################
ADD_SUBDIRECTORY ( IlmImf )
SET_TARGET_PROPERTIES ( IlmImf
PROPERTIES
VERSION 22.0.0
SOVERSION 22
OUTPUT_NAME "IlmImf${OPENEXR_LIBSUFFIX}"
)
##########################
# IlmImfUtil library
##########################
ADD_SUBDIRECTORY ( IlmImfUtil )
SET_TARGET_PROPERTIES ( IlmImfUtil
PROPERTIES
VERSION 22.0.0
SOVERSION 22
OUTPUT_NAME "IlmImfUtil${OPENEXR_LIBSUFFIX}"
)
##########################
# Example Code
##########################
ADD_SUBDIRECTORY ( IlmImfExamples )
##########################
# Tests
##########################
if (BUILD_TESTS)
ADD_SUBDIRECTORY ( IlmImfTest )
ADD_SUBDIRECTORY ( IlmImfUtilTest )
ADD_SUBDIRECTORY ( IlmImfFuzzTest )
endif ()
##########################
# Binaries / Utilities
##########################
if (BUILD_UTILS)
ADD_SUBDIRECTORY ( exrheader )
ADD_SUBDIRECTORY ( exrmaketiled )
ADD_SUBDIRECTORY ( exrstdattr )
ADD_SUBDIRECTORY ( exrmakepreview )
ADD_SUBDIRECTORY ( exrenvmap )
ADD_SUBDIRECTORY ( exrmultiview )
ADD_SUBDIRECTORY ( exrmultipart )
endif ()
##########################
# Installation
##########################
INSTALL ( FILES
${CMAKE_CURRENT_BINARY_DIR}/config/OpenEXRConfig.h
DESTINATION
${CMAKE_INSTALL_PREFIX}/include/OpenEXR
)
# Documentation
INSTALL ( FILES
doc/TechnicalIntroduction.pdf
doc/ReadingAndWritingImageFiles.pdf
doc/OpenEXRFileLayout.pdf
doc/MultiViewOpenEXR.pdf
doc/InterpretingDeepPixels.pdf
doc/TheoryDeepPixels.pdf
DESTINATION
${CMAKE_INSTALL_PREFIX}/share/doc/OpenEXR-${OPENEXR_VERSION}
)
# Examples
INSTALL ( FILES
IlmImfExamples/main.cpp
IlmImfExamples/drawImage.cpp
IlmImfExamples/rgbaInterfaceExamples.cpp
IlmImfExamples/rgbaInterfaceTiledExamples.cpp
IlmImfExamples/generalInterfaceExamples.cpp
IlmImfExamples/lowLevelIoExamples.cpp
IlmImfExamples/previewImageExamples.cpp
IlmImfExamples/generalInterfaceTiledExamples.cpp
IlmImfExamples/generalInterfaceTiledExamples.h
IlmImfExamples/drawImage.h
IlmImfExamples/rgbaInterfaceExamples.h
IlmImfExamples/generalInterfaceExamples.h
IlmImfExamples/rgbaInterfaceTiledExamples.h
IlmImfExamples/lowLevelIoExamples.h
IlmImfExamples/previewImageExamples.h
IlmImfExamples/namespaceAlias.h
DESTINATION
${CMAKE_INSTALL_PREFIX}/share/doc/OpenEXR-${OPENEXR_VERSION}/examples
)
@@ -1,273 +0,0 @@
# yue.nicholas@gmail.com
SET(CMAKE_INCLUDE_CURRENT_DIR 1)
if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/b44ExpLogTable.h")
ADD_EXECUTABLE ( b44ExpLogTable
b44ExpLogTable.cpp
)
TARGET_LINK_LIBRARIES ( b44ExpLogTable
Half
Iex${ILMBASE_LIBSUFFIX}
IlmThread${ILMBASE_LIBSUFFIX}
${PTHREAD_LIB}
)
ADD_CUSTOM_COMMAND (
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/b44ExpLogTable.h
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/b44ExpLogTable > ${CMAKE_CURRENT_BINARY_DIR}/b44ExpLogTable.h
DEPENDS b44ExpLogTable
)
else ()
message (STATUS "Skipping build of b44ExpLogTable.h")
endif ()
if (NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/dwaLookups.h")
ADD_EXECUTABLE ( dwaLookups
dwaLookups.cpp
)
TARGET_LINK_LIBRARIES ( dwaLookups
Half
Iex${ILMBASE_LIBSUFFIX}
IlmThread${ILMBASE_LIBSUFFIX}
${PTHREAD_LIB}
)
ADD_CUSTOM_COMMAND (
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/dwaLookups.h
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/dwaLookups > ${CMAKE_CURRENT_BINARY_DIR}/dwaLookups.h
DEPENDS dwaLookups
)
else ()
message (STATUS "Skipping build of dwaLookups.h")
endif ()
SET ( ILMIMF_SRCS
ImfAttribute.cpp
ImfBoxAttribute.cpp
ImfCRgbaFile.cpp
ImfChannelList.cpp
ImfChannelListAttribute.cpp
ImfFloatAttribute.cpp
ImfFrameBuffer.cpp
ImfHeader.cpp
ImfIO.cpp
ImfInputFile.cpp
ImfIntAttribute.cpp
ImfLineOrderAttribute.cpp
ImfMatrixAttribute.cpp
ImfOpaqueAttribute.cpp
ImfOutputFile.cpp
ImfRgbaFile.cpp
ImfStringAttribute.cpp
ImfVecAttribute.cpp
ImfHuf.cpp
ImfThreading.cpp
ImfWav.cpp
ImfLut.cpp
ImfCompressor.cpp
ImfRleCompressor.cpp
ImfZipCompressor.cpp
ImfPizCompressor.cpp
ImfB44Compressor.cpp
ImfDwaCompressor.cpp
ImfMisc.cpp
ImfCompressionAttribute.cpp
ImfDoubleAttribute.cpp
ImfConvert.cpp
ImfPreviewImage.cpp
ImfPreviewImageAttribute.cpp
ImfVersion.cpp
ImfChromaticities.cpp
ImfChromaticitiesAttribute.cpp
ImfKeyCode.cpp
ImfKeyCodeAttribute.cpp
ImfTimeCode.cpp
ImfTimeCodeAttribute.cpp
ImfRational.cpp
ImfRationalAttribute.cpp
ImfFramesPerSecond.cpp
ImfStandardAttributes.cpp
ImfStdIO.cpp
ImfEnvmap.cpp
ImfEnvmapAttribute.cpp
ImfScanLineInputFile.cpp
ImfTiledInputFile.cpp
ImfTiledMisc.cpp
ImfTiledOutputFile.cpp
ImfTiledRgbaFile.cpp
ImfTileDescriptionAttribute.cpp
ImfTileOffsets.cpp
ImfRgbaYca.cpp
ImfPxr24Compressor.cpp
ImfTestFile.cpp
ImfStringVectorAttribute.cpp
ImfMultiView.cpp
ImfAcesFile.cpp
ImfMultiPartOutputFile.cpp
ImfGenericOutputFile.cpp
ImfOutputPartData.cpp
ImfMultiPartInputFile.cpp
ImfGenericInputFile.cpp
ImfPartType.cpp
ImfInputPartData.cpp
ImfOutputPart.cpp
ImfTiledOutputPart.cpp
ImfInputPart.cpp
ImfTiledInputPart.cpp
ImfDeepScanLineInputPart.cpp
ImfDeepScanLineOutputPart.cpp
ImfDeepScanLineInputFile.cpp
ImfDeepScanLineOutputFile.cpp
ImfDeepTiledInputPart.cpp
ImfDeepTiledOutputPart.cpp
ImfDeepTiledInputFile.cpp
ImfDeepTiledOutputFile.cpp
ImfDeepFrameBuffer.cpp
ImfDeepCompositing.cpp
ImfCompositeDeepScanLine.cpp
ImfDeepImageStateAttribute.cpp
ImfFastHuf.cpp
ImfFloatVectorAttribute.cpp
ImfRle.cpp
ImfSystemSpecific.cpp
ImfZip.cpp
)
IF (BUILD_SHARED_LIBS)
ADD_DEFINITIONS(-DILMIMF_EXPORTS)
ENDIF()
ADD_LIBRARY ( IlmImf ${LIB_TYPE}
${ILMIMF_SRCS}
)
TARGET_LINK_LIBRARIES ( IlmImf
Half
Iex${ILMBASE_LIBSUFFIX}
Imath${ILMBASE_LIBSUFFIX}
IlmThread${ILMBASE_LIBSUFFIX}
${PTHREAD_LIB} ${ZLIB_LIBRARIES}
)
ADD_DEPENDENCIES ( IlmImf b44ExpLogTable )
SET_SOURCE_FILES_PROPERTIES (
ImfB44Compressor.cpp
PROPERTIES
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/b44ExpLogTable.h
)
ADD_DEPENDENCIES ( IlmImf dwaLookups )
SET_SOURCE_FILES_PROPERTIES (
ImfDwaCompressor.cpp
PROPERTIES
OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dwaLookups.h
)
# Libraries
INSTALL ( TARGETS
IlmImf
DESTINATION
${CMAKE_INSTALL_PREFIX}/lib
)
# Headers
INSTALL ( FILES
ImfForward.h
ImfExport.h
ImfAttribute.h
ImfBoxAttribute.h
ImfCRgbaFile.h
ImfChannelList.h
ImfChannelListAttribute.h
ImfCompressionAttribute.h
ImfDoubleAttribute.h
ImfFloatAttribute.h
ImfFrameBuffer.h
ImfHeader.h
ImfIO.h
ImfInputFile.h
ImfIntAttribute.h
ImfLineOrderAttribute.h
ImfMatrixAttribute.h
ImfOpaqueAttribute.h
ImfOutputFile.h
ImfRgbaFile.h
ImfStringAttribute.h
ImfVecAttribute.h
ImfHuf.h
ImfWav.h
ImfLut.h
ImfArray.h
ImfCompression.h
ImfLineOrder.h
ImfName.h
ImfPixelType.h
ImfVersion.h
ImfXdr.h
ImfConvert.h
ImfPreviewImage.h
ImfPreviewImageAttribute.h
ImfChromaticities.h
ImfChromaticitiesAttribute.h
ImfKeyCode.h
ImfKeyCodeAttribute.h
ImfTimeCode.h
ImfTimeCodeAttribute.h
ImfRational.h
ImfRationalAttribute.h
ImfFramesPerSecond.h
ImfStandardAttributes.h
ImfEnvmap.h
ImfEnvmapAttribute.h
ImfInt64.h
ImfRgba.h
ImfTileDescription.h
ImfTileDescriptionAttribute.h
ImfTiledInputFile.h
ImfTiledOutputFile.h
ImfTiledRgbaFile.h
ImfRgbaYca.h
ImfTestFile.h
ImfThreading.h
ImfB44Compressor.h
ImfStringVectorAttribute.h
ImfMultiView.h
ImfAcesFile.h
ImfMultiPartOutputFile.h
ImfGenericOutputFile.h
ImfMultiPartInputFile.h
ImfGenericInputFile.h
ImfPartType.h
ImfPartHelper.h
ImfOutputPart.h
ImfTiledOutputPart.h
ImfInputPart.h
ImfTiledInputPart.h
ImfDeepScanLineOutputFile.h
ImfDeepScanLineOutputPart.h
ImfDeepScanLineInputFile.h
ImfDeepScanLineInputPart.h
ImfDeepTiledInputFile.h
ImfDeepTiledInputPart.h
ImfDeepTiledOutputFile.h
ImfDeepTiledOutputPart.h
ImfDeepFrameBuffer.h
ImfDeepCompositing.h
ImfCompositeDeepScanLine.h
ImfNamespace.h
ImfMisc.h
ImfDeepImageState.h
ImfDeepImageStateAttribute.h
ImfFloatVectorAttribute.h
DESTINATION
${CMAKE_INSTALL_PREFIX}/include/OpenEXR
)
Binary file not shown.
+9 -5
View File
@@ -32,16 +32,20 @@ if [[ ! -e ${OPENJPEG_SRC_DIR} ]] ; then
git clone ${OPENJPEG_REPO} ${OPENJPEG_SRC_DIR}
fi
cd ${OPENJPEG_SRC_DIR}
echo "git checkout ${OPENJPEG_VERSION} --force"
git checkout ${OPENJPEG_VERSION} --force
mkdir -p ${OPENJPEG_BUILD_DIR} && true
cd ${OPENJPEG_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${OPENJPEG_INSTALL_DIR} \
-DBUILD_CODEC=OFF \
${OPENJPEG_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${OPENJPEG_INSTALL_DIR} \
-DBUILD_CODEC=OFF \
${OPENJPEG_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
fi
# ls -R ${OPENJPEG_INSTALL_DIR}
popd
+15 -8
View File
@@ -22,17 +22,24 @@ echo "giflib install dir will be: ${GIFLIB_INSTALL_DIR}"
mkdir -p ${LOCAL_DEPS_DIR}
pushd ${LOCAL_DEPS_DIR}
# Clone giflib project and build
curl --location https://downloads.sourceforge.net/project/giflib/giflib-${GIFLIB_VERSION}.tar.gz -o giflib.tar.gz
tar xzf giflib.tar.gz
pushd giflib-${GIFLIB_VERSION}
cp Makefile Makefile.old
curl --location https://sourceforge.net/p/giflib/bugs/_discuss/thread/4e811ad29b/c323/attachment/Makefile.patch -o Makefile.patch
patch -p0 < Makefile.patch
popd
if [[ ! -e giflib-${GIFLIB_VERSION} ]] ; then
curl --location https://downloads.sourceforge.net/project/giflib/giflib-${GIFLIB_VERSION}.tar.gz -o giflib.tar.gz
tar xzf giflib.tar.gz
pushd giflib-${GIFLIB_VERSION}
cp Makefile Makefile.old
curl --location https://sourceforge.net/p/giflib/bugs/_discuss/thread/4e811ad29b/c323/attachment/Makefile.patch -o Makefile.patch
patch -p0 < Makefile.patch
popd
fi
cd giflib-${GIFLIB_VERSION}
time make PREFIX=${GIFLIB_INSTALL_DIR} CC=${GIFLIB_CC} install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time make PREFIX=${GIFLIB_INSTALL_DIR} CC=${GIFLIB_CC} install
fi
popd
+7 -4
View File
@@ -38,10 +38,13 @@ git checkout ${LIBJPEGTURBO_VERSION} --force
mkdir -p ${LIBJPEGTURBO_BUILD_DIR}
cd ${LIBJPEGTURBO_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBJPEGTURBO_INSTALL_DIR} \
${LIBJPEGTURBO_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBJPEGTURBO_INSTALL_DIR} \
${LIBJPEGTURBO_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
fi
# ls -R ${LIBJPEGTURBO_INSTALL_DIR}
popd
+11 -6
View File
@@ -33,17 +33,22 @@ if [[ ! -e ${LIBPNG_SRC_DIR} ]] ; then
git clone ${LIBPNG_REPO} ${LIBPNG_SRC_DIR}
fi
cd ${LIBPNG_SRC_DIR}
echo "git checkout ${LIBPNG_VERSION} --force"
git checkout ${LIBPNG_VERSION} --force
mkdir -p ${LIBPNG_BUILD_DIR}
cd ${LIBPNG_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBPNG_INSTALL_DIR} \
-DPNG_EXECUTABLES=OFF \
-DPNG_TESTS=OFF \
${LIBPNG_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBPNG_INSTALL_DIR} \
-DPNG_EXECUTABLES=OFF \
-DPNG_TESTS=OFF \
${LIBPNG_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
fi
# ls -R ${LIBPNG_INSTALL_DIR}
popd
+7 -4
View File
@@ -33,12 +33,15 @@ mkdir -p ${LIBRAW_INSTALL_DIR} && true
mkdir -p ${LIBRAW_BUILD_DIR} && true
pushd ${LIBRAW_SOURCE_DIR}
git checkout ${LIBRAW_VERSION} --force
aclocal
autoreconf --install
./configure --prefix=${LIBRAW_INSTALL_DIR}
time make -j ${PARALLEL:=4} && make install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
aclocal
autoreconf --install
./configure --prefix=${LIBRAW_INSTALL_DIR}
time make -j ${PARALLEL:=4} && make install
fi
popd
+16 -6
View File
@@ -9,7 +9,8 @@ LIBTIFF_REPO=${LIBTIFF_REPO:=https://gitlab.com/libtiff/libtiff.git}
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
LIBTIFF_BUILD_DIR=${LIBTIFF_BUILD_DIR:=${LOCAL_DEPS_DIR}/libtiff}
LIBTIFF_INSTALL_DIR=${LIBTIFF_INSTALL_DIR:=${PWD}/ext/dist}
LIBTIFF_VERSION=${LIBTIFF_VERSION:=v4.1.0}
LIBTIFF_VERSION=${LIBTIFF_VERSION:=v4.3.0}
LIBTIFF_BUILD_TYPE=${LIBTIFF_BUILD_TYPE:=Release}
if [[ `uname` == `Linux` ]] ; then
LIBTIFF_CXX_FLAGS=${LIBTIFF_CXX_FLAGS:="-O3 -Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
fi
@@ -30,13 +31,22 @@ cd libtiff
echo "git checkout ${LIBTIFF_VERSION} --force"
git checkout ${LIBTIFF_VERSION} --force
mkdir -p build
cd build
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${LIBTIFF_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${LIBTIFF_CXX_FLAGS}" \
${LIBTIFF_BUILDOPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=${LIBTIFF_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${LIBTIFF_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${LIBTIFF_CXX_FLAGS}" \
-DBUILD_SHARED_LIBS=${LIBTIFF_BUILD_SHARED_LIBS:-ON} \
-Dtiff-tests=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dtiff-docs=${LIBTIFF_BUILD_TESTS:-OFF} \
-Dlibdeflate=ON \
${LIBTIFF_BUILDOPTS} ..
time cmake --build . --target install
fi
popd
# ls -R ${LIBTIFF_INSTALL_DIR}
+12 -8
View File
@@ -10,7 +10,7 @@ uname
if [[ `uname` == "Linux" ]] ; then
LLVM_VERSION=${LLVM_VERSION:=8.0.0}
LLVM_VERSION=${LLVM_VERSION:=13.0.0}
LLVM_INSTALL_DIR=${LLVM_INSTALL_DIR:=${PWD}/llvm-install}
if [[ "$GITHUB_WORKFLOW" != "" ]] ; then
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=ubuntu-18.04}
@@ -23,14 +23,18 @@ if [[ `uname` == "Linux" ]] ; then
else
LLVM_DISTRO_NAME=${LLVM_DISTRO_NAME:=error}
fi
if [ "$LLVM_VERSION" == "5.0.0" ] ; then
LLVMTAR=clang+llvm-${LLVM_VERSION}-linux-x86_64-${LLVM_DISTRO_NAME}.tar.xz
else
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-${LLVM_DISTRO_NAME}.tar.xz
fi
LLVMTAR=clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-${LLVM_DISTRO_NAME}.tar.xz
echo LLVMTAR = $LLVMTAR
curl --location http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
# ls -l $LLVMTAR
if [[ "$LLVM_VERSION" == "10.0.0" ]] || [[ "$LLVM_VERSION" == "11.0.0" ]] \
|| [[ "$LLVM_VERSION" == "11.1.0" ]] || [[ "$LLVM_VERSION" == "12.0.0" ]] \
|| [[ "$LLVM_VERSION" == "13.0.0" ]] || [[ "$LLVM_VERSION" == "14.0.0" ]] ;
then
# new
curl --location https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
else
curl --location http://releases.llvm.org/${LLVM_VERSION}/${LLVMTAR} -o $LLVMTAR
fi
ls -l $LLVMTAR
tar xf $LLVMTAR
rm -f $LLVMTAR
echo "Installed ${LLVM_VERSION} in ${LLVM_INSTALL_DIR}"
+10 -10
View File
@@ -7,11 +7,11 @@ set -ex
# Which OCIO to retrieve, how to build it
OPENCOLORIO_REPO=${OPENCOLORIO_REPO:=https://github.com/AcademySoftwareFoundation/OpenColorIO.git}
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v2.0.0}
OPENCOLORIO_VERSION=${OPENCOLORIO_VERSION:=v2.1.2}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
OPENCOLORIO_SOURCE_DIR=${OPENCOLORIO_SOURCE_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO}
OPENCOLORIO_BUILD_DIR=${OPENCOLORIO_BUILD_DIR:=${LOCAL_DEPS_DIR}/OpenColorIO-build}
OPENCOLORIO_INSTALL_DIR=${OPENCOLORIO_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
OPENCOLORIO_CXX_FLAGS=${OPENCOLORIO_CXX_FLAGS:="-Wno-unused-function -Wno-deprecated-declarations -Wno-cast-qual -Wno-write-strings"}
@@ -21,7 +21,7 @@ OPENCOLORIO_BUILDOPTS="-DOCIO_BUILD_APPS=OFF -DOCIO_BUILD_NUKE=OFF \
-DOCIO_BUILD_GPU_TESTS=OFF \
-DOCIO_BUILD_PYTHON=OFF -DOCIO_BUILD_PYGLUE=OFF \
-DOCIO_BUILD_JAVA=OFF \
-DOCIO_BUILD_STATIC=${OCIO_BUILD_STATIC:=OFF}"
-DBUILD_SHARED_LIBS=${OPENCOLORIO_BUILD_SHARED_LIBS:=ON}"
BASEDIR=`pwd`
pwd
echo "OpenColorIO install dir will be: ${OPENCOLORIO_INSTALL_DIR}"
@@ -30,20 +30,20 @@ mkdir -p ${LOCAL_DEPS_DIR}
pushd ${LOCAL_DEPS_DIR}
# Clone OpenColorIO project from GitHub and build
if [[ ! -e OpenColorIO ]] ; then
echo "git clone ${OPENCOLORIO_REPO} OpenColorIO"
git clone ${OPENCOLORIO_REPO} OpenColorIO
if [[ ! -e ${OPENCOLORIO_SOURCE_DIR} ]] ; then
echo "git clone ${OPENCOLORIO_REPO} ${OPENCOLORIO_SOURCE_DIR}"
git clone ${OPENCOLORIO_REPO} ${OPENCOLORIO_SOURCE_DIR}
fi
cd OpenColorIO
cd ${OPENCOLORIO_SOURCE_DIR}
echo "git checkout ${OPENCOLORIO_VERSION} --force"
git checkout ${OPENCOLORIO_VERSION} --force
mkdir -p build
cd build
mkdir -p ${OPENCOLORIO_BUILD_DIR}
cd ${OPENCOLORIO_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${OPENCOLORIO_INSTALL_DIR} \
-DCMAKE_CXX_FLAGS="${OPENCOLORIO_CXX_FLAGS}" \
${OPENCOLORIO_BUILDOPTS} ..
${OPENCOLORIO_BUILDOPTS} ${OPENCOLORIO_SOURCE_DIR}
time cmake --build . --config Release --target install
popd
+5 -31
View File
@@ -7,7 +7,7 @@ set -ex
# Which OpenEXR to retrieve, how to build it
OPENEXR_REPO=${OPENEXR_REPO:=https://github.com/AcademySoftwareFoundation/openexr.git}
OPENEXR_VERSION=${OPENEXR_VERSION:=v2.4.1}
OPENEXR_VERSION=${OPENEXR_VERSION:=v3.1.5}
# Where to install the final results
LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
@@ -15,7 +15,6 @@ OPENEXR_SOURCE_DIR=${OPENEXR_SOURCE_DIR:=${LOCAL_DEPS_DIR}/openexr}
OPENEXR_BUILD_DIR=${OPENEXR_BUILD_DIR:=${LOCAL_DEPS_DIR}/openexr-build}
OPENEXR_INSTALL_DIR=${OPENEXR_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
OPENEXR_BUILD_TYPE=${OPENEXR_BUILD_TYPE:=Release}
CMAKE_GENERATOR=${CMAKE_GENERATOR:="Unix Makefiles"}
OPENEXR_CMAKE_FLAGS=${OPENEXR_CMAKE_FLAGS:=""}
OPENEXR_CXX_FLAGS=${OPENEXR_CXX_FLAGS:=""}
BASEDIR=$PWD
@@ -24,49 +23,24 @@ pwd
echo "Building OpenEXR ${OPENEXR_VERSION}"
echo "OpenEXR build dir will be: ${OPENEXR_BUILD_DIR}"
echo "OpenEXR install dir will be: ${OPENEXR_INSTALL_DIR}"
echo "CMAKE_PREFIX_PATH is ${CMAKE_PREFIX_PATH}"
echo "OpenEXR Build type is ${OPENEXR_BUILD_TYPE}"
if [[ "$CMAKE_GENERATOR" == "" ]] ; then
OPENEXR_GENERATOR_CMD="-G \"$CMAKE_GENERATOR\""
fi
echo "CMAKE_PREFIX_PATH is ${CMAKE_PREFIX_PATH}"
# Clone OpenEXR project (including IlmBase) from GitHub and build
if [[ ! -e ${OPENEXR_SOURCE_DIR} ]] ; then
echo "git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}"
git clone ${OPENEXR_REPO} ${OPENEXR_SOURCE_DIR}
fi
mkdir -p ${OPENEXR_INSTALL_DIR} && true
mkdir -p ${OPENEXR_BUILD_DIR} && true
pushd ${OPENEXR_SOURCE_DIR}
git checkout ${OPENEXR_VERSION} --force
if [[ ${OPENEXR_VERSION} == "v2.2.0" ]] || [[ ${OPENEXR_VERSION} == "v2.2.1" ]] \
|| [[ ${OPENEXR_VERSION} == "v2.2.2" ]] ; then
mkdir -p ${OPENEXR_BUILD_DIR}/IlmBase && true
mkdir -p ${OPENEXR_BUILD_DIR}/OpenEXR && true
cd ${OPENEXR_BUILD_DIR}/IlmBase
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} ${OPENEXR_GENERATOR_CMD} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
-DCMAKE_CXX_STANDARD=11 \
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}/IlmBase
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
cd ${OPENEXR_BUILD_DIR}/OpenEXR
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} ${OPENEXR_GENERATOR_CMD} \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}\;${OPENEXR_INSTALL_DIR}" \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DBUILD_UTILS=0 -DBUILD_TESTS=0 \
-DCMAKE_CXX_FLAGS="${OPENEXR_CXX_FLAGS}" \
${OPENEXR_CMAKE_FLAGS} ${OPENEXR_SOURCE_DIR}/OpenEXR
time cmake --build . --target install --config ${OPENEXR_BUILD_TYPE}
elif [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
if [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
# Simplified setup for 2.3+
cd ${OPENEXR_BUILD_DIR}
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} -G "$CMAKE_GENERATOR" \
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
@@ -79,7 +53,7 @@ elif [[ ${OPENEXR_VERSION} == "v2.3.0" ]] ; then
else
# Simplified setup for 2.4+
cd ${OPENEXR_BUILD_DIR}
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} -G "$CMAKE_GENERATOR" \
cmake -DCMAKE_BUILD_TYPE=${OPENEXR_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX="${OPENEXR_INSTALL_DIR}" \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}" \
-DILMBASE_PACKAGE_PREFIX="${OPENEXR_INSTALL_DIR}" \
+10 -6
View File
@@ -34,17 +34,21 @@ if [[ ! -e ${PUGIXML_SRC_DIR} ]] ; then
git clone ${PUGIXML_REPO} ${PUGIXML_SRC_DIR}
fi
cd ${PUGIXML_SRC_DIR}
echo "git checkout ${PUGIXML_VERSION} --force"
git checkout ${PUGIXML_VERSION} --force
mkdir -p ${PUGIXML_BUILD_DIR}
cd ${PUGIXML_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTS=OFF \
${PUGIXML_BUILD_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PUGIXML_INSTALL_DIR} \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_TESTS=OFF \
${PUGIXML_BUILD_OPTS} ..
time cmake --build . --config Release --target install
fi
# ls -R ${PUGIXML_INSTALL_DIR}
popd
+10 -6
View File
@@ -7,7 +7,7 @@ set -ex
# Repo and branch/tag/commit of pybind11 to download if we don't have it yet
PYBIND11_REPO=${PYBIND11_REPO:=https://github.com/pybind/pybind11.git}
PYBIND11_VERSION=${PYBIND11_VERSION:=v2.5.0}
PYBIND11_VERSION=${PYBIND11_VERSION:=v2.8.1}
# Where to put pybind11 repo source (default to the ext area)
PYBIND11_SRC_DIR=${PYBIND11_SRC_DIR:=${PWD}/ext/pybind11}
@@ -34,16 +34,20 @@ if [[ ! -e ${PYBIND11_SRC_DIR} ]] ; then
git clone ${PYBIND11_REPO} ${PYBIND11_SRC_DIR}
fi
cd ${PYBIND11_SRC_DIR}
echo "git checkout ${PYBIND11_VERSION} --force"
git checkout ${PYBIND11_VERSION} --force
mkdir -p ${PYBIND11_BUILD_DIR}
cd ${PYBIND11_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PYBIND11_INSTALL_DIR} \
-DPYBIND11_TEST=OFF \
${PYBIND11_BUILD_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${PYBIND11_INSTALL_DIR} \
-DPYBIND11_TEST=OFF \
${PYBIND11_BUILD_OPTS} ..
time cmake --build . --config Release --target install
fi
# ls -R ${PYBIND11_INSTALL_DIR}
popd
+16 -12
View File
@@ -18,6 +18,7 @@ LOCAL_DEPS_DIR=${LOCAL_DEPS_DIR:=${PWD}/ext}
WEBP_SRC_DIR=${WEBP_SRC_DIR:=${LOCAL_DEPS_DIR}/webp}
WEBP_BUILD_DIR=${WEBP_BUILD_DIR:=${WEBP_SRC_DIR}/build}
WEBP_INSTALL_DIR=${WEBP_INSTALL_DIR:=${LOCAL_DEPS_DIR}/dist}
WEBP_BUILD_TYPE=${WEBP_BUILD_TYPE:=${CMAKE_BUILD_TYPE:-Release}}
#WEBP_CONFIG_OPTS=${WEBP_CONFIG_OPTS:=}
pwd
@@ -32,24 +33,27 @@ if [[ ! -e ${WEBP_SRC_DIR} ]] ; then
git clone ${WEBP_REPO} ${WEBP_SRC_DIR}
fi
cd ${WEBP_SRC_DIR}
echo "git checkout ${WEBP_VERSION} --force"
git checkout ${WEBP_VERSION} --force
mkdir -p ${WEBP_BUILD_DIR}
cd ${WEBP_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${WEBP_INSTALL_DIR} \
-DWEBP_BUILD_ANIM_UTILS=OFF \
-DWEBP_BUILD_CWEBP=OFF \
-DWEBP_BUILD_DWEBP=OFF \
-DWEBP_BUILD_VWEBP=OFF \
-DWEBP_BUILD_GIF2WEBPx=OFF \
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
-DBUILD_SHARED_LIBS=ON \
${WEBP_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=${WEBP_BUILD_TYPE} \
-DCMAKE_INSTALL_PREFIX=${WEBP_INSTALL_DIR} \
-DWEBP_BUILD_ANIM_UTILS=OFF \
-DWEBP_BUILD_CWEBP=OFF \
-DWEBP_BUILD_DWEBP=OFF \
-DWEBP_BUILD_VWEBP=OFF \
-DWEBP_BUILD_GIF2WEBPx=OFF \
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
-DBUILD_SHARED_LIBS=ON \
${WEBP_CONFIG_OPTS} ..
time cmake --build . --target install
fi
# ls -R ${WEBP_INSTALL_DIR}
+9 -4
View File
@@ -33,15 +33,20 @@ if [[ ! -e ${ZLIB_SRC_DIR} ]] ; then
git clone ${ZLIB_REPO} ${ZLIB_SRC_DIR}
fi
cd ${ZLIB_SRC_DIR}
echo "git checkout ${ZLIB_VERSION} --force"
git checkout ${ZLIB_VERSION} --force
mkdir -p ${ZLIB_BUILD_DIR} && true
cd ${ZLIB_BUILD_DIR}
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${ZLIB_INSTALL_DIR} \
${ZLIB_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
if [[ -z $DEP_DOWNLOAD_ONLY ]]; then
time cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=${ZLIB_INSTALL_DIR} \
${ZLIB_CONFIG_OPTS} ..
time cmake --build . --config Release --target install
fi
# ls -R ${ZLIB_INSTALL_DIR}
popd
+29 -6
View File
@@ -4,22 +4,45 @@
# any command in it fails. This is crucial for CI tests.
set -ex
OIIO_CMAKE_FLAGS="$MY_CMAKE_FLAGS $OIIO_CMAKE_FLAGS"
if [[ "$USE_SIMD" != "" ]] ; then
MY_CMAKE_FLAGS="$MY_CMAKE_FLAGS -DUSE_SIMD=$USE_SIMD"
OIIO_CMAKE_FLAGS="$OIIO_CMAKE_FLAGS -DUSE_SIMD=$USE_SIMD"
fi
pushd build/$PLATFORM
cmake ../.. -G "$CMAKE_GENERATOR" \
if [[ -n "$FMT_VERSION" ]] ; then
OIIO_CMAKE_FLAGS="$OIIO_CMAKE_FLAGS -DBUILD_FMT_VERSION=$FMT_VERSION"
fi
if [[ -n "$CODECOV" ]] ; then
OIIO_CMAKE_FLAGS="$OIIO_CMAKE_FLAGS -DCODECOV=${CODECOV}"
fi
# On GHA, we can reduce build time with "unity" builds.
if [[ ${GITHUB_ACTIONS} == true ]] ; then
OIIO_CMAKE_FLAGS+=" -DCMAKE_UNITY_BUILD=${CMAKE_UNITY_BUILD:=ON} -DCMAKE_UNITY_BUILD_MODE=${CMAKE_UNITY_BUILD_MODE:=BATCH}"
fi
pushd build
cmake .. -G "$CMAKE_GENERATOR" \
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
-DCMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH" \
-DCMAKE_INSTALL_PREFIX="$OpenImageIO_ROOT" \
-DPYTHON_VERSION="$PYTHON_VERSION" \
-DCMAKE_INSTALL_LIBDIR="$OpenImageIO_ROOT/lib" \
-DCMAKE_CXX_STANDARD="$CMAKE_CXX_STANDARD" \
$MY_CMAKE_FLAGS -DVERBOSE=1
-DOIIO_DOWNLOAD_MISSING_TESTDATA=ON \
-DEXTRA_CPP_ARGS="${OIIO_EXTRA_CPP_ARGS}" \
$OIIO_CMAKE_FLAGS -DVERBOSE=1
# Save a copy of the generated files for debugging broken CI builds.
mkdir cmake-save || /bin/true
cp -r CMake* *.cmake cmake-save
: ${BUILDTARGET:=install}
if [[ "$BUILDTARGET" != "none" ]] ; then
echo "Parallel build " ${CMAKE_BUILD_PARALLEL_LEVEL}
time cmake --build . --target ${BUILDTARGET:=install} --config ${CMAKE_BUILD_TYPE}
echo "Parallel build ${CMAKE_BUILD_PARALLEL_LEVEL} of target ${BUILDTARGET}"
time ${OIIO_CMAKE_BUILD_WRAPPER} cmake --build . --target ${BUILDTARGET} --config ${CMAKE_BUILD_TYPE}
fi
popd
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# Run code coverage analysis
# This assumes that the build occurred with CODECOV=1 and tests have already
# fully run.
set -ex
echo "Performing code coverage analysis"
mkdir _coverage
pushd _coverage
# The sed command below converts from:
# ../build/src/libOpenImageIO/CMakeFiles/OpenImageIO.dir/foo.gcno
# to:
# ../src/libOpenImageIO/foo.cpp
for g in $(find ../build -name "*.gcno" -type f); do
echo "Processing $g"
echo "dirname $g = $(dirname $g) to " `$(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\.cpp\.cpp/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')`
gcov -l -p -o $(dirname "$g") $(echo "$g" | sed -e 's/\/build\//\//' -e 's/\.gcno/\.cpp/' -e 's/\/CMakeFiles.*\.dir\//\//')
done
popd
+7 -27
View File
@@ -4,28 +4,6 @@
# Since it sets many env variables needed by the caller, it should be run
# with 'source', not in a separate shell.
# Figure out the platform
if [[ $RUNNER_OS == macOS ]] ; then
export ARCH=macosx
elif [[ $RUNNER_OS == Linux ]] ; then
export ARCH=linux64
elif [[ $RUNNER_OS == Windows ]] ; then
export ARCH=windows64
elif [[ `uname -m` == aarch64 ]] ; then
export ARCH=aarch64
else
export ARCH=unknown
exit -1
fi
export PLATFORM=$ARCH
if [[ "${DEBUG:=0}" != "0" ]] ; then
export PLATFORM=${PLATFORM}.debug
fi
echo "Architecture is $ARCH"
echo "Build platform name is $PLATFORM"
# Environment variables we always need
export PATH=/usr/local/bin/_ccache:/usr/lib/ccache:$PATH
export USE_CCACHE=${USE_CCACHE:=1}
@@ -36,20 +14,22 @@ if [[ "${RUNNER_OS}" == "macOS" ]] ; then
fi
mkdir -p $CCACHE_DIR
export OpenImageIO_ROOT=$PWD/dist/$PLATFORM
export OpenImageIO_ROOT=$PWD/dist
export DYLD_LIBRARY_PATH=$OpenImageIO_ROOT/lib:$DYLD_LIBRARY_PATH
export LD_LIBRARY_PATH=$OpenImageIO_ROOT/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$OpenImageIO_ROOT/lib64:$LD_LIBRARY_PATH
export OIIO_LIBRARY_PATH=$OpenImageIO_ROOT/lib
export LSAN_OPTIONS=suppressions=$PWD/src/build-scripts/nosanitize.txt
export ASAN_OPTIONS=print_suppressions=0
export UBSAN_OPTIONS=suppressions=$PWD/src/build-scripts/ubsan-suppressions.txt
export PYTHON_VERSION=${PYTHON_VERSION:="2.7"}
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
export BUILD_MISSING_DEPS=${BUILD_MISSING_DEPS:=1}
export COMPILER=${COMPILER:=gcc}
export CC=${CC:=gcc}
export CXX=${CXX:=g++}
export CI=true
export OpenImageIO_CI=true
export USE_NINJA=${USE_NINJA:=1}
export CMAKE_GENERATOR=${CMAKE_GENERATOR:=Ninja}
export CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:=Release}
@@ -66,10 +46,10 @@ export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib64:$LD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$DYLD_LIBRARY_PATH
export OCIO="$PWD/testsuite/common/OpenColorIO/nuke-default/config.ocio"
# export OCIO="$PWD/testsuite/common/OpenColorIO/nuke-default/config.ocio"
export TESTSUITE_CLEANUP_ON_SUCCESS=${TESTSUITE_CLEANUP_ON_SUCCESS:=1}
mkdir -p build/$PLATFORM dist/$PLATFORM
mkdir -p build dist
echo "HOME = $HOME"
echo "PWD = $PWD"
@@ -84,7 +64,7 @@ env | sort
if [[ `uname -s` == "Linux" ]] ; then
head -40 /proc/cpuinfo
elif [[ $ARCH == macosx ]] ; then
elif [[ "${RUNNER_OS}" == "macOS" ]] ; then
sysctl machdep.cpu.features
fi
+37 -10
View File
@@ -2,17 +2,44 @@
# Important: set -ex causes this whole script to terminate with error if
# any command in it fails. This is crucial for CI tests.
set -ex
# (Though we let it run all the way through for code coverage workflows.)
if [[ "${CODECOV}" == "" ]]; then
set -ex
fi
: ${CTEST_EXCLUSIONS:="broken"}
: ${CTEST_TEST_TIMEOUT:=180}
#
# Try a few command line options to test them and also get some important
# debugging info in the CI logs.
#
echo ; echo "Results of oiiotool --version:"
$OpenImageIO_ROOT/bin/oiiotool --version || true
echo ; echo "Results of oiiotool brief help:"
$OpenImageIO_ROOT/bin/oiiotool || true
echo ; echo "Results of oiiotool full --help:"
$OpenImageIO_ROOT/bin/oiiotool --help || true
echo ; echo "Results of oiiotool --colorconfiginfo:"
$OpenImageIO_ROOT/bin/oiiotool --colorconfiginfo
echo ; echo "Results of oiiotool with no args (should get short help message):"
$OpenImageIO_ROOT/bin/oiiotool || true
echo ; echo "Run unit tests and simple stats:"
$OpenImageIO_ROOT/bin/oiiotool --unittest --list-formats --threads 0 \
--cache 1000 --autotile --autopremult --runstats || true
echo ; echo "Try unknown command:"
$OpenImageIO_ROOT/bin/oiiotool -q --unknown || true
echo "Parallel test " ${CTEST_PARALLEL_LEVEL}
pushd build/$PLATFORM
time ctest -C ${CMAKE_BUILD_TYPE} -E broken --force-new-ctest-process \
--output-on-failure --timeout ${CTEST_TEST_TIMEOUT:=180} ${CTEST_ARGS}
#
# Full test suite
#
echo "Parallel test ${CTEST_PARALLEL_LEVEL}"
echo "Default timeout ${CTEST_TEST_TIMEOUT}"
echo "Test exclusions '${CTEST_EXCLUSIONS}'"
echo "CTEST_ARGS '${CTEST_ARGS}'"
pushd build
time ctest -C ${CMAKE_BUILD_TYPE} --force-new-ctest-process --output-on-failure \
-E "${CTEST_EXCLUSIONS}" --timeout ${CTEST_TEST_TIMEOUT} ${CTEST_ARGS}
popd
# if [[ "$CODECOV" == 1 ]] ; then
# bash <(curl -s https://codecov.io/bash)
# fi
Binary file not shown.
+77 -19
View File
@@ -10,54 +10,95 @@ set -ex
if [[ "$ASWF_ORG" != "" ]] ; then
# Using ASWF CentOS container
export PATH=/opt/rh/devtoolset-6/root/usr/bin:/usr/local/bin:$PATH
#ls /etc/yum.repos.d
sudo yum install -y giflib giflib-devel && true
sudo yum install -y opencv opencv-devel && true
sudo yum install -y Field3D Field3D-devel && true
sudo yum install -y ffmpeg ffmpeg-devel && true
if [[ "${EXTRA_DEP_PACKAGES}" != "" ]] ; then
time sudo yum install -y ${EXTRA_DEP_PACKAGES}
fi
if [[ "${CONAN_LLVM_VERSION}" != "" ]] ; then
mkdir conan
pushd conan
# Simple way to conan install just one package:
# conan install clang/${CONAN_LLVM_VERSION}@aswftesting/ci_common1 -g deploy -g virtualenv
# But the below method can accommodate multiple requirements:
echo "[imports]" >> conanfile.txt
echo "., * -> ." >> conanfile.txt
echo "[requires]" >> conanfile.txt
echo "clang/${CONAN_LLVM_VERSION}@aswftesting/ci_common1" >> conanfile.txt
time conan install .
echo "--ls--"
ls -R .
export PATH=$PWD/bin:$PATH
export LD_LIBRARY_PATH=$PWD/lib:$LD_LIBRARY_PATH
export LLVM_ROOT=$PWD
popd
fi
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" ]] ; then
# The "current" version of icc 2023.x on the Intel site is build to
# link against a glibc too new for the ASWF CentOS7-based containers
# we run CI on. So we lock down to a specific version of icc 2022.1
# that is known to work.
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo /usr/bin/yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic-2022.1.0-3768
# Because multiple (possibly newer) versions of oneAPI may be installed,
# use a config file to specify compiler and tbb versions
# NOTE: oneAPI components have independent version numbering.
set +e; source /opt/intel/oneapi/setvars.sh --config oneapi_2022.1.0.cfg; set -e
elif [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$CXX" == "icpx" || "$CC" == "icx" || "$USE_ICX" != "" ]] ; then
sudo cp src/build-scripts/oneAPI.repo /etc/yum.repos.d
sudo yum install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
set +e; source /opt/intel/oneapi/setvars.sh; set -e
fi
else
# Using native Ubuntu runner
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
time sudo apt-get update
time sudo apt-get -q install -y \
git cmake ninja-build ccache g++ \
libboost-dev libboost-thread-dev \
libboost-filesystem-dev libboost-regex-dev \
libboost-dev libboost-thread-dev libboost-filesystem-dev \
libilmbase-dev libopenexr-dev \
libtbb-dev \
libtiff-dev libgif-dev libpng-dev libraw-dev libwebp-dev \
libavcodec-dev libavformat-dev libswscale-dev libavutil-dev \
dcmtk libsquish-dev libopenvdb-dev \
dcmtk libopenvdb-dev \
libfreetype6-dev \
locales wget \
libopencolorio-dev \
libopencv-dev \
qt5-default \
libhdf5-dev
time sudo apt-get -q install -y \
qt5-default || /bin/true
if [[ "${EXTRA_DEP_PACKAGES}" != "" ]] ; then
time sudo apt-get -q install -y ${EXTRA_DEP_PACKAGES}
fi
if [[ "$PYTHON_VERSION" == "2.7" ]] ; then
# Nonstandard python versions
if [[ "${PYTHON_VERSION}" == "3.9" ]] ; then
time sudo apt-get -q install -y python3.9-dev python3-numpy
pip3 --version
pip3 install numpy
elif [[ "$PYTHON_VERSION" == "2.7" ]] ; then
time sudo apt-get -q install -y python-dev python-numpy
else
pip3 install numpy
fi
if [[ "$USE_LIBHEIF" != "0" ]] ; then
sudo add-apt-repository ppa:strukturag/libde265
sudo add-apt-repository ppa:strukturag/libheif
time sudo apt-get -q install -y libheif-dev
sudo add-apt-repository ppa:strukturag/libde265 || true
sudo add-apt-repository ppa:strukturag/libheif || true
time sudo apt-get -q install -y libheif-dev || true
fi
export CMAKE_PREFIX_PATH=/usr/lib/x86_64-linux-gnu:$CMAKE_PREFIX_PATH
if [[ "$CXX" == "g++-4.8" ]] ; then
time sudo apt-get install -y g++-4.8
elif [[ "$CXX" == "g++-6" ]] ; then
if [[ "$CXX" == "g++-6" ]] ; then
time sudo apt-get install -y g++-6
elif [[ "$CXX" == "g++-7" ]] ; then
time sudo apt-get install -y g++-7
@@ -69,6 +110,17 @@ else
time sudo apt-get install -y g++-10
elif [[ "$CXX" == "g++-11" ]] ; then
time sudo apt-get install -y g++-11
elif [[ "$CXX" == "g++-12" ]] ; then
time sudo apt-get install -y g++-12
fi
if [[ "$CXX" == "icpc" || "$CC" == "icc" || "$USE_ICC" != "" || "$USE_ICX" != "" ]] ; then
wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
time sudo apt-get update
time sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic
set +e; source /opt/intel/oneapi/setvars.sh; set -e
fi
fi
@@ -108,14 +160,16 @@ if [[ "$LIBRAW_VERSION" != "" ]] ; then
source src/build-scripts/build_libraw.bash
fi
if [[ "$OPENJPEG_VERSION" != "" ]] ; then
source src/build-scripts/build_OpenJPEG.bash
fi
if [[ "$PUGIXML_VERSION" != "" ]] ; then
source src/build-scripts/build_pugixml.bash
export MY_CMAKE_FLAGS+=" -DUSE_EXTERNAL_PUGIXML=1 "
fi
if [[ "$OPENCOLORIO_VERSION" != "" ]] ; then
# Temporary (?) fix: GH ninja having problems, fall back to make
CMAKE_GENERATOR="Unix Makefiles" \
source src/build-scripts/build_opencolorio.bash
fi
@@ -123,8 +177,12 @@ if [[ "$PTEX_VERSION" != "" ]] ; then
source src/build-scripts/build_Ptex.bash
fi
src/build-scripts/install_test_images.bash
if [[ "$USE_ICC" != "" ]] ; then
# We used gcc for the prior dependency builds, but use icc for OIIO itself
echo "which icpc:" $(which icpc)
export CXX=icpc
export CC=icc
fi
# Save the env for use by other stages
src/build-scripts/save-env.bash
+6 -9
View File
@@ -2,7 +2,7 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
# DEP_DIR="$PWD/ext/dist"
DEP_DIR="$PWD/dist/$PLATFORM"
@@ -27,10 +27,14 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DEP_DIR/lib:$VCPKG_INSTALLATION_ROOT/i
if [[ "$PYTHON_VERSION" == "3.6" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.6.8/x64"
else
elif [[ "$PYTHON_VERSION" == "3.7" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.7.9/x64"
export Python_EXECUTABLE="/c/hostedtoolcache/windows/Python/3.7.9/x64/python.exe"
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages
elif [[ "$PYTHON_VERSION" == "3.9" ]] ; then
export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;/c/hostedtoolcache/windows/Python/3.9.10/x64"
export Python_EXECUTABLE="/c/hostedtoolcache/windows/Python/3.9.10/x64/python3.exe"
export PYTHONPATH=$OpenImageIO_ROOT/lib/python${PYTHON_VERSION}/site-packages
fi
pip install numpy
@@ -46,15 +50,12 @@ echo "---------------"
# vcpkg update
#
time vcpkg install boost-asio:x64-windows
time vcpkg install boost-container:x64-windows
time vcpkg install boost-filesystem:x64-windows
time vcpkg install boost-math:x64-windows
time vcpkg install boost-regex:x64-windows
time vcpkg install boost-stacktrace:x64-windows
time vcpkg install boost-system:x64-windows
time vcpkg install boost-thread:x64-windows
time vcpkg install boost-tokenizer:x64-windows
# # vcpkg install zlib:x64-windows
vcpkg install tiff:x64-windows
@@ -66,7 +67,6 @@ vcpkg install libjpeg-turbo:x64-windows
#
# vcpkg install libraw:x64-windows
# vcpkg install openjpeg:x64-windows
# vcpkg install libsquish:x64-windows
# # vcpkg install ffmpeg:x64-windows # takes FOREVER!
# # vcpkg install webp:x64-windows # No such vcpkg package?a
#
@@ -136,9 +136,6 @@ echo "DEP_DIR $DEP_DIR :"
ls -R -l "$DEP_DIR"
src/build-scripts/install_test_images.bash
# source src/build-scripts/build_openexr.bash
# export CMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH;$ILMBASE_ROOT;$OPENEXR_ROOT"
# source src/build-scripts/build_opencolorio.bash
+16 -25
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# This script, which assumes it is runnign on a Mac OSX with Homebrew
# This script, which assumes it is running on a Mac OSX with Homebrew
# installed, does a "brew install" in all packages reasonably needed by
# OIIO.
@@ -24,45 +24,36 @@ brew list --versions
# All cases except for clang-format target, we need the dependencies.
brew install --display-times -q gcc ccache cmake ninja boost || true
brew link --overwrite gcc
brew unlink python@2.7 || true
brew unlink python@3.9 || true
brew install --display-times -q python@${PYTHON_VERSION} || true
brew unlink python@3.8 || true
brew unlink python@3.9 || true
brew unlink python@3.10 || true
brew link --overwrite --force python@${PYTHON_VERSION} || true
brew upgrade --display-times -q cmake || true
brew install --display-times -q libtiff imath openexr opencolorio
brew install --display-times -q libpng giflib webp jpeg-turbo openjpeg
#brew upgrade --display-times -q cmake || true
#brew install --display-times -q libtiff
brew install --display-times -q imath openexr opencolorio
#brew install --display-times -q libpng giflib webp
brew install --display-times -q jpeg-turbo openjpeg
brew install --display-times -q freetype libraw dcmtk pybind11 numpy || true
brew install --display-times -q ffmpeg libheif libsquish ptex || true
brew install --display-times -q ffmpeg libheif ptex || true
brew install --display-times -q tbb || true
# No OpenVDB until it's upgraded to use Imath 3
# brew install --display-times -q openvdb || true
brew install --display-times -q openvdb || true
brew install --display-times -q opencv || true
brew install --display-times -q qt@5
brew install --display-times -q field3d || true
echo ""
echo "After brew installs:"
brew list --versions
# Needed on some systems
if [[ $PYTHON_VERSION != "2.7" ]] ; then
pip3 install numpy
else
pip install numpy
fi
pip${PYTHON_VERSION} install numpy
# Set up paths. These will only affect the caller if this script is
# run with 'source' rather than in a separate shell.
export PATH=/usr/local/opt/qt5/bin:$PATH ;
export PATH=/usr/local/opt/python/libexec/bin:$PATH ;
export PYTHONPATH=/usr/local/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH ;
export PATH=/usr/local/opt/llvm/bin:$PATH ;
# If field3d and hdf5 get even slightly out of sync, hdf5 will throw fits.
# This is unnecessary, so we disable the step to make CI more likely to
# pass in cases where they don't exactly match on the CI instances.
export HDF5_DISABLE_VERSION_CHECK=1
export PATH=/usr/local/opt/qt5/bin:$PATH
export PATH=/usr/local/opt/python/libexec/bin:$PATH
export PYTHONPATH=/usr/local/lib/python${PYTHON_VERSION}/site-packages:$PYTHONPATH
#export PATH=/usr/local/opt/llvm/bin:$PATH
# Save the env for use by other stages
src/build-scripts/save-env.bash
+13 -11
View File
@@ -1,20 +1,22 @@
#!/usr/bin/env bash
if [[ ! -e ../oiio-images ]] ; then
git clone https://github.com/OpenImageIO/oiio-images.git ../oiio-images
git clone https://github.com/OpenImageIO/oiio-images.git -b master --depth 1 ../oiio-images
# NOTE: on release branches, this should include `-b RB-x.y`` so that
# updates to the master oiio-images don't break tests in release branches.
fi
if [[ ! -e ../libtiffpic ]] ; then
curl -o pics-3.8.0.tar.gz https://download.osgeo.org/libtiff/pics-3.8.0.tar.gz
tar xf pics-3.8.0.tar.gz -C ..
fi
# if [[ ! -e ../libtiffpic ]] ; then
# curl -o pics-3.8.0.tar.gz https://download.osgeo.org/libtiff/pics-3.8.0.tar.gz
# tar xf pics-3.8.0.tar.gz -C ..
# fi
if [[ ! -e ../openexr-images ]] ; then
git clone https://github.com/openexr/openexr-images.git ../openexr-images
git clone https://github.com/openexr/openexr-images.git --depth 1 ../openexr-images
fi
if [[ ! -e ../bmpsuite ]] ; then
mkdir ../bmpsuite
curl -o bmpsuite.zip http://entropymine.com/jason/bmpsuite/bmpsuite.zip
unzip bmpsuite.zip -d ../bmpsuite
fi
# if [[ ! -e ../bmpsuite ]] ; then
# mkdir ../bmpsuite
# curl -o bmpsuite.zip http://entropymine.com/jason/bmpsuite/bmpsuite.zip
# unzip bmpsuite.zip -d ../bmpsuite
# fi
+1 -9
View File
@@ -1,10 +1,2 @@
leak:Imf_2_2
leak:Imf_2_3
leak:libIlmImf
leak:libgomp
leak:boost::detail::make_external_thread_data
leak:boost::detail::add_new_tss_node
leak:g_malloc0
leak:ArgParse::options
leak:LibRaw::copy_fuji_uncropped
leak:libtbb
leak:libjpeg
+7
View File
@@ -0,0 +1,7 @@
[oneAPI]
name=Intel® oneAPI repository
baseurl=https://yum.repos.intel.com/oneapi
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://yum.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB
+5 -2
View File
@@ -1,8 +1,11 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
add_oiio_plugin (cineoninput.cpp
libcineon/Cineon.cpp libcineon/OutStream.cpp libcineon/Codec.cpp
libcineon/Reader.cpp libcineon/Writer.cpp libcineon/CineonHeader.cpp
libcineon/Reader.cpp libcineon/CineonHeader.cpp
libcineon/ElementReadStream.cpp libcineon/InStream.cpp)
# Note: OIIO doesn't support cineon output, so we don't compile
# libcineon/Writer.cpp
+27 -24
View File
@@ -1,6 +1,6 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#include <cmath>
@@ -19,12 +19,12 @@ OIIO_PLUGIN_NAMESPACE_BEGIN
class CineonInput final : public ImageInput {
public:
CineonInput() { init(); }
virtual ~CineonInput() { close(); }
virtual const char* format_name(void) const override { return "cineon"; }
virtual bool open(const std::string& name, ImageSpec& newspec) override;
virtual bool close() override;
virtual bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
~CineonInput() override { close(); }
const char* format_name(void) const override { return "cineon"; }
bool open(const std::string& name, ImageSpec& newspec) override;
bool close() override;
bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
private:
InStream* m_stream = nullptr;
@@ -50,7 +50,7 @@ private:
// Obligatory material to make this a recognizeable imageio plugin:
// Obligatory material to make this a recognizable imageio plugin:
OIIO_PLUGIN_EXPORTS_BEGIN
OIIO_EXPORT ImageInput*
@@ -85,7 +85,7 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
m_cin.SetInStream(m_stream);
if (!m_cin.ReadHeader()) {
error("Could not read header");
errorfmt("Could not read header");
return false;
}
@@ -108,12 +108,11 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
// fill channel names
m_spec.channelnames.clear();
int gscount = 0, rcount = 0, gcount = 0, bcount = 0;
char buf[3];
for (int i = 0; i < m_cin.header.NumberOfElements(); i++) {
switch (m_cin.header.ImageDescriptor(i)) {
case cineon::kGrayscale:
if (++gscount > 1) {
std::string ch = Strutil::sprintf("I%d", gscount);
std::string ch = Strutil::fmt::format("I{}", gscount);
m_spec.channelnames.push_back(ch);
} else
m_spec.channelnames.emplace_back("I");
@@ -121,7 +120,7 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
case cineon::kPrintingDensityRed:
case cineon::kRec709Red:
if (++gscount > 1) {
std::string ch = Strutil::sprintf("R%d", rcount);
std::string ch = Strutil::fmt::format("R{}", rcount);
m_spec.channelnames.push_back(ch);
} else
m_spec.channelnames.emplace_back("R");
@@ -129,7 +128,7 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
case cineon::kPrintingDensityGreen:
case cineon::kRec709Green:
if (++gcount > 1) {
std::string ch = Strutil::sprintf("G%d", gcount);
std::string ch = Strutil::fmt::format("G{}", gcount);
m_spec.channelnames.push_back(ch);
} else
m_spec.channelnames.emplace_back("G");
@@ -137,14 +136,14 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
case cineon::kPrintingDensityBlue:
case cineon::kRec709Blue:
if (++bcount > 1) {
std::string ch = Strutil::sprintf("B%d", bcount);
std::string ch = Strutil::fmt::format("B{}", bcount);
m_spec.channelnames.push_back(ch);
} else
m_spec.channelnames.emplace_back("B");
break;
default:
std::string ch = Strutil::sprintf("channel%d",
m_spec.channelnames.size());
std::string ch = Strutil::fmt::format("channel{}",
m_spec.channelnames.size());
m_spec.channelnames.push_back(ch);
break;
}
@@ -184,7 +183,7 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
if (!std::isinf(m_cin.header.Gamma()) && m_cin.header.Gamma() != 0.0f)
// actual gamma value is read later on
m_spec.attribute("oiio:ColorSpace",
Strutil::sprintf("GammaCorrected%.2g", g));
Strutil::fmt::format("Gamma{:.2g}", g));
break;
}
@@ -201,8 +200,9 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
// libcineon's date/time format is pretty close to OIIO's (libcineon
// uses %Y:%m:%d:%H:%M:%S%Z)
m_spec.attribute("DateTime",
Strutil::sprintf("%s %s", m_cin.header.creationDate,
m_cin.header.creationTime));
Strutil::fmt::format("{} {}",
m_cin.header.creationDate,
m_cin.header.creationTime));
// FIXME: do something about the time zone
}
@@ -332,13 +332,16 @@ CineonInput::open(const std::string& name, ImageSpec& newspec)
// libcineon's date/time format is pretty close to OIIO's (libcineon
// uses %Y:%m:%d:%H:%M:%S%Z)
m_spec.attribute("DateTime",
Strutil::sprintf("%s %s", m_cin.header.sourceDate,
m_cin.header.sourceTime));
Strutil::fmt::format("{} {}", m_cin.header.sourceDate,
m_cin.header.sourceTime));
// FIXME: do something about the time zone
}
m_cin.header.FilmEdgeCode(buf);
if (buf[0])
m_spec.attribute("cineon:FilmEdgeCode", buf);
{
char filmedge[17];
m_cin.header.FilmEdgeCode(filmedge, sizeof(filmedge));
if (filmedge[0])
m_spec.attribute("cineon:FilmEdgeCode", filmedge);
}
// read in user data
if (m_cin.header.UserSize() != 0 && m_cin.header.UserSize() != 0xFFFFFFFF) {
+32 -39
View File
@@ -82,7 +82,7 @@ cineon::GenericHeader::GenericHeader()
void cineon::GenericHeader::Reset()
{
// File Information
this->magicNumber = MAGIC_COOKIE;
this->magicNumber = CINEON_MAGIC_COOKIE;
this->imageOffset = ~0;
EmptyString(this->version);
OIIO::Strutil::safe_strcpy(this->version, SPEC_VERSION, sizeof(this->version));
@@ -212,6 +212,8 @@ bool cineon::Header::Check()
#ifdef OIIO_DOES_NOT_NEED_THIS
bool cineon::Header::Write(OutStream *io)
{
// write the header to the file
@@ -254,7 +256,7 @@ bool cineon::Header::WriteOffsetData(OutStream *io)
//const long IMAGE_STRUCTURE = 72; // sizeof the image data structure
/*int i;
for (i = 0; i < MAX_ELEMENTS; i++)
for (i = 0; i < CINEON_MAX_ELEMENTS; i++)
{
// only write if there is a defined image description
if (this->chan[i].descriptor == kUndefinedDescriptor)
@@ -272,11 +274,12 @@ bool cineon::Header::WriteOffsetData(OutStream *io)
return true;
}
#endif /* OIIO_DOES_NOT_NEED_THIS */
bool cineon::Header::ValidMagicCookie(const U32 magic)
{
U32 mc = MAGIC_COOKIE;
U32 mc = CINEON_MAGIC_COOKIE;
if (magic == mc)
return true;
@@ -289,7 +292,7 @@ bool cineon::Header::ValidMagicCookie(const U32 magic)
bool cineon::Header::DetermineByteSwap(const U32 magic) const
{
U32 mc = MAGIC_COOKIE;
U32 mc = CINEON_MAGIC_COOKIE;
bool byteSwap = false;
@@ -317,7 +320,7 @@ bool cineon::Header::Validate()
SwapBytes(this->fileSize);
// Image information
for (int i = 0; i < MAX_ELEMENTS; i++)
for (int i = 0; i < CINEON_MAX_ELEMENTS; i++)
{
SwapBytes(this->chan[i].pixelsPerLine);
SwapBytes(this->chan[i].linesPerElement);
@@ -372,7 +375,7 @@ int cineon::GenericHeader::ImageElementCount() const
{
int i = 0;
while (i < MAX_ELEMENTS )
while (i < CINEON_MAX_ELEMENTS )
{
if (this->ImageDescriptor(i) == kUndefinedDescriptor)
break;
@@ -383,6 +386,7 @@ int cineon::GenericHeader::ImageElementCount() const
}
#ifdef OIIO_DOES_NOT_NEED_THIS
void cineon::GenericHeader::CalculateNumberOfElements()
{
int i = this->ImageElementCount();
@@ -398,7 +402,7 @@ void cineon::Header::CalculateOffsets()
{
int i;
for (i = 0; i < MAX_ELEMENTS; i++)
for (i = 0; i < CINEON_MAX_ELEMENTS; i++)
{
// only write if there is a defined image description
if (this->chan[i].designator[1] == kUndefinedDescriptor)
@@ -407,11 +411,12 @@ void cineon::Header::CalculateOffsets()
}
}
#endif /* OIIO_DOES_NOT_NEED_THIS */
cineon::DataSize cineon::GenericHeader::ComponentDataSize(const int element) const
{
if (element < 0 || element >= MAX_ELEMENTS)
if (element < 0 || element >= CINEON_MAX_ELEMENTS)
return kByte;
cineon::DataSize ret;
@@ -444,7 +449,7 @@ cineon::DataSize cineon::GenericHeader::ComponentDataSize(const int element) con
int cineon::GenericHeader::ComponentByteCount(const int element) const
{
if (element < 0 || element >= MAX_ELEMENTS)
if (element < 0 || element >= CINEON_MAX_ELEMENTS)
return kByte;
int ret;
@@ -500,43 +505,31 @@ int cineon::GenericHeader::DataSizeByteCount(const DataSize ds)
}
void cineon::IndustryHeader::FilmEdgeCode(char *edge) const
void cineon::IndustryHeader::FilmEdgeCode(char *edge, size_t size) const
{
if (this->filmManufacturingIdCode == 0xff
&& this->filmType == 0xff
&& this->perfsOffset == 0xff
&& this->prefix == 0xffffffff
&& this->count == 0xffffffff)
*edge = 0;
else
sprintf(edge, "%02u%02u%02u%06u%04u",
(unsigned int)this->filmManufacturingIdCode,
(unsigned int)this->filmType,
(unsigned int)this->perfsOffset,
this->prefix,
this->count);
if (this->filmManufacturingIdCode == 0xff && this->filmType == 0xff
&& this->perfsOffset == 0xff && this->prefix == 0xffffffff
&& this->count == 0xffffffff)
*edge = 0;
else
snprintf(edge, size, "%02u%02u%02u%06u%04u",
(unsigned int)this->filmManufacturingIdCode,
(unsigned int)this->filmType,
(unsigned int)this->perfsOffset, this->prefix,
this->count);
}
#ifdef OIIO_DOES_NOT_NEED_THIS
void cineon::IndustryHeader::SetFilmEdgeCode(const char *edge)
{
char buf[7];
strncpy(buf, edge, 2);
this->filmManufacturingIdCode = OIIO::Strutil::stoi(buf);
strncpy(buf, edge + 2, 2);
this->filmType = OIIO::Strutil::stoi(buf);
strncpy(buf, edge + 4, 2);
this->perfsOffset = OIIO::Strutil::stoi(buf);
strncpy(buf, edge + 6, 6);
this->prefix = OIIO::Strutil::stoi(buf);
strncpy(buf, edge + 12, 4);
this->count = OIIO::Strutil::stoi(buf);
this->filmManufacturingIdCode = OIIO::Strutil::stoi(OIIO::string_view(edge, 2));
this->filmType = OIIO::Strutil::stoi(OIIO::string_view(edge + 2, 2));
this->perfsOffset = OIIO::Strutil::stoi(OIIO::string_view(edge + 4, 2));
this->prefix = OIIO::Strutil::stoi(OIIO::string_view(edge + 6, 6));
this->count = OIIO::Strutil::stoi(OIIO::string_view(edge + 12, 4));
}
#endif /* OIIO_DOES_NOT_NEED_THIS */
void cineon::GenericHeader::SetCreationTimeDate(const long sec)
+66 -71
View File
@@ -64,24 +64,17 @@
*/
#define SPEC_VERSION "V4.5"
/*!
* \def MAX_ELEMENTS
/*!
* \def CINEON_MAX_ELEMENTS
* \brief Maximum number of image elements
*/
#define MAX_ELEMENTS 8
#define CINEON_MAX_ELEMENTS 8
/*!
* \def MAX_COMPONENTS
* \brief Maximum number of components per image element
*/
#define MAX_COMPONENTS 8
/*!
* \def MAGIC_COOKIE
/*!
* \def CINEON_MAGIC_COOKIE
* \brief HEX value of 0x802A5FD7
*/
#define MAGIC_COOKIE 0x802A5FD7
#define CINEON_MAGIC_COOKIE 0x802A5FD7
@@ -275,8 +268,8 @@ namespace cineon
U8 imageOrientation; //!< Image orientation \see Orientation
U8 numberOfElements; //!< Number of elements (1-8)
U8 unused1[2]; //!< Unused (word alignment)
ImageElement chan[MAX_ELEMENTS]; //!< Image element data structures
R32 whitePoint[2]; //!< White point (x, y pair)
ImageElement chan[CINEON_MAX_ELEMENTS]; //!< Image element data structures
R32 whitePoint[2]; //!< White point (x, y pair)
R32 redPrimary[2]; //!< Red primary chromaticity (x, y pair)
R32 greenPrimary[2]; //!< Green primary chromaticity (x, y pair)
R32 bluePrimary[2]; //!< Blue primary chromaticity (x, y pair)
@@ -856,7 +849,7 @@ namespace cineon
inline void SetXDevicePitch(const R32 size);
/*!
* \brief Get the veritcal pitch of the device
* \brief Get the vertical pitch of the device
* \return pitch in samples/mm
*/
inline R32 YDevicePitch() const;
@@ -962,7 +955,7 @@ namespace cineon
* \brief Get the film edge code information that is machine readable
* \param edge buffer to write film edge code information (16+1 chars)
*/
void FilmEdgeCode(char *edge) const;
void FilmEdgeCode(char *edge, size_t size) const;
/*!
* \brief Set the film edge code information that is machine readable
@@ -1056,6 +1049,7 @@ namespace cineon
*/
bool Read(InStream *);
#ifdef OIIO_DOES_NOT_NEED_THIS
/*!
* \brief Set the Output Stream object to write header to
*/
@@ -1063,6 +1057,7 @@ namespace cineon
// write the offset within the header
bool WriteOffsetData(OutStream *);
#endif
/*!
* \brief Validate the header
@@ -1242,30 +1237,30 @@ namespace cineon
inline U32 GenericHeader::PixelsPerLine(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return 0xffffffff;
return this->chan[i].pixelsPerLine;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return 0xffffffff;
return this->chan[i].pixelsPerLine;
}
inline void GenericHeader::SetPixelsPerLine(const int i, const U32 ppl)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].pixelsPerLine = ppl;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].pixelsPerLine = ppl;
}
inline U32 GenericHeader::LinesPerElement(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return 0xffffffff;
return this->chan[i].linesPerElement;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return 0xffffffff;
return this->chan[i].linesPerElement;
}
inline void GenericHeader::SetLinesPerElement(const int i, const U32 lpe)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].linesPerElement = lpe;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].linesPerElement = lpe;
}
inline U8 GenericHeader::DataSign() const
@@ -1280,100 +1275,100 @@ namespace cineon
inline R32 GenericHeader::LowData(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return std::numeric_limits<R32>::infinity();
return this->chan[i].lowData;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return std::numeric_limits<R32>::infinity();
return this->chan[i].lowData;
}
inline void GenericHeader::SetLowData(const int i, const R32 data)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].lowData = data;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].lowData = data;
}
inline R32 GenericHeader::LowQuantity(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return std::numeric_limits<R32>::max();
return this->chan[i].lowQuantity;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return std::numeric_limits<R32>::max();
return this->chan[i].lowQuantity;
}
inline void GenericHeader::SetLowQuantity(const int i, const R32 quant)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].lowQuantity = quant;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].lowQuantity = quant;
}
inline R32 GenericHeader::HighData(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return std::numeric_limits<R32>::max();
return this->chan[i].highData;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return std::numeric_limits<R32>::max();
return this->chan[i].highData;
}
inline void GenericHeader::SetHighData(const int i, const R32 data)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].highData = data;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].highData = data;
}
inline R32 GenericHeader::HighQuantity(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return std::numeric_limits<R32>::max();
return this->chan[i].highQuantity;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return std::numeric_limits<R32>::max();
return this->chan[i].highQuantity;
}
inline void GenericHeader::SetHighQuantity(const int i, const R32 quant)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].highQuantity = quant;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].highQuantity = quant;
}
inline U8 GenericHeader::Metric(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return 0xff;
return this->chan[i].designator[0];
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return 0xff;
return this->chan[i].designator[0];
}
inline void GenericHeader::SetMetric(const int i, const U8 m)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].designator[0] = m;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].designator[0] = m;
}
inline Descriptor GenericHeader::ImageDescriptor(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return Descriptor(0xff);
return Descriptor(this->chan[i].designator[1]);
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return Descriptor(0xff);
return Descriptor(this->chan[i].designator[1]);
}
inline void GenericHeader::SetImageDescriptor(const int i, const Descriptor desc)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].designator[1] = (U8)desc;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].designator[1] = (U8)desc;
}
inline U8 GenericHeader::BitDepth(const int i) const
{
if (i < 0 || i >= MAX_ELEMENTS)
return 0xff;
return this->chan[i].bitDepth;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return 0xff;
return this->chan[i].bitDepth;
}
inline void GenericHeader::SetBitDepth(const int i, const U8 depth)
{
if (i < 0 || i >= MAX_ELEMENTS)
return;
this->chan[i].bitDepth = depth;
if (i < 0 || i >= CINEON_MAX_ELEMENTS)
return;
this->chan[i].bitDepth = depth;
}
inline Interleave GenericHeader::ImageInterleave() const
@@ -94,7 +94,7 @@ namespace cineon
offset += block.x1 * numberOfComponents / 3 * 4;
// get the read count in bytes, round to the 32-bit boundry
// get the read count in bytes, round to the 32-bit boundary
int readSize = (block.x2 - block.x1 + 1) * numberOfComponents;
readSize += readSize % 3;
readSize = readSize / 3 * 4;
@@ -110,7 +110,7 @@ namespace cineon
for (int count = (block.x2 - block.x1 + 1) * numberOfComponents - 1; count >= 0; count--)
{
// unpacking the buffer backwords
// unpacking the buffer backwards
U16 d1 = U16(readBuf[(count + index) / 3] >> ((2 - (count + index) % 3) * 10 + PADDINGBITS) & 0x3ff);
BaseTypeConvertU10ToU16(d1, d1);
BaseTypeConverter(d1, obuf[count]);
@@ -146,7 +146,7 @@ namespace cineon
for (int i = count - 1; i >= 0; i--)
{
// unpacking the buffer backwords
// unpacking the buffer backwards
// find the byte that the data starts in, read in as a 16 bits then shift and mask
// the pattern with byte offset is:
// 10 bits datasize rotates every 4 data elements
+6 -6
View File
@@ -82,12 +82,12 @@ void cineon::Writer::SetImageInfo(const U32 width, const U32 height)
}
// returns next available or MAX_ELEMENTS if full
// returns next available or CINEON_MAX_ELEMENTS if full
int cineon::Writer::NextAvailElement() const
{
unsigned int i;
for (i = 0; i < MAX_ELEMENTS; i++)
for (i = 0; i < CINEON_MAX_ELEMENTS; i++)
{
if (this->header.ImageDescriptor(i) == kUndefinedDescriptor)
break;
@@ -139,7 +139,7 @@ void cineon::Writer::SetElement(const int num, const Descriptor desc, const U8 b
const R32 highData, const R32 highQuantity)
{
// make sure the range is good
if (num < 0 || num >= MAX_ELEMENTS)
if (num < 0 || num >= CINEON_MAX_ELEMENTS)
return;
// set values
@@ -160,7 +160,7 @@ void cineon::Writer::SetElement(const int num, const Descriptor desc, const U8 b
bool cineon::Writer::WriteElement(const int element, void *data, const long count)
{
// make sure the range is good
if (element < 0 || element >= MAX_ELEMENTS)
if (element < 0 || element >= CINEON_MAX_ELEMENTS)
return false;
// make sure the entry is valid
@@ -180,7 +180,7 @@ bool cineon::Writer::WriteElement(const int element, void *data, const long coun
bool cineon::Writer::WriteElement(const int element, void *data)
{
// make sure the range is good
if (element < 0 || element >= MAX_ELEMENTS)
if (element < 0 || element >= CINEON_MAX_ELEMENTS)
return false;
// make sure the entry is valid
@@ -197,7 +197,7 @@ bool cineon::Writer::WriteElement(const int element, void *data, const DataSize
bool status = true;
// make sure the range is good
if (element < 0 || element >= MAX_ELEMENTS)
if (element < 0 || element >= CINEON_MAX_ELEMENTS)
return false;
// make sure the entry is valid
@@ -83,12 +83,13 @@ namespace cineon
void RleCompress(IB *src, IB *dst, const int bufsize, const int len, BufferAccess &access)
{
IB ch;
int count;
// int count;
int i;
int index = bufsize - 1;
bool start = true;
//bool match = true;
#if 0 /* This seems to not be used */
// for each data type, have maximum length of rle datum
// subtract one so it the LSBit can be used to state
int maxCount;
@@ -102,13 +103,13 @@ namespace cineon
maxCount = 0xffff - 1;
else
maxCount = 1000000; // high number for floats, doubles
#endif
for (i = len - 1; i >= 0; i--)
{
if (start)
{
count = 1;
// count = 1;
start = false;
ch = src[i];
dst[index--] = ch;
+53 -13
View File
@@ -3,30 +3,70 @@
include(CMakeFindDependencyMacro)
# add here all the find_dependency() whenever switching to config based dependencies
if (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 3.0)
find_dependency(Imath @Imath_VERSION@
HINTS @Imath_DIR@)
elseif (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 2.4 AND @FOUND_OPENEXR_WITH_CONFIG@)
find_dependency(IlmBase @OpenEXR_VERSION@
HINTS @IlmBase_DIR@ @OpenEXR_DIR@)
find_dependency(OpenEXR @OpenEXR_VERSION@
HINTS @OpenEXR_DIR@)
find_dependency(ZLIB @ZLIB_VERSION@) # Because OpenEXR doesn't do it
find_dependency(Threads) # Because OpenEXR doesn't do it
if (NOT @OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH@ AND NOT OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH)
if (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 3.0)
find_dependency(Imath @Imath_VERSION@
HINTS @Imath_DIR@)
elseif (@OpenEXR_VERSION@ VERSION_GREATER_EQUAL 2.4 AND @FOUND_OPENEXR_WITH_CONFIG@)
find_dependency(IlmBase @OpenEXR_VERSION@
HINTS @IlmBase_DIR@ @OpenEXR_DIR@)
find_dependency(OpenEXR @OpenEXR_VERSION@
HINTS @OpenEXR_DIR@)
find_dependency(ZLIB @ZLIB_VERSION@) # Because OpenEXR doesn't do it
find_dependency(Threads) # Because OpenEXR doesn't do it
endif ()
endif ()
set_and_check (@PROJECT_NAME@_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
set_and_check (@PROJECT_NAME@_INCLUDES "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
set_and_check (@PROJECT_NAME@_LIB_DIR "@CMAKE_INSTALL_FULL_LIBDIR@")
if (NOT @OIIO_USING_FMT_LOCAL@ AND NOT @INTERNALIZE_FMT@)
find_dependency(fmt)
endif ()
if (NOT @BUILD_SHARED_LIBS@)
# This is required in static library builds, as e.g. PNG::PNG appears among
# INTERFACE_LINK_LIBRARIES. If the project does not know about PNG target, it will cause
# configuration error about unknown targets being linked in.
find_dependency(TIFF)
if (@JPEG_FOUND@)
find_dependency(JPEG)
endif()
if (@PNG_FOUND@)
find_dependency(PNG)
endif()
# The following have the same problem except that INTERFACE_LINK_LIBRARIES use
# TARGET_NAME_IF_EXISTS, so the error only happens on link time.
if (@OIIO_TBB@)
find_dependency(TBB)
endif ()
endif ()
# Compute the installation prefix relative to this file. Note that cmake files are installed
# to ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} (see OIIO_CONFIG_INSTALL_DIR)
get_filename_component(_CURR_INSTALL_LIBDIR "${CMAKE_CURRENT_LIST_DIR}/../../" ABSOLUTE)
get_filename_component(_ABS_CMAKE_INSTALL_LIBDIR "@CMAKE_INSTALL_FULL_LIBDIR@" ABSOLUTE)
get_filename_component(_ABS_CMAKE_INSTALL_INCLUDEDIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@" ABSOLUTE)
file(RELATIVE_PATH _INCLUDEDIR_RELATIVE_TO_LIBDIR
"${_ABS_CMAKE_INSTALL_LIBDIR}" "${_ABS_CMAKE_INSTALL_INCLUDEDIR}")
get_filename_component(_CURR_INSTALL_INCLUDE_DIR
"${_CURR_INSTALL_LIBDIR}/${_INCLUDEDIR_RELATIVE_TO_LIBDIR}" ABSOLUTE)
set_and_check (@PROJECT_NAME@_INCLUDE_DIR "${_CURR_INSTALL_INCLUDE_DIR}")
set_and_check (@PROJECT_NAME@_INCLUDES "${_CURR_INSTALL_INCLUDE_DIR}")
set_and_check (@PROJECT_NAME@_LIB_DIR "${_CURR_INSTALL_LIBDIR}")
set (@PROJECT_NAME@_PLUGIN_SEARCH_PATH "@PLUGIN_SEARCH_PATH_NATIVE@")
if (NOT @FOUND_OPENEXR_WITH_CONFIG@)
list (APPEND @PROJECT_NAME@_INCLUDES ${IMATH_INCLUDES} ${OPENEXR_INCLUDES})
endif ()
set (OIIO_USING_IMATH_VERSION_MAJOR @Imath_VERSION_MAJOR@)
set (OIIO_USING_IMATH_VERSION_MINOR @Imath_VERSION_MINOR@)
#...logic to determine installedPrefix from the own location...
#set (@PROJECT_NAME@_CONFIG_DIR "${installedPrefix}/@CONFIG_INSTALL_DIR@")
include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components ("@PROJECT_NAME@")
# Set a CMake variable that says if this OpenImageIO build has OCIO support
set (@PROJECT_NAME@_HAS_OpenColorIO @OpenColorIO_FOUND@)
+18 -14
View File
@@ -39,20 +39,24 @@ macro (add_oiio_plugin)
get_filename_component (_plugin_name ${CMAKE_CURRENT_SOURCE_DIR} NAME_WE)
if (NOT _plugin_NAME)
# If NAME is not supplied, infer target name (and therefore the
# executable name) from the directory name.
# library name) from the directory name.
get_filename_component (_plugin_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
endif ()
# if (NOT _plugin_SRC)
# # If SRC is not supplied, assume local cpp files are its source.
# file (GLOB _plugin_SRC *.cpp)
# endif ()
# If SRC is supplied, use it. Otherwise, assume any unparsed arguments are the
# source files. If there are none, then glob *.cpp of the current directory.
if (NOT _plugin_SRC)
set (_plugin_SRC ${_plugin_UNPARSED_ARGUMENTS})
endif ()
if (NOT _plugin_SRC)
file (GLOB _plugin_SRC *.cpp)
endif ()
check_is_enabled (${_plugin_name} _enable_plugin)
if (_enable_plugin)
if (EMBEDPLUGINS)
# Add each source file to the libOpenImageIO_srcs, but it takes some
# bending over backwards to change it in the parent scope.
set (_plugin_all_source ${libOpenImageIO_srcs})
foreach (_plugin_source_file ${_plugin_UNPARSED_ARGUMENTS} )
foreach (_plugin_source_file ${_plugin_SRC})
list (APPEND _plugin_all_source "${CMAKE_CURRENT_SOURCE_DIR}/${_plugin_source_file}")
endforeach ()
set (libOpenImageIO_srcs "${_plugin_all_source}" PARENT_SCOPE)
@@ -60,17 +64,17 @@ macro (add_oiio_plugin)
set (format_plugin_include_dirs ${format_plugin_include_dirs} ${_plugin_INCLUDE_DIRS} PARENT_SCOPE)
set (format_plugin_libs ${format_plugin_libs} ${_plugin_LINK_LIBRARIES} PARENT_SCOPE)
else ()
# Get the name of the current directory and use it as the target name.
get_filename_component (_plugin_name ${CMAKE_CURRENT_SOURCE_DIR} NAME)
add_library (${_plugin_name} MODULE ${_plugin_UNPARSED_ARGUMENTS})
target_compile_definitions (${_plugin_name} PRIVATE
# # Get the name of the current directory and use it as the target name.
# get_filename_component (_plugin_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME)
add_library (${_plugin_NAME} MODULE ${_plugin_SRC})
target_compile_definitions (${_plugin_NAME} PRIVATE
${_plugin_DEFINITIONS}
OpenImageIO_EXPORTS)
target_include_directories (${_plugin_name} PRIVATE ${_plugin_INCLUDE_DIRS})
target_link_libraries (${_plugin_name} PUBLIC OpenImageIO
target_include_directories (${_plugin_NAME} PRIVATE ${_plugin_INCLUDE_DIRS})
target_link_libraries (${_plugin_NAME} PUBLIC OpenImageIO
PRIVATE ${_plugin_LINK_LIBRARIES})
set_target_properties (${_plugin_name} PROPERTIES PREFIX "" FOLDER "Plugins")
install_targets (${_plugin_name})
set_target_properties (${_plugin_NAME} PROPERTIES PREFIX "" FOLDER "Plugins")
install_targets (${_plugin_NAME})
endif ()
else ()
message (STATUS "${ColorRed}Disabling ${_plugin_name} ${ColorReset}")
+1 -1
View File
@@ -1,6 +1,6 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
# Is the named package "enabled" via our disabling convention? If either
# USE_pkgname (or the all-uppercase USE_PKGNAME, or ENABLE_pkgname, or
+25 -19
View File
@@ -1,6 +1,6 @@
# Copyright Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
set (REQUIRED_DEPS "" CACHE STRING
@@ -37,8 +37,11 @@ endfunction ()
# turned off explicitly from one of these sources.
# * Print a message if the package is enabled but not found. This is based
# on ${Pkgname}_FOUND or $PKGNAME_FOUND.
# * Optional DEFINITIONS <string> are passed to add_definitions if the
# * Optional DEFINITIONS <string>... are passed to add_definitions if the
# package is found.
# * Optional SETVARIABLES <id>... is a list of CMake variables to set to
# TRUE if the package is found (they will not be set or changed if the
# package is not found).
# * Optional PRINT <list> is a list of variables that will be printed
# if the package is found, if VERBOSE is on.
# * Optional DEPS <list> is a list of hard dependencies; for each one, if
@@ -74,7 +77,7 @@ macro (checked_find_package pkgname)
# singleValueKeywords:
"ENABLE;ISDEPOF;VERSION_MIN;VERSION_MAX;RECOMMEND_MIN;RECOMMEND_MIN_REASON"
# multiValueKeywords:
"DEFINITIONS;PRINT;DEPS"
"DEFINITIONS;PRINT;DEPS;SETVARIABLES"
# argsToParse:
${ARGN})
string (TOLOWER ${pkgname} pkgname_lower)
@@ -143,23 +146,10 @@ macro (checked_find_package pkgname)
endif ()
endforeach ()
message (STATUS "${ColorGreen}Found ${pkgname} ${${pkgname}_VERSION} ${_config_status}${ColorReset}")
if (_pkg_VERBOSE)
if (_pkg_DEBUG)
dump_matching_variables (${pkgname})
endif ()
set (_vars_to_print ${pkgname}_INCLUDES ${pkgname_upper}_INCLUDES
${pkgname}_INCLUDE_DIR ${pkgname_upper}_INCLUDE_DIR
${pkgname}_INCLUDE_DIRS ${pkgname_upper}_INCLUDE_DIRS
${pkgname}_LIBRARIES ${pkgname_upper}_LIBRARIES
${_pkg_PRINT})
list (REMOVE_DUPLICATES _vars_to_print)
foreach (_v IN LISTS _vars_to_print)
if (NOT "${${_v}}" STREQUAL "")
message (STATUS " ${_v} = ${${_v}}")
endif ()
endforeach ()
endif ()
add_definitions (${_pkg_DEFINITIONS})
foreach (_v IN LISTS _pkg_SETVARIABLES)
set (${_v} TRUE)
endforeach ()
if (_pkg_RECOMMEND_MIN)
if (${${pkgname}_VERSION} VERSION_LESS ${_pkg_RECOMMEND_MIN})
message (STATUS "${ColorYellow}Recommend ${pkgname} >= ${_pkg_RECOMMEND_MIN} ${_pkg_RECOMMEND_MIN_REASON} ${ColorReset}")
@@ -187,6 +177,22 @@ macro (checked_find_package pkgname)
message (FATAL_ERROR "${ColorRed}${pkgname} is required, aborting.${ColorReset}")
endif ()
endif()
if (_pkg_VERBOSE AND (${pkgname}_FOUND OR ${pkgname_upper}_FOUND OR _pkg_DEBUG))
if (_pkg_DEBUG)
dump_matching_variables (${pkgname})
endif ()
set (_vars_to_print ${pkgname}_INCLUDES ${pkgname_upper}_INCLUDES
${pkgname}_INCLUDE_DIR ${pkgname_upper}_INCLUDE_DIR
${pkgname}_INCLUDE_DIRS ${pkgname_upper}_INCLUDE_DIRS
${pkgname}_LIBRARIES ${pkgname_upper}_LIBRARIES
${_pkg_PRINT})
list (REMOVE_DUPLICATES _vars_to_print)
foreach (_v IN LISTS _vars_to_print)
if (NOT "${${_v}}" STREQUAL "")
message (STATUS " ${_v} = ${${_v}}")
endif ()
endforeach ()
endif ()
else ()
if (NOT _quietskip)
message (STATUS "${ColorRed}Not using ${pkgname} -- disabled ${_disablereason} ${ColorReset}")
+1 -1
View File
@@ -1,6 +1,6 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
# Define color codes for pretty terminal output
+132 -42
View File
@@ -1,6 +1,6 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
###########################################################################
#
@@ -28,10 +28,12 @@ message (STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
# C++ language standard
#
set (CMAKE_CXX_STANDARD 14 CACHE STRING
"C++ standard to prefer (14, 17, 20, etc.)")
"C++ standard to build with (14, 17, 20, etc.)")
set (DOWNSTREAM_CXX_STANDARD 14 CACHE STRING
"C++ minimum standard to impose on downstream clients")
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CMAKE_CXX_EXTENSIONS OFF)
message (STATUS "Building for C++${CMAKE_CXX_STANDARD}")
message (STATUS "Building with C++${CMAKE_CXX_STANDARD}, downstream minimum C++${DOWNSTREAM_CXX_STANDARD}")
###########################################################################
@@ -49,7 +51,8 @@ else ()
set (GCC_VERSION 0)
endif ()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lang")
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lang"
OR CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
# If using any flavor of clang, set CMAKE_COMPILER_IS_CLANG. If it's
# Apple's variety, set CMAKE_COMPILER_IS_APPLECLANG and
# APPLECLANG_VERSION_STRING, otherwise for generic clang set
@@ -63,6 +66,12 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER MATCHES "[Cc]lan
if (VERBOSE)
message (STATUS "The compiler is Clang: ${CMAKE_CXX_COMPILER_ID} version ${APPLECLANG_VERSION_STRING}")
endif ()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
set (CMAKE_COMPILER_IS_INTELCLANG 1)
string (REGEX MATCH "[0-9]+(\\.[0-9]+)+" INTELCLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
message (STATUS "The compiler is Intel Clang: ${CMAKE_CXX_COMPILER_ID} version ${INTELCLANG_VERSION_STRING}")
endif ()
else ()
string (REGEX REPLACE ".* version ([0-9]+\\.[0-9]+).*" "\\1" CLANG_VERSION_STRING ${clang_full_version_string})
if (VERBOSE)
@@ -80,10 +89,14 @@ endif ()
###########################################################################
# Turn on more detailed warnings and optionally consider warnings as errors
#
if (${PROJECT_NAME}_SUPPORTED_RELEASE)
option (STOP_ON_WARNING "Stop building if there are any compiler warnings" OFF)
else ()
if (NOT ${PROJECT_NAME}_SUPPORTED_RELEASE OR DEFINED ENV{${PROJECT_NAME}_CI})
# For development branches (i.e., not a supported release), or when
# running CI, default to treating all warnings as errors.
option (STOP_ON_WARNING "Stop building if there are any compiler warnings" ON)
else ()
# For release branches not doing a CI build default to just printing
# warnings but not letting them stop the build.
option (STOP_ON_WARNING "Stop building if there are any compiler warnings" OFF)
endif()
option (EXTRA_WARNINGS "Enable lots of extra pedantic warnings" OFF)
if (NOT MSVC)
@@ -91,11 +104,8 @@ if (NOT MSVC)
if (EXTRA_WARNINGS)
add_compile_options ("-Wextra")
endif ()
if (STOP_ON_WARNING OR DEFINED ENV{CI})
if (STOP_ON_WARNING)
add_compile_options ("-Werror")
# N.B. Force CI builds to use -Werror, even if STOP_ON_WARNING has
# been switched off by default, which we may do in release
# branches.
endif ()
endif ()
@@ -115,7 +125,7 @@ set (CXX_VISIBILITY_PRESET "hidden" CACHE STRING "Symbol visibility (hidden or d
option (VISIBILITY_INLINES_HIDDEN "Hide symbol visibility of inline functions" ON)
set (VISIBILITY_MAP_FILE "${PROJECT_SOURCE_DIR}/src/build-scripts/hidesymbols.map" CACHE FILEPATH "Visibility map file")
set (C_VISIBILITY_PRESET ${CXX_VISIBILITY_PRESET})
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND
if (${CXX_VISIBILITY_PRESET} STREQUAL "hidden" AND VISIBILITY_MAP_FILE AND
(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) AND
(CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU"))
# Linux/FreeBSD/Hurd: also hide all the symbols of dependent libraries
@@ -168,13 +178,17 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
# Ensure this macro is set for stdint.h
add_definitions ("-D__STDC_LIMIT_MACROS")
add_definitions ("-D__STDC_CONSTANT_MACROS")
# this allows native instructions to be used for sqrtf instead of a function call
add_compile_options ("-fno-math-errno")
endif ()
if (INTELCLANG_VERSION_STRING VERSION_GREATER_EQUAL 2022.1.0)
# New versions of icx warn about changing certain floating point options
add_compile_options ("-Wno-overriding-t-option")
endif ()
if (MSVC)
# Microsoft specific options
add_compile_options (/W1)
add_compile_options (/MP)
add_definitions (-D_CRT_SECURE_NO_DEPRECATE)
add_definitions (-D_CRT_SECURE_NO_WARNINGS)
add_definitions (-D_CRT_NONSTDC_NO_WARNINGS)
@@ -188,6 +202,32 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
add_compile_options (-march=i586)
endif ()
# Fast-math mode may go faster, but it breaks IEEE and also makes inconsistent
# results on different compilers/platforms, so we don't use it by default.
option (ENABLE_FAST_MATH "Use fast math (may break IEEE fp rules)" OFF)
if (ENABLE_FAST_MATH)
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
add_compile_options ("-ffast-math")
elseif (MSVC)
add_compile_options ("/fp:fast")
endif ()
else ()
if (CMAKE_COMPILER_IS_INTELCLANG)
# Intel icx is fast-math by default, so if we don't want that, we need
# to explicitly disable it.
add_compile_options ("-fno-fast-math")
endif ()
endif ()
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
# this allows native instructions to be used for sqrtf instead of a function call
add_compile_options ("-fno-math-errno")
endif ()
# We will use this for ccache and timing
set (MY_RULE_LAUNCH "")
###########################################################################
# Use ccache if found
@@ -202,12 +242,30 @@ if (CCACHE_FOUND AND USE_CCACHE)
if (CMAKE_COMPILER_IS_CLANG AND USE_QT AND (NOT DEFINED ENV{CCACHE_CPP2}))
message (STATUS "Ignoring ccache because clang + Qt + env CCACHE_CPP2 is not set")
else ()
set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
set (MY_RULE_LAUNCH ccache)
endif ()
endif ()
###########################################################################
# Build time debugging aid: time all compile & link commands
#
# Note, though, that this is not especially helpful when doing a parallel
# build. If you wish to time individual compile commands, it's best to also
# set `-j 1` or CMAKE_BUILD_PARALLEL_LEVEL to 1.
option (TIME_COMMANDS "Time each compile and link command" OFF)
if (TIME_COMMANDS)
set (MY_RULE_LAUNCH "${CMAKE_COMMAND} -E time ${MY_RULE_LAUNCH}")
endif ()
# Note: This must be after any option that alters MY_RULE_LAUNCH
if (MY_RULE_LAUNCH)
set_property (GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${MY_RULE_LAUNCH})
set_property (GLOBAL PROPERTY RULE_LAUNCH_LINK ${MY_RULE_LAUNCH})
endif ()
###########################################################################
# Option to force use of libc++ (the LLVM project's alternate C++ standard
# library). Currently this only has an effect if using clang as the
@@ -281,6 +339,7 @@ if (NOT VERBOSE)
set (CMAKE_REQUIRED_QUIET 1)
endif ()
include (CMakePushCheckState)
include (CheckCXXSourceCompiles)
include (CheckCXXSourceRuns)
include (CheckLibraryExists)
@@ -289,7 +348,7 @@ include (CheckLibraryExists)
# Check if we need libatomic on this platform. We shouldn't on mainstream
# x86/x86_64, but might on some other platforms.
#
if (NOT MSVC AND NOT APPLE)
if (NOT MSVC AND NOT APPLE AND NOT ANDROID)
cmake_push_check_state ()
check_cxx_source_runs(
"#include <atomic>
@@ -317,17 +376,38 @@ if (NOT MSVC AND NOT APPLE)
endif ()
###########################################################################
# Check if we need have std::filesystem on this platform.
#
cmake_push_check_state ()
set (CMAKE_REQUIRED_DEFINITIONS ${CSTD_FLAGS})
check_cxx_source_compiles("#include <filesystem>
int main() { std::filesystem::path p; return 0; }"
USE_STD_FILESYSTEM)
if (USE_STD_FILESYSTEM AND GCC_VERSION AND GCC_VERSION VERSION_LESS 9.0)
message (STATUS "Excluding USE_STD_FILESYSTEM because gcc is ${GCC_VERSION}")
set (USE_STD_FILESYSTEM OFF)
endif ()
if (USE_STD_FILESYSTEM)
# Note: std::filesystem seems unreliable for gcc until 9
message (STATUS "Compiler supports std::filesystem")
add_definitions (-DUSE_STD_FILESYSTEM)
else ()
message (STATUS "Using Boost::filesystem")
add_definitions (-DUSE_BOOST_FILESYSTEM)
endif ()
cmake_pop_check_state ()
###########################################################################
# Code coverage options
#
option (CODECOV "Build code coverage tests" OFF)
if (CODECOV AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
message (STATUS "Compiling for code coverage analysis")
add_compile_options ("-ftest-coverage -fprofile-arcs -O0")
add_compile_options (-ftest-coverage -fprofile-arcs)
add_link_options (-ftest-coverage -fprofile-arcs)
add_definitions ("-D${PROJ_NAME}_CODE_COVERAGE=1")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
endif ()
@@ -341,22 +421,9 @@ if (SANITIZE AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
foreach (feature ${SANITIZE_FEATURE_LIST})
message (STATUS " sanitize feature: ${feature}")
add_compile_options (-fsanitize=${feature})
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=${feature}")
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=${feature}")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=${feature}")
add_link_options (-fsanitize=${feature})
endforeach()
add_compile_options (-g -fno-omit-frame-pointer)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set (SANITIZE_ON_LINUX 1)
endif ()
if (CMAKE_COMPILER_IS_GNUCC AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
add_compile_options ("-fuse-ld=gold")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
set (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=gold")
set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold")
set (SANITIZE_LIBRARIES "asan;pthread")
# set (SANITIZE_LIBRARIES "asan" "ubsan")
endif()
if (CMAKE_COMPILER_IS_GNUCC)
# turn on glibcxx extra annotations to find vector writes past end
add_definitions ("-D_GLIBCXX_SANITIZE_VECTOR=1")
@@ -365,6 +432,29 @@ if (SANITIZE AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
endif ()
###########################################################################
# Fortification and hardening options
#
# In modern gcc and clang, FORTIFY_SOURCE provides buffer overflow checks
# (with some compiler-assisted deduction of buffer lengths) for the following
# functions: memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy,
# strcat, strncat, sprintf, vsprintf, snprintf, vsnprintf, gets.
#
# We try to avoid these unsafe functions anyway, but it's good to have the
# extra protection, at least as an extra set of checks during CI. Some users
# may also wish to enable it at some level if they are deploying it in a
# security-sensitive environment. FORTIFY_SOURCE=3 may have minor performance
# impact, though FORTIFY_SOURCE=2 should not have a measurable effect on
# performance versus not doing any fortification. All fortification levels are
# not available in all compilers.
set (FORTIFY_SOURCE "0" CACHE STRING "Turn on Fortification level (0, 1, 2, 3)")
if (FORTIFY_SOURCE AND (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG))
message (STATUS "Compiling with _FORTIFY_SOURCE=${FORTIFY_SOURCE}")
add_compile_options (-D_FORTIFY_SOURCE=${FORTIFY_SOURCE})
endif ()
###########################################################################
# clang-tidy options
#
@@ -419,16 +509,15 @@ endif ()
#
# Note: skip all of this checking, setup, and cmake-format target if this
# is being built as a subproject.
if (NOT ${PROJECT_NAME}_IS_SUBPROJECT)
if (PROJECT_IS_TOP_LEVEL)
set (CLANG_FORMAT_EXE_HINT "" CACHE PATH "clang-format executable's directory (will search if not specified")
set (CLANG_FORMAT_INCLUDES "src/*.h" "src/*.cpp"
CACHE STRING "Glob patterns to include for clang-format")
set (CLANG_FORMAT_EXCLUDES "*pugixml*" "*SHA1*" "*/farmhash.cpp"
"src/dpx.imageio/libdpx/*"
"src/cineon.imageio/libcineon/*"
"src/dds.imageio/squish/*"
"src/dds.imageio/bcdec.h"
"src/gif.imageio/gif.h"
"src/hdr.imageio/rgbe.cpp"
"src/libutil/stb_sprintf.h"
CACHE STRING "Glob patterns to exclude for clang-format")
find_program (CLANG_FORMAT_EXE
@@ -463,7 +552,7 @@ endif ()
set (EXTRA_CPP_ARGS "" CACHE STRING "Extra C++ command line definitions")
if (EXTRA_CPP_ARGS)
message (STATUS "Extra C++ args: ${EXTRA_CPP_ARGS}")
add_compile_options ("${EXTRA_CPP_ARGS}")
add_compile_options (${EXTRA_CPP_ARGS})
endif()
set (EXTRA_DSO_LINK_ARGS "" CACHE STRING "Extra command line definitions when building DSOs")
@@ -515,9 +604,10 @@ endif ()
###########################################################################
# Any extra logic to be run only for CI builds goes here.
# We expect our own CI runs to define env variable ${PROJECT_NAME}_CI
#
if (DEFINED ENV{CI} OR DEFINED ENV{GITHUB_ACTIONS})
add_definitions ("-D${PROJ_NAME}_CI=1" "-DBUILD_CI=1")
if (DEFINED ENV{${PROJECT_NAME}_CI})
add_definitions (-D${PROJ_NAME}_CI=1 -DBUILD_CI=1)
if (APPLE)
# Keep Mono framework from being incorrectly searched for include
# files on GitHub Actions CI.
@@ -529,7 +619,7 @@ endif ()
###########################################################################
# Rpath handling at the install step
#
set (MACOSX_RPATH ON)
# set (MACOSX_RPATH ON)
if (CMAKE_SKIP_RPATH)
# We need to disallow the user from truly setting CMAKE_SKIP_RPATH, since
# we want to run the generated executables from the build tree in order to
+81 -54
View File
@@ -1,6 +1,6 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
###########################################################################
# Find external dependencies
@@ -29,6 +29,8 @@ include (ExternalProject)
option (BUILD_MISSING_DEPS "Try to download and build any missing dependencies" OFF)
include (FindThreads)
###########################################################################
# Boost setup
@@ -36,31 +38,36 @@ if (MSVC)
# Disable automatic linking using pragma comment(lib,...) of boost libraries upon including of a header
add_definitions (-DBOOST_ALL_NO_LIB=1)
endif ()
if (LINKSTATIC)
set (Boost_USE_STATIC_LIBS ON)
else ()
if (MSVC)
# If the build system hasn't been specifically told how to link Boost, link it the same way as other
# OIIO dependencies:
if (NOT DEFINED Boost_USE_STATIC_LIBS)
set (Boost_USE_STATIC_LIBS "${LINKSTATIC}")
endif ()
if (MSVC)
# Not linking Boost as static libraries: either an explicit setting or LINKSTATIC is FALSE:
if (NOT Boost_USE_STATIC_LIBS)
add_definitions (-DBOOST_ALL_DYN_LINK=1)
endif ()
endif ()
if (BOOST_CUSTOM)
set (Boost_FOUND true)
# N.B. For a custom version, the caller had better set up the variables
# Boost_VERSION, Boost_INCLUDE_DIRS, Boost_LIBRARY_DIRS, Boost_LIBRARIES.
else ()
set (Boost_COMPONENTS filesystem system thread)
# The FindBoost.cmake interface is broken if it uses boost's installed
# cmake output (e.g. boost 1.70.0, cmake <= 3.14). Specifically it fails
# to set the expected variables printed below. So until that's fixed
# force FindBoost.cmake to use the original brute force path.
set (Boost_NO_BOOST_CMAKE ON)
checked_find_package (Boost REQUIRED
VERSION_MIN 1.53
COMPONENTS ${Boost_COMPONENTS}
RECOMMEND_MIN 1.66
RECOMMEND_MIN_REASON "Boost 1.66 is the oldest version our CI tests against"
PRINT Boost_INCLUDE_DIRS Boost_LIBRARIES )
set (Boost_COMPONENTS thread)
if (NOT USE_STD_FILESYSTEM)
list (APPEND Boost_COMPONENTS filesystem)
endif ()
message (STATUS "Boost_COMPONENTS = ${Boost_COMPONENTS}")
# The FindBoost.cmake interface is broken if it uses boost's installed
# cmake output (e.g. boost 1.70.0, cmake <= 3.14). Specifically it fails
# to set the expected variables printed below. So until that's fixed
# force FindBoost.cmake to use the original brute force path.
set (Boost_NO_BOOST_CMAKE ON)
checked_find_package (Boost REQUIRED
VERSION_MIN 1.53
COMPONENTS ${Boost_COMPONENTS}
RECOMMEND_MIN 1.66
RECOMMEND_MIN_REASON "Boost 1.66 is the oldest version our CI tests against"
PRINT Boost_INCLUDE_DIRS Boost_LIBRARIES )
# On Linux, Boost 1.55 and higher seems to need to link against -lrt
if (CMAKE_SYSTEM_NAME MATCHES "Linux"
@@ -87,36 +94,52 @@ checked_find_package (TIFF REQUIRED
# IlmBase & OpenEXR
checked_find_package (OpenEXR REQUIRED
VERSION_MIN 2.0
RECOMMEND_MIN 2.2
RECOMMEND_MIN_REASON "for DWA compression"
VERSION_MIN 2.3
RECOMMEND_MIN 2.4
PRINT IMATH_INCLUDES OPENEXR_INCLUDES)
# Force Imath includes to be before everything else to ensure that we have
# the right Imath/OpenEXR version, not some older version in the system
# library. This shoudn't be necessary, except for the common case of people
# library. This shouldn't be necessary, except for the common case of people
# building against Imath/OpenEXR 3.x when there is still a system-level
# install version of 2.x.
include_directories(BEFORE ${IMATH_INCLUDES} ${OPENEXR_INCLUDES})
if (CMAKE_COMPILER_IS_CLANG AND OPENEXR_VERSION VERSION_LESS 2.3)
# clang C++ >= 11 doesn't like 'register' keyword in old exr headers
add_compile_options (-Wno-deprecated-register)
endif ()
if (MSVC AND NOT LINKSTATIC)
add_definitions (-DOPENEXR_DLL) # Is this needed for new versions?
endif ()
if (OPENEXR_VERSION VERSION_GREATER_EQUAL 2.5.99)
if (OPENEXR_VERSION VERSION_GREATER_EQUAL 3.0)
set (OIIO_USING_IMATH 3)
else ()
set (OIIO_USING_IMATH 2)
endif ()
set (OPENIMAGEIO_IMATH_TARGETS
# For OpenEXR/Imath 3.x:
$<TARGET_NAME_IF_EXISTS:Imath::Imath>
$<TARGET_NAME_IF_EXISTS:Imath::Half>
# For OpenEXR >= 2.4/2.5 with reliable exported targets
$<TARGET_NAME_IF_EXISTS:IlmBase::Imath>
$<TARGET_NAME_IF_EXISTS:IlmBase::Half>
$<TARGET_NAME_IF_EXISTS:IlmBase::Iex>
# For OpenEXR <= 2.3:
${ILMBASE_LIBRARIES} )
set (OPENIMAGEIO_OPENEXR_TARGETS
# For OpenEXR/Imath 3.x:
$<TARGET_NAME_IF_EXISTS:OpenEXR::OpenEXR>
# For OpenEXR >= 2.4/2.5 with reliable exported targets
$<TARGET_NAME_IF_EXISTS:OpenEXR::IlmImf>
$<TARGET_NAME_IF_EXISTS:IlmBase::IlmThread>
$<TARGET_NAME_IF_EXISTS:IlmBase::Iex>
# For OpenEXR <= 2.3:
${OPENEXR_LIBRARIES} )
set (OPENIMAGEIO_IMATH_DEPENDENCY_VISIBILITY "PUBLIC" CACHE STRING
"Should we expose Imath library dependency as PUBLIC or PRIVATE")
set (OPENIMAGEIO_CONFIG_DO_NOT_FIND_IMATH OFF CACHE BOOL
"Exclude find_dependency(Imath) from the exported OpenImageIOConfig.cmake")
# JPEG -- prefer Turbo-JPEG to regular libjpeg
checked_find_package (JPEGTurbo
DEFINITIONS -DUSE_JPEG_TURBO=1
PRINT JPEG_INCLUDES JPEG_INCLUDE_DIRS
JPEG_LIBRARIES)
JPEG_LIBRARIES JPEG_VERSION)
if (NOT JPEG_FOUND) # Try to find the non-turbo version
checked_find_package (JPEG REQUIRED)
endif ()
@@ -151,24 +174,31 @@ endif ()
checked_find_package (Freetype
DEFINITIONS -DUSE_FREETYPE=1 )
checked_find_package (HDF5
ISDEPOF Field3D)
checked_find_package (OpenColorIO
DEFINITIONS -DUSE_OCIO=1 -DUSE_OPENCOLORIO=1)
DEFINITIONS -DUSE_OCIO=1 -DUSE_OPENCOLORIO=1
# PREFER_CONFIG
)
if (OpenColorIO_FOUND)
option (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS
"For deveoper debugging/testing ONLY! Disable OCIO 2.2 builtin configs." OFF)
if (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS OR "$ENV{OIIO_DISABLE_BUILTIN_OCIO_CONFIGS}")
add_compile_definitions(OIIO_DISABLE_BUILTIN_OCIO_CONFIGS)
endif ()
else ()
set (OpenColorIO_FOUND 0)
endif ()
checked_find_package (OpenCV 3.0
DEFINITIONS -DUSE_OPENCV=1)
# Intel TBB
set (TBB_USE_DEBUG_BUILD OFF)
checked_find_package (TBB 2017
DEFINITIONS -DUSE_TBB=1
SETVARIABLES OIIO_TBB
PREFER_CONFIG)
checked_find_package (DCMTK VERSION_MIN 3.6.1) # For DICOM images
checked_find_package (FFmpeg VERSION_MIN 3.0)
checked_find_package (Field3D
DEPS HDF5
DEFINITIONS -DUSE_FIELD3D=1)
checked_find_package (GIF
VERSION_MIN 4
RECOMMEND_MIN 5.0
@@ -196,7 +226,11 @@ if (LibRaw_FOUND AND LibRaw_VERSION VERSION_LESS 0.20 AND CMAKE_CXX_STANDARD VER
# set (LIBRAW_FOUND 0)
endif ()
checked_find_package (OpenJPEG VERSION_MIN 2.0)
checked_find_package (OpenJPEG VERSION_MIN 2.0
RECOMMEND_MIN 2.2
RECOMMEND_MIN_REASON "for multithreading support")
# Note: Recent OpenJPEG versions have exported cmake configs, but we don't
# find them reliable at all, so we stick to our FindOpenJPEG.cmake module.
checked_find_package (OpenVDB
VERSION_MIN 5.0
@@ -276,22 +310,13 @@ macro (find_or_download_robin_map)
endmacro()
###########################################################################
# libsquish
option (USE_EMBEDDED_LIBSQUISH
"Force use of embedded Libsquish, even if external is found" OFF)
if (NOT USE_EMBEDDED_LIBSQUISH)
checked_find_package (Libsquish)
endif ()
###########################################################################
# fmtlib
option (BUILD_FMT_FORCE "Force local download/build of fmt even if installed" OFF)
option (BUILD_MISSING_FMT "Local download/build of fmt if not installed" ON)
set (BUILD_FMT_VERSION "7.1.3" CACHE STRING "Preferred fmtlib/fmt version, when downloading/building our own")
option (INTERNALIZE_FMT "Copy fmt headers into <install>/include/OpenImageIO/detail/fmt" ON)
set (BUILD_FMT_VERSION "9.1.0" CACHE STRING "Preferred fmtlib/fmt version, when downloading/building our own")
macro (find_or_download_fmt)
# If we weren't told to force our own download/build of fmt, look
@@ -320,9 +345,11 @@ macro (find_or_download_fmt)
endif ()
endif ()
set (FMT_INCLUDE_DIR "${FMT_INSTALL_DIR}/include")
set (OIIO_USING_FMT_LOCAL TRUE)
else ()
set (OIIO_USING_FMT_LOCAL FALSE)
endif ()
checked_find_package (fmt REQUIRED)
endmacro()
find_or_download_fmt()
include_directories (${FMT_INCLUDES})
+15 -2
View File
@@ -12,6 +12,9 @@
# The executable may be disabled individually using any of the usual
# check_is_enabled() conventions (e.g. -DENABLE_<executable>=OFF).
#
# If -DENABLE_INSTALL_<executable>=OFF was specified, the target will be built
# (in the build area) but will not be installed.
#
# Usage:
#
# fancy_add_executable ([ NAME targetname ... ]
@@ -42,13 +45,23 @@ macro (fancy_add_executable)
target_include_directories (${_target_NAME} SYSTEM PRIVATE ${_target_SYSTEM_INCLUDE_DIRS})
endif ()
if (_target_DEFINITIONS)
target_compile_definitions (${_target_name} PRIVATE ${_target_DEFINITIONS})
target_compile_definitions (${_target_NAME} PRIVATE ${_target_DEFINITIONS})
endif ()
if (_target_LINK_LIBRARIES)
target_link_libraries (${_target_NAME} PRIVATE ${_target_LINK_LIBRARIES})
endif ()
set_target_properties (${_target_NAME} PROPERTIES FOLDER "Tools")
install_targets (${_target_NAME})
check_is_enabled (INSTALL_${_target_NAME} _target_NAME_INSTALL_enabled)
if (CMAKE_UNITY_BUILD AND UNITY_BUILD_MODE STREQUAL GROUP)
set_source_files_properties(${_target_SRC} PROPERTIES
UNITY_GROUP ${_target_NAME})
if (VERBOSE)
message (STATUS "Unity group ${_target_NAME} = ${_target_SRC}")
endif ()
endif ()
if (_target_NAME_INSTALL_enabled)
install_targets (${_target_NAME})
endif ()
else ()
message (STATUS "${ColorRed}Disabling ${_target_NAME} ${ColorReset}")
endif ()
+14 -6
View File
@@ -18,7 +18,7 @@
# Modifications:
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
if (FFMPEG_INCLUDES AND FFMPEG_LIBRARIES)
set (FFmpeg_FOUND TRUE)
@@ -59,17 +59,25 @@ else ()
endif ()
if (FFMPEG_INCLUDES)
file(STRINGS "${FFMPEG_INCLUDES}/libavcodec/version.h" TMP
set (_libavcodec_version_major_h "${FFMPEG_INCLUDES}/libavcodec/version_major.h")
if (NOT EXISTS "${_libavcodec_version_major_h}")
set (_libavcodec_version_major_h "${FFMPEG_INCLUDES}/libavcodec/version.h")
endif()
file(STRINGS "${_libavcodec_version_major_h}" TMP
REGEX "^#define LIBAVCODEC_VERSION_MAJOR .*$")
string (REGEX MATCHALL "[0-9]+[.0-9]+" LIBAVCODEC_VERSION_MAJOR ${TMP})
string (REGEX MATCHALL "[0-9]+[.0-9]+" LIBAVCODEC_VERSION_MAJOR "${TMP}")
file(STRINGS "${FFMPEG_INCLUDES}/libavcodec/version.h" TMP
REGEX "^#define LIBAVCODEC_VERSION_MINOR .*$")
string (REGEX MATCHALL "[0-9]+[.0-9]+" LIBAVCODEC_VERSION_MINOR ${TMP})
string (REGEX MATCHALL "[0-9]+[.0-9]+" LIBAVCODEC_VERSION_MINOR "${TMP}")
file(STRINGS "${FFMPEG_INCLUDES}/libavcodec/version.h" TMP
REGEX "^#define LIBAVCODEC_VERSION_MICRO .*$")
string (REGEX MATCHALL "[0-9]+[.0-9]+" LIBAVCODEC_VERSION_MICRO ${TMP})
string (REGEX MATCHALL "[0-9]+[.0-9]+" LIBAVCODEC_VERSION_MICRO "${TMP}")
set (LIBAVCODEC_VERSION "${LIBAVCODEC_VERSION_MAJOR}.${LIBAVCODEC_VERSION_MINOR}.${LIBAVCODEC_VERSION_MICRO}")
if (LIBAVCODEC_VERSION VERSION_GREATER_EQUAL 58.134.100)
if (LIBAVCODEC_VERSION VERSION_GREATER_EQUAL 59.37.100)
set (FFMPEG_VERSION 5.1)
elseif (LIBAVCODEC_VERSION VERSION_GREATER_EQUAL 59.18.100)
set (FFMPEG_VERSION 5.0)
elseif (LIBAVCODEC_VERSION VERSION_GREATER_EQUAL 58.134.100)
set (FFMPEG_VERSION 4.4)
elseif (LIBAVCODEC_VERSION VERSION_GREATER_EQUAL 58.91.100)
set (FFMPEG_VERSION 4.3)
-47
View File
@@ -1,47 +0,0 @@
# Module to find Field3D
#
# This module will first look into the directories defined by the variables:
# - Field3D_ROOT, FIELD3D_INCLUDE_PATH, FIELD3D_LIBRARY_PATH
#
# This module defines the following variables:
#
# Field3D_FOUND True if Field3D was found.
# FIELD3D_INCLUDES Where to find Field3D headers
# FIELD3D_LIBRARIES List of libraries to link against when using Field3D
# FIELD3D_VERSION Version of Field3D (e.g., 3.6.2)
include (FindPackageHandleStandardArgs)
find_path (FIELD3D_INCLUDE_DIR Field3D/Field.h
HINTS
${FIELD3D_INCLUDE_PATH}
ENV FIELD3D_INCLUDE_PATH
DOC "The directory where Field3D headers reside")
find_library (FIELD3D_LIBRARY Field3D
HINTS
${FIELD3D_LIBRARY_PATH}
ENV FIELD3D_LIBRARY_PATH
DOC "The Field3D libraries")
find_package_handle_standard_args (Field3D
REQUIRED_VARS FIELD3D_INCLUDE_DIR FIELD3D_LIBRARY
)
if (Field3D_FOUND)
set (FIELD3D_INCLUDES ${FIELD3D_INCLUDE_DIR})
set (FIELD3D_LIBRARIES ${FIELD3D_LIBRARY})
if (NOT TARGET Field3D::Field3D)
add_library(Field3D::Field3D UNKNOWN IMPORTED)
set_target_properties(Field3D::Field3D PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${FIELD3D_INCLUDES}")
set_property(TARGET Field3D::Field3D APPEND PROPERTY
IMPORTED_LOCATION "${FIELD3D_LIBRARIES}")
endif ()
endif ()
mark_as_advanced (
FIELD3D_INCLUDE_DIR
FIELD3D_LIBRARY
)
+12
View File
@@ -29,6 +29,12 @@ endif ()
if (JPEG_INCLUDE_DIR AND JPEG_LIBRARY)
set (JPEG_INCLUDE_DIRS ${JPEG_INCLUDE_DIR} CACHE PATH "JPEG include dirs")
set (JPEG_LIBRARIES ${JPEG_LIBRARY} CACHE STRING "JPEG libraries")
file(STRINGS "${JPEG_INCLUDE_DIR}/jconfig.h"
jpeg_lib_version REGEX "^#define[\t ]+JPEG_LIB_VERSION[\t ]+.*")
if (jpeg_lib_version)
string(REGEX REPLACE "^#define[\t ]+JPEG_LIB_VERSION[\t ]+([0-9]+).*"
"\\1" JPEG_VERSION "${jpeg_lib_version}")
endif ()
endif ()
# handle the QUIETLY and REQUIRED arguments and set JPEG_FOUND to TRUE if
@@ -37,6 +43,12 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(JPEG DEFAULT_MSG JPEG_LIBRARIES JPEG_INCLUDE_D
if (JPEG_FOUND)
set (JPEGTURBO_FOUND true)
# Use an intermediary target named "JPEG::JPEG" to match libjpeg's export
if(NOT TARGET JPEG::JPEG)
add_library(JPEG::JPEG INTERFACE IMPORTED)
target_link_libraries(JPEG::JPEG INTERFACE ${JPEG_LIBRARY})
endif()
endif ()
mark_as_advanced(JPEG_LIBRARIES JPEG_INCLUDE_DIRS )
+4
View File
@@ -86,6 +86,10 @@ MARK_AS_ADVANCED(LibRaw_VERSION_STRING
if (LINKSTATIC)
# Necessary?
find_package (Jasper)
if (JASPER_FOUND)
set (LibRaw_r_LIBRARIES ${LibRaw_r_LIBRARIES} ${JASPER_LIBRARIES})
endif()
find_library (LCMS2_LIBRARIES NAMES lcms2)
if (LCMS2_LIBRARIES)
set (LibRaw_r_LIBRARIES ${LibRaw_r_LIBRARIES} ${LCMS2_LIBRARIES})
-50
View File
@@ -1,50 +0,0 @@
# Module to find Libsquish
#
# This module will first look into the directories defined by the variables:
# - Libsquish_ROOT, LIBSQUISH_INCLUDE_PATH, LIBSQUISH_LIBRARY_PATH
#
# This module defines the following variables:
#
# Libsquish_FOUND True if Libsquish was found.
# LIBSQUISH_INCLUDES Where to find Libsquish headers
# LIBSQUISH_LIBRARIES List of libraries to link against when using Libsquish
# LIBSQUISH_VERSION Version of Libsquish (e.g., 3.6.2)
include (FindPackageHandleStandardArgs)
find_path (LIBSQUISH_INCLUDE_DIR squish.h
HINTS
${LIBSQUISH_INCLUDE_PATH}
ENV LIBSQUISH_INCLUDE_PATH
DOC "The directory where Libsquish headers reside")
find_library (LIBSQUISH_LIBRARY squish
HINTS
${LIBSQUISH_LIBRARY_PATH}
ENV LIBSQUISH_LIBRARY_PATH
DOC "The Libsquish libraries")
find_package_handle_standard_args (Libsquish
REQUIRED_VARS
LIBSQUISH_INCLUDE_DIR
LIBSQUISH_LIBRARY
)
if (Libsquish_FOUND)
set (LIBSQUISH_INCLUDES ${LIBSQUISH_INCLUDE_DIR})
set (LIBSQUISH_LIBRARIES ${LIBSQUISH_LIBRARY})
if (NOT TARGET Libsquish::Libsquish)
add_library(Libsquish::Libsquish UNKNOWN IMPORTED)
set_target_properties(Libsquish::Libsquish PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${LIBSQUISH_INCLUDES}")
set_property(TARGET Libsquish::Libsquish APPEND PROPERTY
IMPORTED_LOCATION "${LIBSQUISH_LIBRARIES}")
endif ()
endif ()
mark_as_advanced (
LIBSQUISH_INCLUDE_DIR
LIBSQUISH_LIBRARY
)
+3 -1
View File
@@ -36,8 +36,10 @@ if (EXISTS "${_ocv_version_file}")
string (REGEX MATCHALL "[0-9]+" CV_VERSION_REVISION ${TMP})
if (CV_VERSION_EPOCH)
set (OpenCV_VERSION "${CV_VERSION_EPOCH}.${CV_VERSION_MAJOR}.${CV_VERSION_MINOR}")
string(REPLACE "." "" OpenCV_VERSION_SUFFIX "${OpenCV_VERSION}")
else ()
set (OpenCV_VERSION "${CV_VERSION_MAJOR}.${CV_VERSION_MINOR}.${CV_VERSION_REVISION}")
string(REPLACE "." "" OpenCV_VERSION_SUFFIX "${OpenCV_VERSION}")
endif ()
endif ()
@@ -49,7 +51,7 @@ set (libdirs "${PROJECT_SOURCE_DIR}/lib"
/usr/local/opt/opencv3/lib
)
set (opencv_components opencv_core opencv_imgproc opencv_videoio)
set (opencv_components opencv_core opencv_imgproc opencv_videoio opencv_core${OpenCV_VERSION_SUFFIX} opencv_imgproc${OpenCV_VERSION_SUFFIX} opencv_videoio${OpenCV_VERSION_SUFFIX})
foreach (component ${opencv_components})
find_library (${component}_lib
NAMES ${component}
+61 -17
View File
@@ -1,14 +1,44 @@
# Module to find OpenColorIO
#
# This module will first look into the directories hinted by the variables:
# - OpenColorIO_ROOT, OPENCOLORIO_INCLUDE_PATH, OPENCOLORIO_LIBRARY_PATH
# - OpenColorIO_ROOT
#
# This module defines the following variables:
# This module defines the following targets:
#
# OPENCOLORIO_FOUND - True if OpenColorIO was found.
# - OpenColorIO::OpenColorIO
#
# Old style CMake, this module also defines the following variables:
#
# OpenColorIO_FOUND - True if OpenColorIO was found.
# OPENCOLORIO_INCLUDES - where to find OpenColorIO.h
# OPENCOLORIO_LIBRARIES - list of libraries to link against when using OpenColorIO
# OPENCOLORIO_DEFINITIONS - Definitions needed when using OpenColorIO
#
# Hints and overrides:
#
# - OPENCOLORIO_INTERFACE_LINK_LIBRARIES - override for interface link
# libraries on the OpenColorIO::OpenColorIO target.
# - OPENCOLORIO_NO_CONFIG - if ON, this module will be used even if an
# OCIO >= 2.1 cmake config is found. If OFF (the default), a config file
# will be preferred if found.
#
# OpenColorIO 2.1 exports proper cmake config files on its own.
# Once OCIO 2.1 is our new minimum, this FindOpenColorIO.cmake will
# eventually be deprecated and disappear.
#
if (NOT OPENCOLORIO_NO_CONFIG)
find_package(OpenColorIO CONFIG)
endif ()
if (TARGET OpenColorIO::OpenColorIO)
if (OPENCOLORIO_INTERFACE_LINK_LIBRARIES)
set_target_properties(OpenColorIO::OpenColorIO PROPERTIES
INTERFACE_LINK_LIBRARIES "${OPENCOLORIO_INTERFACE_LINK_LIBRARIES}")
endif ()
else ()
# vvvv the rest is if no OCIO exported config file is found
include (FindPackageHandleStandardArgs)
include (FindPackageMessage)
@@ -23,8 +53,23 @@ find_path (OPENCOLORIO_INCLUDE_DIR
/opt/local/include
DOC "The directory where OpenColorIO/OpenColorIO.h resides")
if (EXISTS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h")
# Search twice, because this symbol changed between OCIO 1.x and 2.x
file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" TMP
REGEX "^#define OCIO_VERSION_STR[ \t].*$")
if (NOT TMP)
file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" TMP
REGEX "^#define OCIO_VERSION[ \t].*$")
endif ()
string (REGEX MATCHALL "([0-9]+)\\.([0-9]+)\\.[0-9]+" OPENCOLORIO_VERSION ${TMP})
set (OPENCOLORIO_VERSION_MAJOR ${CMAKE_MATCH_1})
set (OPENCOLORIO_VERSION_MINOR ${CMAKE_MATCH_2})
endif ()
find_library (OPENCOLORIO_LIBRARY
NAMES OCIO OpenColorIO
NAMES
OpenColorIO
OpenColorIO_${OPENCOLORIO_VERSION_MAJOR}_${OPENCOLORIO_VERSION_MINOR}
HINTS
${OPENCOLORIO_LIBRARY_PATH}
ENV OPENCOLORIO_LIBRARY_PATH
@@ -35,24 +80,13 @@ find_library (OPENCOLORIO_LIBRARY
/opt/local/lib
DOC "The OCIO library")
if (EXISTS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h")
# Search twice, because this symbol changed between OCIO 1.x and 2.x
file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" TMP
REGEX "^#define OCIO_VERSION_STR[ \t].*$")
if (NOT TMP)
file(STRINGS "${OPENCOLORIO_INCLUDE_DIR}/OpenColorIO/OpenColorABI.h" TMP
REGEX "^#define OCIO_VERSION[ \t].*$")
endif ()
string (REGEX MATCHALL "[0-9]+[.0-9]+" OPENCOLORIO_VERSION ${TMP})
endif ()
find_package_handle_standard_args (OpenColorIO
REQUIRED_VARS OPENCOLORIO_INCLUDE_DIR OPENCOLORIO_LIBRARY
FOUND_VAR OPENCOLORIO_FOUND
FOUND_VAR OpenColorIO_FOUND
VERSION_VAR OPENCOLORIO_VERSION
)
if (OPENCOLORIO_FOUND)
if (OpenColorIO_FOUND)
set (OPENCOLORIO_INCLUDES ${OPENCOLORIO_INCLUDE_DIR})
set (OPENCOLORIO_LIBRARIES ${OPENCOLORIO_LIBRARY})
set (OPENCOLORIO_DEFINITIONS "")
@@ -63,11 +97,20 @@ if (OPENCOLORIO_FOUND)
set_property(TARGET OpenColorIO::OpenColorIO APPEND PROPERTY
IMPORTED_LOCATION "${OPENCOLORIO_LIBRARIES}")
if (OPENCOLORIO_INTERFACE_LINK_LIBRARIES)
set_target_properties(OpenColorIO::OpenColorIO PROPERTIES
INTERFACE_LINK_LIBRARIES "${OPENCOLORIO_INTERFACE_LINK_LIBRARIES}")
endif ()
if (LINKSTATIC)
target_compile_definitions(OpenColorIO::OpenColorIO
INTERFACE "-DOpenColorIO_STATIC")
endif()
endif ()
if (NOT TARGET OpenColorIO::OpenColorIOHeaders)
add_library(OpenColorIO::OpenColorIOHeaders INTERFACE IMPORTED)
set_target_properties(OpenColorIO::OpenColorIOHeaders PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPENCOLORIO_INCLUDES}")
endif ()
endif ()
if (OpenColorIO_FOUND AND LINKSTATIC)
@@ -87,3 +130,4 @@ if (OpenColorIO_FOUND AND LINKSTATIC)
endif ()
endif ()
endif()
+17 -12
View File
@@ -46,7 +46,7 @@ if (TARGET OpenEXR::OpenEXR AND TARGET Imath::Imath)
# OpenEXR 3.x if both of these targets are found
set (FOUND_OPENEXR_WITH_CONFIG 1)
if (NOT OpenEXR_FIND_QUIETLY)
message (STATUS "Found CONFIG for OpenEXR 3 (OPENEXR_VERSION=${OpenEXR_VERSION})")
message (STATUS "Found CONFIG for OpenEXR 3 (OpenEXR_VERSION=${OpenEXR_VERSION})")
endif ()
# Mimic old style variables
@@ -76,7 +76,7 @@ elseif (TARGET OpenEXR::IlmImf AND TARGET IlmBase::Imath AND
# OpenEXR 2.4 or 2.5 with exported config
set (FOUND_OPENEXR_WITH_CONFIG 1)
if (NOT OpenEXR_FIND_QUIETLY)
message (STATUS "Found CONFIG for OpenEXR 2 (OPENEXR_VERSION=${OpenEXR_VERSION})")
message (STATUS "Found CONFIG for OpenEXR 2 (OpenEXR_VERSION=${OpenEXR_VERSION})")
endif ()
# Mimic old style variables
@@ -166,21 +166,23 @@ find_path (OPENEXR_INCLUDE_PATH OpenEXR/OpenEXRConfig.h
# Try to figure out version number
if (DEFINED _OPENEXR_VERSION AND NOT "${_OPENEXR_VERSION}" STREQUAL "")
set (OPENEXR_VERSION "${_OPENEXR_VERSION}")
string (REGEX REPLACE "([0-9]+)\\.[0-9\\.]+" "\\1" OPENEXR_VERSION_MAJOR "${_OPENEXR_VERSION}")
string (REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" OPENEXR_VERSION_MINOR "${_OPENEXR_VERSION}")
set (OpenEXR_VERSION "${_OPENEXR_VERSION}")
string (REGEX REPLACE "([0-9]+)\\.[0-9\\.]+" "\\1" OpenEXR_VERSION_MAJOR "${_OPENEXR_VERSION}")
string (REGEX REPLACE "[0-9]+\\.([0-9]+)(\\.[0-9]+)?" "\\1" OpenEXR_VERSION_MINOR "${_OPENEXR_VERSION}")
elseif (EXISTS "${OPENEXR_INCLUDE_PATH}/OpenEXR/ImfMultiPartInputFile.h")
# Must be at least 2.0
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_STRING .*$")
string (REGEX MATCHALL "[0-9]+[.0-9]+" OPENEXR_VERSION ${TMP})
string (REGEX MATCHALL "[0-9]+[.0-9]+" OpenEXR_VERSION ${TMP})
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MAJOR .*$")
string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MAJOR ${TMP})
string (REGEX MATCHALL "[0-9]+" OpenEXR_VERSION_MAJOR ${TMP})
file(STRINGS "${OPENEXR_INCLUDE_PATH}/OpenEXR/OpenEXRConfig.h" TMP REGEX "^#define OPENEXR_VERSION_MINOR .*$")
string (REGEX MATCHALL "[0-9]+" OPENEXR_VERSION_MINOR ${TMP})
string (REGEX MATCHALL "[0-9]+" OpenEXR_VERSION_MINOR ${TMP})
else ()
# Assume an old one, predates 2.x that had versions
set (OPENEXR_VERSION 1.6.1)
set (OPENEXR_MAJOR 1)
set (OPENEXR_MINOR 6)
set (OpenEXR_VERSION 1.6.1)
set (OpenEXR_VERSION_MAJOR 1)
set (OpenEXR_VERSION_MINOR 6)
endif ()
@@ -222,9 +224,9 @@ foreach (COMPONENT ${_openexr_components})
string (TOUPPER ${COMPONENT} UPPERCOMPONENT)
# First try with the version embedded
find_library (OPENEXR_${UPPERCOMPONENT}_LIBRARY
NAMES ${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}
NAMES ${COMPONENT}-${OpenEXR_VERSION_MAJOR}_${OpenEXR_VERSION_MINOR}
${COMPONENT}
${COMPONENT}-${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR}_d
${COMPONENT}-${OpenEXR_VERSION_MAJOR}_${OpenEXR_VERSION_MINOR}_d
${COMPONENT}_d
HINTS ${OPENEXR_LIBRARY_DIR} $ENV{OPENEXR_LIBRARY_DIR}
${GENERIC_LIBRARY_PATHS} )
@@ -237,7 +239,10 @@ find_package_handle_standard_args (OpenEXR
)
if (OPENEXR_FOUND)
set (OpenEXR_VERSION ${OPENEXR_VERSION})
set (OPENEXR_VERSION_MAJOR ${OpenEXR_VERSION_MAJOR})
set (OPENEXR_VERSION_MINOR ${OpenEXR_VERSION_MINOR})
set (Imath_VERSION_MAJOR ${OpenEXR_VERSION_MAJOR})
set (Imath_VERSION_MINOR ${OpenEXR_VERSION_MINOR})
set (ILMBASE_FOUND TRUE)
set (ILMBASE_INCLUDES ${ILMBASE_INCLUDE_PATH})
set (IMATH_INCLUDES ${ILMBASE_INCLUDE_PATH})
-127
View File
@@ -1,127 +0,0 @@
###########################################################################
# OpenImageIO https://www.openimageio.org
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
#
# For an up-to-date version of this file, see:
# https://github.com/OpenImageIO/oiio/blob/master/src/cmake/Modules/FindOpenImageIO.cmake
#
###########################################################################
#
# CMake module to find OpenImageIO
#
# This module will set
# OpenImageIO_FOUND True, if found
# OPENIMAGEIO_INCLUDES directory where headers are found
# OPENIMAGEIO_LIBRARIES libraries for OIIO
# OPENIMAGEIO_LIBRARY_DIRS library dirs for OIIO
# OPENIMAGEIO_VERSION Version ("major.minor.patch.tweak")
# OPENIMAGEIO_VERSION_MAJOR Version major number
# OPENIMAGEIO_VERSION_MINOR Version minor number
# OPENIMAGEIO_VERSION_PATCH Version minor patch
# OPENIMAGEIO_VERSION_TWEAK Version minor tweak
# OIIOTOOL_BIN Path to oiiotool executable
#
# Imported targets:
# OpenImageIO::OpenImageIO The libOpenImageIO library.
# OpenImageIO::oiiotool The oiiotool executable.
#
# Special inputs:
# OpenImageIO_ROOT - if using CMake >= 3.12, will automatically search
# this area for OIIO components.
# OPENIMAGEIO_ROOT_DIR - custom "prefix" location of OIIO installation
# (expecting bin, lib, include subdirectories)
# This is deprecated, but will work for a while.
# OpenImageIO_FIND_QUIETLY - if set, print minimal console output
# OIIO_LIBNAME_SUFFIX - if set, optional nonstandard library suffix
#
###########################################################################
#
# NOTE: This file is deprecated.
#
# In OIIO 2.1+, we generate OpenImageIOConfig.cmake files that are now the
# preferred way for downstream projecs to find an installed OIIO. There
# should be no need to copy this FindOpenImageIO.cmake file into downstream
# projects, *unless* they need to work with a range of OIIO vesions that
# may include <2.1, which would lack the generated config files.
#
###########################################################################
# If 'OPENIMAGE_HOME' not set, use the env variable of that name if available
if (NOT OPENIMAGEIO_ROOT_DIR AND NOT $ENV{OPENIMAGEIO_ROOT_DIR} STREQUAL "")
set (OPENIMAGEIO_ROOT_DIR $ENV{OPENIMAGEIO_ROOT_DIR})
endif ()
find_library ( OPENIMAGEIO_LIBRARY
NAMES OpenImageIO${OIIO_LIBNAME_SUFFIX}
HINTS ${OPENIMAGEIO_ROOT_DIR}
PATH_SUFFIXES lib64 lib )
find_path ( OPENIMAGEIO_INCLUDE_DIR
NAMES OpenImageIO/imageio.h
HINTS ${OPENIMAGEIO_ROOT_DIR} )
find_program ( OIIOTOOL_BIN
NAMES oiiotool
HINTS ${OPENIMAGEIO_ROOT_DIR} )
# Try to figure out version number
set (OIIO_VERSION_HEADER "${OPENIMAGEIO_INCLUDE_DIR}/OpenImageIO/oiioversion.h")
if (EXISTS "${OIIO_VERSION_HEADER}")
file (STRINGS "${OIIO_VERSION_HEADER}" TMP REGEX "^#define OIIO_VERSION_MAJOR .*$")
string (REGEX MATCHALL "[0-9]+" OPENIMAGEIO_VERSION_MAJOR ${TMP})
file (STRINGS "${OIIO_VERSION_HEADER}" TMP REGEX "^#define OIIO_VERSION_MINOR .*$")
string (REGEX MATCHALL "[0-9]+" OPENIMAGEIO_VERSION_MINOR ${TMP})
file (STRINGS "${OIIO_VERSION_HEADER}" TMP REGEX "^#define OIIO_VERSION_PATCH .*$")
string (REGEX MATCHALL "[0-9]+" OPENIMAGEIO_VERSION_PATCH ${TMP})
file (STRINGS "${OIIO_VERSION_HEADER}" TMP REGEX "^#define OIIO_VERSION_TWEAK .*$")
if (TMP)
string (REGEX MATCHALL "[0-9]+" OPENIMAGEIO_VERSION_TWEAK ${TMP})
else ()
set (OPENIMAGEIO_VERSION_TWEAK 0)
endif ()
set (OPENIMAGEIO_VERSION "${OPENIMAGEIO_VERSION_MAJOR}.${OPENIMAGEIO_VERSION_MINOR}.${OPENIMAGEIO_VERSION_PATCH}.${OPENIMAGEIO_VERSION_TWEAK}")
endif ()
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (OpenImageIO
FOUND_VAR OpenImageIO_FOUND
REQUIRED_VARS OPENIMAGEIO_INCLUDE_DIR OPENIMAGEIO_LIBRARY
OPENIMAGEIO_VERSION
VERSION_VAR OPENIMAGEIO_VERSION
)
set (OPENIMAGEIO_FOUND ${OpenImageIO_FOUND}) # Old name
if (OpenImageIO_FOUND)
set (OPENIMAGEIO_INCLUDES ${OPENIMAGEIO_INCLUDE_DIR})
set (OPENIMAGEIO_LIBRARIES ${OPENIMAGEIO_LIBRARY})
get_filename_component (OPENIMAGEIO_LIBRARY_DIRS "${OPENIMAGEIO_LIBRARY}" DIRECTORY)
if (NOT OpenImageIO_FIND_QUIETLY)
message ( STATUS "OpenImageIO includes = ${OPENIMAGEIO_INCLUDE_DIR}" )
message ( STATUS "OpenImageIO libraries = ${OPENIMAGEIO_LIBRARIES}" )
message ( STATUS "OpenImageIO library_dirs = ${OPENIMAGEIO_LIBRARY_DIRS}" )
message ( STATUS "OpenImageIO oiiotool = ${OIIOTOOL_BIN}" )
endif ()
if (NOT TARGET OpenImageIO::OpenImageIO)
add_library(OpenImageIO::OpenImageIO UNKNOWN IMPORTED)
set_target_properties(OpenImageIO::OpenImageIO PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPENIMAGEIO_INCLUDES}")
set_property(TARGET OpenImageIO::OpenImageIO APPEND PROPERTY
IMPORTED_LOCATION "${OPENIMAGEIO_LIBRARIES}")
endif ()
if (NOT TARGET OpenImageIO::oiiotool AND EXISTS "${OIIOTOOL_BIN}")
add_executable(OpenImageIO::oiiotool IMPORTED)
set_target_properties(OpenImageIO::oiiotool PROPERTIES
IMPORTED_LOCATION "${OIIOTOOL_BIN}")
endif ()
endif ()
mark_as_advanced (
OPENIMAGEIO_INCLUDE_DIR
OPENIMAGEIO_LIBRARY
)
+3 -38
View File
@@ -17,7 +17,8 @@ macro (PREFIX_FIND_INCLUDE_DIR prefix includefile libpath_var)
string (TOUPPER ${prefix}_INCLUDE_DIR tmp_varname)
find_path(${tmp_varname} ${includefile}
PATHS ${${libpath_var}}
NO_DEFAULT_PATH
PATH_SUFFIXES openjpeg openjpeg-2.0 openjpeg-2.1 openjpeg-2.2
openjpeg-2.3 openjpeg-2.4 openjpeg-2.5
)
if (${tmp_varname})
mark_as_advanced (${tmp_varname})
@@ -31,12 +32,10 @@ macro (PREFIX_FIND_LIB prefix libname libpath_var liblist_var cachelist_var)
find_library(${tmp_prefix}_LIBRARY_RELEASE
NAMES ${libname}
PATHS ${${libpath_var}}
NO_DEFAULT_PATH
)
find_library(${tmp_prefix}_LIBRARY_DEBUG
NAMES ${libname}d ${libname}_d ${libname}debug ${libname}_debug
PATHS ${${libpath_var}}
NO_DEFAULT_PATH
)
# Properly define ${tmp_prefix}_LIBRARY (cached) and ${tmp_prefix}_LIBRARIES
select_library_configurations (${tmp_prefix})
@@ -56,25 +55,9 @@ endmacro ()
# Generic search paths
set (OpenJpeg_include_paths
/usr/local/include/openjpeg-2.4
/usr/local/include/openjpeg-2.3
/usr/local/include/openjpeg-2.2
/usr/local/include/openjpeg-2.1
/usr/local/include/openjpeg-2.0
/usr/local/include/openjpeg
/usr/local/include
/usr/include/openjpeg-2.4
/usr/include/openjpeg-2.3
/usr/include/openjpeg-2.2
/usr/include/openjpeg-2.1
/usr/include/openjpeg
/usr/include
/opt/local/include
/opt/local/include/openjpeg-2.4
/opt/local/include/openjpeg-2.3
/opt/local/include/openjpeg-2.2
/opt/local/include/openjpeg-2.1
/opt/local/include/openjpeg-2.0)
)
set (OpenJpeg_library_paths
/usr/lib
@@ -83,24 +66,6 @@ set (OpenJpeg_library_paths
/sw/lib
/opt/local/lib)
if (OpenJPEG_ROOT)
set (OpenJpeg_library_paths
${OpenJPEG_ROOT}/lib
${OpenJPEG_ROOT}/lib64
${OpenJPEG_ROOT}/bin
${OpenJpeg_library_paths}
)
set (OpenJpeg_include_paths
${OpenJPEG_ROOT}/include/openjpeg-2.4
${OpenJPEG_ROOT}/include/openjpeg-2.3
${OpenJPEG_ROOT}/include/openjpeg-2.2
${OpenJPEG_ROOT}/include/openjpeg-2.1
${OpenJPEG_ROOT}/include/openjpeg-2.0
${OpenJPEG_ROOT}/include/openjpeg
${OpenJPEG_ROOT}/include
${OpenJpeg_include_paths}
)
endif()
# Locate the header files
+4 -4
View File
@@ -79,11 +79,11 @@ if (OpenVDB_FOUND)
set(OPENVDB_LIBRARIES ${OPENVDB_LIBRARY})
set(OPENVDB_INCLUDES ${OPENVDB_INCLUDE_DIR})
if (NOT TARGET OpenVDB::OpenVDB)
add_library(OpenVDB::OpenVDB UNKNOWN IMPORTED)
set_target_properties(OpenVDB::OpenVDB PROPERTIES
if (NOT TARGET OpenVDB::openvdb)
add_library(OpenVDB::openvdb UNKNOWN IMPORTED)
set_target_properties(OpenVDB::openvdb PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPENVDB_INCLUDES}")
set_property(TARGET OpenVDB::OpenVDB APPEND PROPERTY
set_property(TARGET OpenVDB::openvdb APPEND PROPERTY
IMPORTED_LOCATION "${OPENVDB_LIBRARIES}")
endif ()
endif ()
+22 -4
View File
@@ -58,7 +58,7 @@
#
# * TBB_FOUND - Set to false, or undefined, if we haven’t found, or
# don’t want to use TBB.
# * TBB_<component>_FOUND - If False, optional <component> part of TBB sytem is
# * TBB_<component>_FOUND - If False, optional <component> part of TBB system is
# not available.
# * TBB_VERSION - The full version string
# * TBB_VERSION_MAJOR - The major version
@@ -74,7 +74,7 @@
# tbbmalloc, tbbmalloc_debug, tbb_preview, or
# tbb_preview_debug.
#
# The following varibles should be used to build and link with TBB:
# The following variables should be used to build and link with TBB:
#
# * TBB_INCLUDE_DIRS - The include directory for TBB.
# * TBB_LIBRARIES - The libraries to link against to use TBB.
@@ -208,7 +208,25 @@ if(NOT TBB_FOUND)
REQUIRED_VARS TBB_INCLUDE_DIRS TBB_LIBRARIES
HANDLE_COMPONENTS
VERSION_VAR TBB_VERSION)
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES)
mark_as_advanced(TBB_INCLUDE_DIRS TBB_LIBRARIES)
set(_tbb_version_file)
# Add targets
if (TBB_FOUND)
if (NOT TARGET TBB::tbb)
add_library(TBB::tbb UNKNOWN IMPORTED)
set_target_properties(TBB::tbb PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS})
set_property(TARGET TBB::tbb APPEND PROPERTY
IMPORTED_LOCATION ${TBB_tbb_LIBRARY})
endif ()
if (NOT TARGET TBB::tbbmalloc)
add_library(TBB::tbbmalloc UNKNOWN IMPORTED)
set_target_properties(TBB::tbbmalloc PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${TBB_INCLUDE_DIRS})
set_property(TARGET TBB::tbbmalloc APPEND PROPERTY
IMPORTED_LOCATION ${TBB_tbbmalloc_LIBRARY})
endif ()
endif()
endif()
+13 -8
View File
@@ -1,6 +1,6 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
# Python-related options.
option (USE_PYTHON "Build the Python bindings" ON)
@@ -50,7 +50,7 @@ macro (find_python)
set (PythonInterp_FIND_VERSION_MAJOR ${Python_VERSION_MAJOR})
if (NOT DEFINED PYTHON_SITE_DIR)
set (PYTHON_SITE_DIR "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_FOUND}/site-packages")
set (PYTHON_SITE_DIR "${CMAKE_INSTALL_LIBDIR}/python${PYTHON_VERSION_FOUND}/site-packages/OpenImageIO")
endif ()
if (VERBOSE)
message (STATUS " Python site packages dir ${PYTHON_SITE_DIR}")
@@ -64,12 +64,12 @@ endmacro()
# pybind11
macro (setup_python_module)
cmake_parse_arguments (lib "" "TARGET;MODULE;LIBS" "SOURCES" ${ARGN})
cmake_parse_arguments (lib "" "TARGET;MODULE" "SOURCES;LIBS" ${ARGN})
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
set (target_name ${lib_TARGET})
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND NOT ${CMAKE_COMPILER_ID} STREQUAL "Intel")
# Seems to be a problem on some systems, with pybind11 and python headers
set_property (SOURCE ${lib_SOURCES} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-macro-redefined ")
endif ()
@@ -81,11 +81,14 @@ macro (setup_python_module)
#
# Declare the libraries it should link against
target_link_libraries (${target_name}
PRIVATE ${lib_LIBS} ${SANITIZE_LIBRARIES})
PRIVATE ${lib_LIBS})
# if (APPLE)
# set_target_properties (${target_name} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
# endif ()
set (_module_LINK_FLAGS "${VISIBILITY_MAP_COMMAND} ${EXTRA_DSO_LINK_ARGS}")
if (UNIX AND NOT APPLE)
# Hide symbols from any static dependent libraries embedded here.
set (_module_LINK_FLAGS "${_module_LINK_FLAGS} -Wl,--exclude-libs,ALL")
endif ()
set_target_properties (${target_name} PROPERTIES LINK_FLAGS ${_module_LINK_FLAGS})
# Exclude the 'lib' prefix from the name
@@ -137,5 +140,7 @@ macro (setup_python_module)
RUNTIME DESTINATION ${PYTHON_SITE_DIR} COMPONENT user
LIBRARY DESTINATION ${PYTHON_SITE_DIR} COMPONENT user)
install(FILES __init__.py DESTINATION ${PYTHON_SITE_DIR})
endmacro ()
+205 -113
View File
@@ -16,33 +16,12 @@ add_custom_command (OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/testsuite/runtest.py"
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/testsuite/runtest.py")
add_custom_target ( CopyFiles ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/testsuite/runtest.py" )
set(OIIO_TESTSUITE_IMAGEDIR "${PROJECT_SOURCE_DIR}/.." CACHE PATH
# set(OIIO_TESTSUITE_IMAGEDIR "${PROJECT_SOURCE_DIR}/.." CACHE PATH
set(OIIO_TESTSUITE_IMAGEDIR "${PROJECT_BINARY_DIR}/testsuite" CACHE PATH
"Location of oiio-images, openexr-images, libtiffpic, etc.." )
# oiio_set_testenv() - add environment variables to a test
#
# Usage:
# oiio_set_testenv ( testname
# testsuite - The root of all tests ${CMAKE_SOURCE_DIR}/testsuite
# testsrcdir - Current test directory in ${CMAKE_SOURCE_DIR}
# testdir - Current test sandbox in ${CMAKE_BINARY_DIR}
# IMAGEDIR - Optional path to image reference/compare directory)
#
macro (oiio_set_testenv testname testsuite testsrcdir testdir IMAGEDIR)
set_property(TEST ${testname} PROPERTY ENVIRONMENT
"OIIO_TESTSUITE_ROOT=${testsuite}"
";OIIO_TESTSUITE_SRC=${testsrcdir}"
";OIIO_TESTSUITE_CUR=${testdir}")
if (NOT ${IMAGEDIR} STREQUAL "")
set_property(TEST ${testname} APPEND PROPERTY ENVIRONMENT
"OIIO_TESTSUITE_IMAGEDIR=${IMAGEDIR}")
endif()
endmacro ()
# oiio_add_tests() - add a set of test cases.
#
# Usage:
@@ -51,6 +30,8 @@ endmacro ()
# [ URL http://find.reference.cases.here.com ]
# [ FOUNDVAR variable_name ... ]
# [ ENABLEVAR variable_name ... ]
# [ SUFFIX suffix ]
# [ ENVIRONMENT "VAR=value" ... ]
# )
#
# The optional argument IMAGEDIR is used to check whether external test images
@@ -64,8 +45,13 @@ endmacro ()
# The optional ENABLEVAR introduces variables (typically ENABLE_Foo) that
# if existing and yet false, will skip the test.
#
# The optional SUFFIX is appended to the test name.
#
# The optinonal ENVIRONMENT is a list of environment variables to set for the
# test.
#
macro (oiio_add_tests)
cmake_parse_arguments (_ats "" "" "URL;IMAGEDIR;LABEL;FOUNDVAR;ENABLEVAR;TESTNAME" ${ARGN})
cmake_parse_arguments (_ats "" "SUFFIX;TESTNAME" "URL;IMAGEDIR;LABEL;FOUNDVAR;ENABLEVAR;ENVIRONMENT" ${ARGN})
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
set (_ats_testdir "${OIIO_TESTSUITE_IMAGEDIR}/${_ats_IMAGEDIR}")
# If there was a FOUNDVAR param specified and that variable name is
@@ -83,6 +69,17 @@ macro (oiio_add_tests)
set (_test_disabled 1)
endif ()
endforeach ()
if (OpenColorIO_VERSION VERSION_GREATER_EQUAL 2.2
AND NOT (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS OR "$ENV{OIIO_DISABLE_BUILTIN_OCIO_CONFIGS}"))
# For OCIO 2.2+, have the testsuite use the default built-in config
list (APPEND _ats_ENVIRONMENT "OCIO=ocio://default"
"OIIO_TESTSUITE_OCIOCONFIG=ocio://default")
else ()
# For OCIO 2.1 and earlier, have the testsuite use one we have in
# the testsuite directory.
list (APPEND _ats_ENVIRONMENT "OCIO=../common/OpenColorIO/nuke-default/config.ocio"
"OIIO_TESTSUITE_OCIOCONFIG=../common/OpenColorIO/nuke-default/config.ocio")
endif ()
if (_test_disabled)
message (STATUS "Skipping test(s) ${_ats_UNPARSED_ARGUMENTS} because of disabled ${_ats_ENABLEVAR}")
elseif (_ats_IMAGEDIR AND NOT EXISTS ${_ats_testdir})
@@ -94,13 +91,16 @@ macro (oiio_add_tests)
else ()
# Add the tests if all is well.
set (_has_generator_expr TRUE)
set (_testsuite "${CMAKE_SOURCE_DIR}/testsuite")
foreach (_testname ${_ats_UNPARSED_ARGUMENTS})
set (_testsuite "${CMAKE_SOURCE_DIR}/testsuite")
set (_testsrcdir "${_testsuite}/${_testname}")
set (_testdir "${CMAKE_BINARY_DIR}/testsuite/${_testname}")
set (_testdir "${CMAKE_BINARY_DIR}/testsuite/${_testname}${_ats_SUFFIX}")
if (_ats_TESTNAME)
set (_testname "${_ats_TESTNAME}")
endif ()
if (_ats_SUFFIX)
set (_testname "${_testname}${_ats_SUFFIX}")
endif ()
if (_ats_LABEL MATCHES "broken")
set (_testname "${_testname}-broken")
endif ()
@@ -113,32 +113,17 @@ macro (oiio_add_tests)
file (MAKE_DIRECTORY "${_testdir}")
add_test ( NAME ${_testname}
COMMAND ${_runtest} )
add_test ( NAME ${_testname} COMMAND ${_runtest} )
set_property(TEST ${_testname} APPEND PROPERTY ENVIRONMENT
"OIIO_TESTSUITE_ROOT=${_testsuite}"
"OIIO_TESTSUITE_SRC=${_testsrcdir}"
"OIIO_TESTSUITE_CUR=${_testdir}"
${_ats_ENVIRONMENT})
if (NOT ${_ats_testdir} STREQUAL "")
set_property(TEST ${_testname} APPEND PROPERTY ENVIRONMENT
"OIIO_TESTSUITE_IMAGEDIR=${_ats_testdir}")
endif()
oiio_set_testenv("${_testname}" "${_testsuite}"
"${_testsrcdir}" "${_testdir}" "${_ats_testdir}")
# For texture tests, add a second test using batch mode as well.
if (_testname MATCHES "texture")
set (_testname ${_testname}.batch)
set (_testdir ${_testdir}.batch)
set (_runtest ${Python_EXECUTABLE} "${CMAKE_SOURCE_DIR}/testsuite/runtest.py" ${_testdir})
if (MSVC_IDE)
set (_runtest ${_runtest} --devenv-config $<CONFIGURATION>
--solution-path "${CMAKE_BINARY_DIR}" )
endif ()
file (MAKE_DIRECTORY "${_testdir}")
add_test ( NAME "${_testname}"
COMMAND env TESTTEX_BATCH=1 ${_runtest} )
oiio_set_testenv("${_testname}" "${_testsuite}"
"${_testsrcdir}" "${_testdir}.batch" "${_ats_testdir}")
endif ()
#if (VERBOSE)
# message (STATUS "TEST ${_testname}: ${_runtest}")
#endif ()
endforeach ()
if (VERBOSE)
message (STATUS "TESTS: ${_ats_UNPARSED_ARGUMENTS}")
@@ -152,90 +137,114 @@ endmacro ()
# directories with plugins are included.
#
macro (oiio_add_all_tests)
# Tests that require oiio-images:
oiio_add_tests (gpsread
oiiotool oiiotool-attribs oiiotool-copy
oiiotool-xform
maketx oiiotool-maketx
misnamed-file
texture-crop texture-cropover
texture-filtersize
texture-overscan
texture-wrapfill
texture-res texture-maxres
IMAGEDIR oiio-images URL "Recent checkout of oiio-images"
)
# Remaining freestanding tests:
# Freestanding tests:
oiio_add_tests (
cmake-consumer
iinfo igrep
nonwhole-tiles
oiiotool-composite
oiiotool
oiiotool-composite oiiotool-control oiiotool-copy
oiiotool-fixnan
oiiotool-pattern
oiiotool-readerror
oiiotool-subimage oiiotool-text
oiiotool-subimage oiiotool-text oiiotool-xform
diff
dither dup-channels
jpeg-corrupt
maketx oiiotool-maketx
misnamed-file
missingcolor
null
rational
)
set (all_texture_tests
texture-derivs texture-fill
texture-flipt texture-gettexels texture-gray
texture-interp-bicubic
texture-blurtube
texture-crop texture-cropover
texture-half texture-uint16
texture-icwrite
texture-interp-bilinear
texture-interp-closest
texture-levels-stochaniso
texture-levels-stochmip
texture-mip-nomip texture-mip-onelevel
texture-mip-trilinear
texture-mip-stochastictrilinear
texture-mip-stochasticaniso
texture-missing
texture-overscan
texture-pointsample
texture-udim texture-udim2
texture-uint8
texture-width0blur
texture-wrapfill
texture-fat texture-skinny
texture-stats
texture-threadtimes
texture-env
)
oiio_add_tests (${all_texture_tests})
# Duplicate texture tests with batch mode
oiio_add_tests (${all_texture_tests}
SUFFIX ".batch"
ENVIRONMENT TESTTEX_BATCH=1)
# Tests that require oiio-images:
oiio_add_tests (gpsread
oiiotool-attribs
texture-filtersize
texture-filtersize-stochastic
texture-res texture-maxres
IMAGEDIR oiio-images URL "Recent checkout of oiio-images"
)
# Add tests that require the Python bindings if we built the Python
# bindings. This is mostly the test that are specifically about testing
# the Python bindings themselves, but also a handful of tests that are
# mainly about other things but happen to use Python in order to perform
# thee test.
# We also exclude these tests if this is a sanitizer build on Linux,
# because the Python interpreter itself won't be linked with the right asan
# Add tests that require the Python bindings.
#
# We also exclude these tests if this is a sanitizer build, because the
# Python interpreter itself won't be linked with the right asan
# libraries to run correctly.
if (USE_PYTHON AND NOT BUILD_OIIOUTIL_ONLY AND NOT SANITIZE_ON_LINUX)
if (USE_PYTHON AND NOT BUILD_OIIOUTIL_ONLY AND NOT SANITIZE)
oiio_add_tests (
python-typedesc python-paramlist
python-imagespec python-roi python-deep python-colorconfig
python-imageinput python-imageoutput
python-imagebuf python-imagebufalgo
python-texturesys
IMAGEDIR oiio-images
)
python-colorconfig
python-deep
python-imagebuf
python-imagecache
python-imageoutput
python-imagespec
python-paramlist
python-roi
python-texturesys
python-typedesc
)
# These Python tests also need access to oiio-images
oiio_add_tests (
python-imageinput python-imagebufalgo
IMAGEDIR oiio-images
)
endif ()
oiio_add_tests (oiiotool-color
FOUNDVAR OPENCOLORIO_FOUND)
if (NOT DEFINED ENV{CI} AND NOT DEFINED ENV{GITHUB_ACTIONS})
oiio_add_tests (texture-icwrite)
endif ()
FOUNDVAR OpenColorIO_FOUND)
# List testsuites for specific formats or features which might be not found
# or be intentionally disabled, or which need special external reference
# images from the web that if not found, should skip the tests:
oiio_add_tests (bmp
ENABLEVAR ENABLE_BMP
IMAGEDIR bmpsuite
URL http://entropymine.com/jason/bmpsuite/bmpsuite.zip)
IMAGEDIR oiio-images/bmpsuite)
oiio_add_tests (cineon
ENABLEVAR ENABLE_CINEON
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
oiio_add_tests (dpx
ENABLEVAR ENABLE_DPX
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
oiio_add_tests (field3d texture-field3d
FOUNDVAR Field3D_FOUND ENABLEVAR ENABLE_FIELD3D)
oiio_add_tests (dds
ENABLEVAR ENABLE_DDS
IMAGEDIR oiio-images/dds URL "Recent checkout of oiio-images")
oiio_add_tests (fits
ENABLEVAR ENABLE_FITS
IMAGEDIR fits-images
@@ -243,6 +252,10 @@ macro (oiio_add_all_tests)
oiio_add_tests (gif
FOUNDVAR GIF_FOUND ENABLEVAR ENABLE_GIF
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
oiio_add_tests (hdr
ENABLEVAR ENABLE_HDR
IMAGEDIR openexr-images
URL http://github.com/AcademySoftwareFoundation/openexr-images)
oiio_add_tests (heif
FOUNDVAR Libheif_FOUND ENABLEVAR ENABLE_Libheif
URL https://github.com/nokiatech/heif/tree/gh-pages/content)
@@ -253,53 +266,80 @@ macro (oiio_add_all_tests)
ENABLEVAR ENABLE_IFF
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
oiio_add_tests (jpeg2000
FOUNDVAR OPENJPEG_FOUND
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
oiio_add_tests (jpeg2000-j2kp4files
FOUNDVAR OPENJPEG_FOUND
IMAGEDIR j2kp4files_v1_5
URL http://www.itu.int/net/ITU-T/sigdb/speimage/ImageForm-s.aspx?val=10100803)
oiio_add_tests (openexr-suite openexr-multires openexr-chroma
openexr-v2 openexr-window perchannel
oiiotool-deep
set (all_openexr_tests
openexr-suite openexr-multires openexr-chroma
openexr-v2 openexr-window perchannel oiiotool-deep)
oiio_add_tests (${all_openexr_tests}
ENVIRONMENT OPENIMAGEIO_OPTIONS=openexr:core=0
IMAGEDIR openexr-images
URL http://www.openexr.com/downloads.html)
if (NOT DEFINED ENV{CI} AND NOT DEFINED ENV{GITHUB_ACTIONS})
oiio_add_tests (openexr-damaged
URL http://github.com/AcademySoftwareFoundation/openexr-images)
if (OpenEXR_VERSION VERSION_GREATER_EQUAL 3.1)
# For OpenEXR >= 3.1, be sure to test with the core option on
oiio_add_tests (${all_openexr_tests}
SUFFIX ".core"
ENVIRONMENT OPENIMAGEIO_OPTIONS=openexr:core=1
IMAGEDIR openexr-images
URL http://www.openexr.com/downloads.html)
URL http://github.com/AcademySoftwareFoundation/openexr-images)
endif ()
oiio_add_tests (openvdb
# if (NOT DEFINED ENV{${PROJECT_NAME}_CI})
# oiio_add_tests (openexr-damaged
# IMAGEDIR openexr-images
# URL http://github.com/AcademySoftwareFoundation/openexr-images)
# endif ()
oiio_add_tests (openvdb texture-texture3d
FOUNDVAR OpenVDB_FOUND ENABLEVAR ENABLE_OpenVDB)
oiio_add_tests (png
oiio_add_tests (openvdb texture-texture3d
SUFFIX ".batch"
ENVIRONMENT TESTTEX_BATCH=1
FOUNDVAR OpenVDB_FOUND ENABLEVAR ENABLE_OpenVDB)
oiio_add_tests (png png-damaged
ENABLEVAR ENABLE_PNG
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images)
oiio_add_tests (pnm
ENABLEVAR ENABLE_PNM
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images)
oiio_add_tests (psd psd-colormodes
ENABLEVAR ENABLE_PSD
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images)
oiio_add_tests (ptex
FOUNDVAR PTEX_FOUND ENABLEVAR ENABLE_PTEX)
oiio_add_tests (raw
FOUNDVAR LIBRAW_FOUND ENABLEVAR ENABLE_LIBRAW
IMAGEDIR oiio-images/raw
URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images/raw)
oiio_add_tests (rla
ENABLEVAR ENABLE_RLA
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images)
oiio_add_tests (sgi
ENABLEVAR ENABLE_SGI
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
oiio_add_tests (targa-tgautils
IMAGEDIR oiio-images)
oiio_add_tests (targa
ENABLEVAR ENABLE_TARGA
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images)
if (USE_PYTHON AND NOT SANITIZE)
oiio_add_tests (targa-thumbnail
ENABLEVAR ENABLE_TARGA
IMAGEDIR oiio-images)
endif()
if (NOT WIN32)
oiio_add_tests (term
ENABLEVAR ENABLE_TERM)
# I just could not get this test to work on Windows CI. The test fails
# when comparing the output, but the saved artifacts compare just fine
# on my system. Maybe someone will come back to this.
endif ()
oiio_add_tests (tiff-suite tiff-depths tiff-misc
IMAGEDIR libtiffpic
URL http://www.simplesystems.org/libtiff/images.html)
IMAGEDIR oiio-images/libtiffpic)
oiio_add_tests (webp
FOUNDVAR WebP_FOUND ENABLEVAR ENABLE_WebP
IMAGEDIR oiio-images/webp URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images/webp)
oiio_add_tests (zfile ENABLEVAR ENABLE_ZFILE
IMAGEDIR oiio-images URL "Recent checkout of oiio-images")
IMAGEDIR oiio-images)
if (SPI_TESTS)
oiio_add_tests (oiiotool-spi
@@ -309,3 +349,55 @@ macro (oiio_add_all_tests)
endif ()
endmacro()
set (OIIO_LOCAL_TESTDATA_ROOT "${CMAKE_SOURCE_DIR}/.." CACHE PATH
"Directory to check for local copies of testsuite data")
option (OIIO_DOWNLOAD_MISSING_TESTDATA "Try to download any missing test data" OFF)
function (oiio_get_test_data name)
cmake_parse_arguments (_ogtd "" "REPO;BRANCH" "" ${ARGN})
# Arguments: <prefix> <options> <one_value_keywords> <multi_value_keywords> args...
if (IS_DIRECTORY "${OIIO_LOCAL_TESTDATA_ROOT}/${name}"
AND NOT EXISTS "${CMAKE_BINARY_DIR}/testsuite/${name}")
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
# Just make a link if we can
message (STATUS "Linking ${name} from ${OIIO_LOCAL_TESTDATA_ROOT}/../${name}")
file (CREATE_LINK "${OIIO_LOCAL_TESTDATA_ROOT}/${name}"
"${CMAKE_BINARY_DIR}/testsuite/${name}"
SYMBOLIC COPY_ON_ERROR)
else ()
# Older cmake -- copy
message (STATUS "Copying ${name} from ${OIIO_LOCAL_TESTDATA_ROOT}/../${name}")
file (COPY "${OIIO_LOCAL_TESTDATA_ROOT}/${name}"
DESTINATION "${CMAKE_BINARY_DIR}/testsuite")
endif ()
elseif (IS_DIRECTORY "${CMAKE_BINARY_DIR}/testsuite/${name}")
message (STATUS "Test data for ${name} already present in testsuite")
elseif (OIIO_DOWNLOAD_MISSING_TESTDATA AND _ogtd_REPO)
# Test data directory didn't exist -- fetch it
message (STATUS "Cloning ${name} from ${_ogtd_REPO}")
if (NOT _ogtd_BRANCH)
set (_ogtd_BRANCH master)
endif ()
find_package (Git)
if (Git_FOUND AND GIT_EXECUTABLE)
execute_process(COMMAND ${GIT_EXECUTABLE} clone --depth 1
${_ogtd_REPO} -b ${_ogtd_BRANCH}
${CMAKE_BINARY_DIR}/testsuite/${name})
else ()
message (WARNING "${ColorRed}Could not find Git executable, could not download test data from ${_ogtd_REPO}${ColorReset}")
endif ()
else ()
message (STATUS "${ColorRed}Missing test data ${name}${ColorReset}")
endif ()
endfunction()
function (oiio_setup_test_data)
oiio_get_test_data (oiio-images
REPO https://github.com/OpenImageIO/oiio-images.git)
oiio_get_test_data (openexr-images
REPO https://github.com/AcademySoftwareFoundation/openexr-images.git)
oiio_get_test_data (fits-images)
oiio_get_test_data (j2kp4files_v1_5)
endfunction ()
+2 -14
View File
@@ -1,17 +1,5 @@
# Copyright 2008-present Contributors to the OpenImageIO project.
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
# https://github.com/OpenImageIO/oiio
if (Libsquish_FOUND)
# External libsquish was found -- use it
add_oiio_plugin (ddsinput.cpp
LINK_LIBRARIES Libsquish::Libsquish
)
else ()
# No external libsquish was found -- use the embedded version.
add_oiio_plugin (ddsinput.cpp squish/alpha.cpp squish/clusterfit.cpp
squish/colourblock.cpp squish/colourfit.cpp squish/colourset.cpp
squish/maths.cpp squish/rangefit.cpp squish/singlecolourfit.cpp
squish/squish.cpp
INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/squish")
endif ()
add_oiio_plugin (ddsinput.cpp)
File diff suppressed because it is too large Load Diff
+54 -20
View File
@@ -1,6 +1,6 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#pragma once
@@ -10,36 +10,60 @@ OIIO_PLUGIN_NAMESPACE_BEGIN
namespace DDS_pvt {
// IneQuation was here
#define DDS_MAKE4CC(a, b, c, d) (a | b << 8 | c << 16 | d << 24)
#define DDS_4CC_DXT1 DDS_MAKE4CC('D', 'X', 'T', '1')
#define DDS_4CC_DXT2 DDS_MAKE4CC('D', 'X', 'T', '2')
#define DDS_4CC_DXT3 DDS_MAKE4CC('D', 'X', 'T', '3')
#define DDS_4CC_DXT4 DDS_MAKE4CC('D', 'X', 'T', '4')
#define DDS_4CC_DXT5 DDS_MAKE4CC('D', 'X', 'T', '5')
#define DDS_4CC_ATI1 DDS_MAKE4CC('A', 'T', 'I', '1')
#define DDS_4CC_ATI2 DDS_MAKE4CC('A', 'T', 'I', '2')
#define DDS_4CC_DX10 DDS_MAKE4CC('D', 'X', '1', '0')
#define DDS_4CC_RXGB DDS_MAKE4CC('R', 'X', 'G', 'B')
#define DDS_4CC_BC4U DDS_MAKE4CC('B', 'C', '4', 'U')
#define DDS_4CC_BC5U DDS_MAKE4CC('B', 'C', '5', 'U')
#define DDS_FORMAT_BC4_UNORM 80
#define DDS_FORMAT_BC5_UNORM 83
#define DDS_FORMAT_BC6H_UF16 95
#define DDS_FORMAT_BC6H_SF16 96
#define DDS_FORMAT_BC7_UNORM 98
enum class Compression {
None,
DXT1, // aka BC1
DXT2,
DXT3, // aka BC2
DXT4,
DXT5, // aka BC3
BC4, // aka ATI1
BC5, // aka ATI2
BC6HU,
BC6HS,
BC7
};
/// DDS pixel format flags. Channel flags are only applicable for uncompressed
/// images.
///
enum {
DDS_PF_ALPHA = 0x00000001, ///< image has alpha channel
DDS_PF_FOURCC = 0x00000004, ///< image is compressed
DDS_PF_LUMINANCE = 0x00020000, ///< image has luminance data
DDS_PF_RGB = 0x00000040 ///< image has RGB data
DDS_PF_ALPHA = 0x00000001, ///< image has alpha channel
DDS_PF_ALPHAONLY = 0x00000002, ///< image has only the alpha channel
DDS_PF_FOURCC = 0x00000004, ///< image is compressed
DDS_PF_LUMINANCE = 0x00020000, ///< image has luminance data
DDS_PF_RGB = 0x00000040, ///< image has RGB data
DDS_PF_YUV = 0x00000200, ///< image has YUV data
DDS_PF_NORMAL = 0x80000000u, ///< image is a tangent space normal map
};
/// DDS pixel format structure.
///
typedef struct {
uint32_t size; ///< structure size, must be 32
uint32_t flags; ///< flags to indicate valid fields
uint32_t fourCC; ///< compression four-character code
uint32_t bpp; ///< bits per pixel
uint32_t rmask; ///< bitmask for the red channel
uint32_t gmask; ///< bitmask for the green channel
uint32_t bmask; ///< bitmask for the blue channel
uint32_t amask; ///< bitmask for the alpha channel
uint32_t size; ///< structure size, must be 32
uint32_t flags; ///< flags to indicate valid fields
uint32_t fourCC; ///< compression four-character code
uint32_t bpp; ///< bits per pixel
uint32_t masks[4]; ///< bitmasks for the r,g,b,a channels
} dds_pixformat;
/// DDS caps flags, field 1.
@@ -66,8 +90,10 @@ enum {
/// DDS caps structure.
///
typedef struct {
uint32_t flags1; ///< flags to indicate certain surface properties
uint32_t flags2; ///< flags to indicate certain surface properties
uint32_t flags1;
uint32_t flags2;
uint32_t flags3;
uint32_t flags4;
} dds_caps;
/// DDS global flags - indicate valid header fields.
@@ -84,8 +110,6 @@ enum {
};
/// DDS file header.
/// Please note that this layout is not identical to the one found in a file.
///
typedef struct {
uint32_t fourCC; ///< file four-character code
uint32_t size; ///< structure size, must be 124
@@ -95,11 +119,21 @@ typedef struct {
uint32_t pitch; ///< bytes per scanline (uncmp.)/total byte size (cmp.)
uint32_t depth; ///< image depth (for 3D textures)
uint32_t mipmaps; ///< number of mipmaps
// 11 reserved 4-byte fields come in here
uint32_t unused0[11];
dds_pixformat fmt; ///< pixel format
dds_caps caps; ///< DirectDraw Surface caps
uint32_t unused1;
} dds_header;
/// Optional header for images in DX10+ formats.
typedef struct {
uint32_t dxgiFormat;
uint32_t resourceDimension;
uint32_t miscFlag;
uint32_t arraySize;
uint32_t miscFlag2;
} dds_header_dx10;
} // namespace DDS_pvt
+422 -190
View File
@@ -1,74 +1,84 @@
// Copyright 2008-present Contributors to the OpenImageIO project.
// SPDX-License-Identifier: BSD-3-Clause
// https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
// https://github.com/OpenImageIO/oiio
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <stdint.h>
#include <OpenImageIO/dassert.h>
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/fmath.h>
#include <OpenImageIO/imageio.h>
#include <OpenImageIO/parallel.h>
#include <OpenImageIO/typedesc.h>
#include "dds_pvt.h"
#include "squish.h"
#define BCDEC_IMPLEMENTATION
#include "bcdec.h"
OIIO_PLUGIN_NAMESPACE_BEGIN
using namespace DDS_pvt;
constexpr int kBlockSize = 4;
// uncomment the following define to enable 3x2 cube map layout
//#define DDS_3X2_CUBE_MAP_LAYOUT
class DDSInput final : public ImageInput {
public:
DDSInput() { init(); }
virtual ~DDSInput() { close(); }
virtual const char* format_name(void) const override { return "dds"; }
virtual bool open(const std::string& name, ImageSpec& newspec) override;
virtual bool close() override;
virtual int current_subimage(void) const override
~DDSInput() override { close(); }
const char* format_name(void) const override { return "dds"; }
int supports(string_view feature) const override
{
return feature == "ioproxy";
}
bool open(const std::string& name, ImageSpec& newspec) override;
bool open(const std::string& name, ImageSpec& spec,
const ImageSpec& config) override;
bool close() override;
int current_subimage(void) const override
{
lock_guard lock(*this);
return m_subimage;
}
virtual int current_miplevel(void) const override
int current_miplevel(void) const override
{
lock_guard lock(*this);
return m_miplevel;
}
virtual bool seek_subimage(int subimage, int miplevel) override;
virtual bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
virtual bool read_native_tile(int subimage, int miplevel, int x, int y,
int z, void* data) override;
bool seek_subimage(int subimage, int miplevel) override;
bool read_native_scanline(int subimage, int miplevel, int y, int z,
void* data) override;
bool read_native_tile(int subimage, int miplevel, int x, int y, int z,
void* data) override;
private:
std::string m_filename; ///< Stash the filename
FILE* m_file; ///< Open image handle
std::vector<unsigned char> m_buf; ///< Buffer the image pixels
int m_subimage;
int m_miplevel;
int m_nchans; ///< Number of colour channels in image
int m_nfaces; ///< Number of cube map sides in image
int m_Bpp; ///< Number of bytes per pixel
int m_redL, m_redR; ///< Bit shifts to extract red channel
int m_greenL, m_greenR; ///< Bit shifts to extract green channel
int m_blueL, m_blueR; ///< Bit shifts to extract blue channel
int m_alphaL, m_alphaR; ///< Bit shifts to extract alpha channel
int m_nchans; ///< Number of colour channels in image
int m_nfaces; ///< Number of cube map sides in image
int m_Bpp; ///< Number of bytes per pixel
uint32_t m_BitCounts[4]; ///< Bit counts in r,g,b,a channels
uint32_t m_RightShifts[4]; ///< Shifts to extract r,g,b,a channels
Compression m_compression = Compression::None;
dds_header m_dds; ///< DDS header
dds_header_dx10 m_dx10;
/// Reset everything to initial state
///
void init()
{
m_file = NULL;
m_subimage = -1;
m_miplevel = -1;
m_buf.clear();
ioproxy_clear();
}
/// Helper function: read the image as scanlines (all but cubemaps).
@@ -81,7 +91,8 @@ private:
/// Helper function: calculate bit shifts to properly extract channel data
///
inline void calc_shifts(int mask, int& left, int& right);
inline static void calc_shifts(uint32_t mask, uint32_t& count,
uint32_t& right);
/// Helper function: performs the actual file seeking.
///
@@ -90,21 +101,199 @@ private:
/// Helper function: performs the actual pixel decoding.
bool internal_readimg(unsigned char* dst, int w, int h, int d);
/// Helper: read, with error detection
///
bool fread(void* buf, size_t itemsize, size_t nitems)
{
size_t n = ::fread(buf, itemsize, nitems, m_file);
if (n != nitems)
errorf("Read error");
return n == nitems;
}
};
static TypeDesc::BASETYPE
GetBaseType(Compression cmp)
{
if (cmp == Compression::BC6HU || cmp == Compression::BC6HS)
return TypeDesc::HALF;
return TypeDesc::UINT8;
}
static int
GetChannelCount(Compression cmp, bool isNormal)
{
if (isNormal)
return 3;
if (cmp == Compression::BC4)
return 1;
if (cmp == Compression::BC5)
return 2;
if (cmp == Compression::BC6HU || cmp == Compression::BC6HS)
return 3;
return 4;
}
static size_t
GetBlockSize(Compression cmp)
{
return cmp == Compression::DXT1 || cmp == Compression::BC4 ? 8 : 16;
}
static size_t
GetStorageRequirements(size_t width, size_t height, Compression cmp)
{
size_t blockCount = ((width + kBlockSize - 1) / kBlockSize)
* ((height + kBlockSize - 1) / kBlockSize);
return blockCount * GetBlockSize(cmp);
}
static uint8_t
ComputeNormalZ(uint8_t x, uint8_t y)
{
float nx = 2 * (x / 255.0f) - 1;
float ny = 2 * (y / 255.0f) - 1;
float nz = 0.0f;
float nz2 = 1 - nx * nx - ny * ny;
if (nz2 > 0) {
nz = sqrtf(nz2);
}
int z = int(255.0f * (nz + 1) / 2.0f);
if (z < 0)
z = 0;
if (z > 255)
z = 255;
return z;
}
static void
ComputeNormalRG(uint8_t rgba[kBlockSize * kBlockSize * 4])
{
// expand from RG into RGB, computing B from RG
for (int i = kBlockSize * kBlockSize - 1; i >= 0; --i) {
uint8_t x = rgba[i * 2 + 0];
uint8_t y = rgba[i * 2 + 1];
rgba[i * 3 + 0] = x;
rgba[i * 3 + 1] = y;
rgba[i * 3 + 2] = ComputeNormalZ(x, y);
}
}
static void
ComputeNormalAG(uint8_t rgba[kBlockSize * kBlockSize * 4])
{
// contract from RGBA (R & B unused) to RGB, computing B from GA
for (int i = 0; i < kBlockSize * kBlockSize; ++i) {
uint8_t x = rgba[i * 4 + 3];
uint8_t y = rgba[i * 4 + 1];
rgba[i * 3 + 0] = x;
rgba[i * 3 + 1] = y;
rgba[i * 3 + 2] = ComputeNormalZ(x, y);
}
}
// Obligatory material to make this a recognizeable imageio plugin:
static void
DecompressImage(uint8_t* rgba, int width, int height, const uint8_t* blocks,
Compression cmp, const dds_pixformat& pixelFormat, int nthreads)
{
const size_t blockSize = GetBlockSize(cmp);
const int channelCount = GetChannelCount(cmp,
pixelFormat.flags & DDS_PF_NORMAL);
const int widthInBlocks = (width + kBlockSize - 1) / kBlockSize;
const int heightInBlocks = (height + kBlockSize - 1) / kBlockSize;
paropt opt = paropt(nthreads, paropt::SplitDir::Y, 8);
parallel_for_chunked(
0, heightInBlocks, 0,
[&](int64_t ybb, int64_t ybe) {
uint8_t rgbai[kBlockSize * kBlockSize * 4];
uint16_t rgbh[kBlockSize * kBlockSize * 3];
const int ybegin = int(ybb) * kBlockSize;
const int yend = std::min(int(ybe) * kBlockSize, height);
const uint8_t* srcBlocks = blocks + ybb * widthInBlocks * blockSize;
for (int y = ybegin; y < yend; y += kBlockSize) {
for (int x = 0; x < width; x += kBlockSize) {
// decompress the BCn block
switch (cmp) {
case Compression::DXT1:
bcdec_bc1(srcBlocks, rgbai, kBlockSize * 4);
break;
case Compression::DXT2:
case Compression::DXT3:
bcdec_bc2(srcBlocks, rgbai, kBlockSize * 4);
break;
case Compression::DXT4:
case Compression::DXT5:
bcdec_bc3(srcBlocks, rgbai, kBlockSize * 4);
break;
case Compression::BC4:
bcdec_bc4(srcBlocks, rgbai, kBlockSize);
break;
case Compression::BC5:
bcdec_bc5(srcBlocks, rgbai, kBlockSize * 2);
break;
case Compression::BC6HU:
case Compression::BC6HS:
bcdec_bc6h_half(srcBlocks, rgbh, kBlockSize * 3,
cmp == Compression::BC6HS);
break;
case Compression::BC7:
bcdec_bc7(srcBlocks, rgbai, kBlockSize * 4);
break;
default: return;
}
srcBlocks += blockSize;
// Swap R & A for RXGB format case
if (cmp == Compression::DXT5
&& pixelFormat.fourCC == DDS_4CC_RXGB) {
for (int i = 0; i < 16; ++i) {
uint8_t r = rgbai[i * 4 + 0];
uint8_t a = rgbai[i * 4 + 3];
rgbai[i * 4 + 0] = a;
rgbai[i * 4 + 3] = r;
}
}
// Convert into full normal map if needed
else if (pixelFormat.flags & DDS_PF_NORMAL) {
if (cmp == Compression::BC5) {
ComputeNormalRG(rgbai);
} else if (cmp == Compression::DXT5) {
ComputeNormalAG(rgbai);
}
}
// Write the pixels into the destination image location,
// making sure to not go outside of image boundaries (BCn
// blocks always decode to 4x4 pixels, but output image
// might not be multiple of 4).
if (cmp == Compression::BC6HU
|| cmp == Compression::BC6HS) {
// HDR formats: half
const uint16_t* src = rgbh;
uint16_t* dst = (uint16_t*)rgba
+ channelCount
* (size_t(width) * y + x);
for (int py = 0; py < kBlockSize && y + py < yend;
py++) {
int cols = std::min(kBlockSize, width - x);
memcpy(dst, src, cols * channelCount * 2);
src += kBlockSize * channelCount;
dst += channelCount * width;
}
} else {
// LDR formats: uint8
const uint8_t* src = rgbai;
uint8_t* dst = rgba
+ channelCount * (size_t(width) * y + x);
for (int py = 0; py < kBlockSize && y + py < yend;
py++) {
int cols = std::min(kBlockSize, width - x);
memcpy(dst, src, cols * channelCount);
src += kBlockSize * channelCount;
dst += channelCount * width;
}
}
}
}
},
opt);
}
// Obligatory material to make this a recognizable imageio plugin:
OIIO_PLUGIN_EXPORTS_BEGIN
OIIO_EXPORT ImageInput*
@@ -127,53 +316,28 @@ OIIO_PLUGIN_EXPORTS_END
bool
DDSInput::open(const std::string& name, ImageSpec& newspec,
const ImageSpec& config)
{
ioproxy_retrieve_from_config(config);
return open(name, newspec);
}
bool
DDSInput::open(const std::string& name, ImageSpec& newspec)
{
m_filename = name;
m_file = Filesystem::fopen(name, "rb");
if (!m_file) {
errorf("Could not open file \"%s\"", name);
if (!ioproxy_use_or_open(name))
return false;
}
// due to struct packing, we may get a corrupt header if we just load the
// struct from file; to address that, read every member individually
// save some typing
#define RH(memb) \
if (!fread(&m_dds.memb, sizeof(m_dds.memb), 1)) \
return false
static_assert(sizeof(dds_header) == 128, "dds header size does not match");
if (!ioread(&m_dds, sizeof(m_dds), 1))
return false;
RH(fourCC);
RH(size);
RH(flags);
RH(height);
RH(width);
RH(pitch);
RH(depth);
RH(mipmaps);
// advance the file pointer by 44 bytes (reserved fields)
fseek(m_file, 44, SEEK_CUR);
// pixel format struct
RH(fmt.size);
RH(fmt.flags);
RH(fmt.fourCC);
RH(fmt.bpp);
RH(fmt.rmask);
RH(fmt.gmask);
RH(fmt.bmask);
RH(fmt.amask);
// caps
RH(caps.flags1);
RH(caps.flags2);
// advance the file pointer by 8 bytes (reserved fields)
fseek(m_file, 8, SEEK_CUR);
#undef RH
if (bigendian()) {
// DDS files are little-endian
// only swap values which are not flags or bitmasks
@@ -233,41 +397,90 @@ DDSInput::open(const std::string& name, ImageSpec& newspec)
|| !(m_dds.flags & DDS_HEIGHT) || !m_dds.height
|| ((m_dds.flags & DDS_DEPTH) && !m_dds.depth)
|| (!(m_dds.fmt.flags & DDS_PF_FOURCC)
&& !((m_dds.fmt.flags & DDS_PF_RGB)
| (m_dds.fmt.flags & DDS_PF_LUMINANCE)
| (m_dds.fmt.flags & DDS_PF_ALPHA)))) {
&& !(m_dds.fmt.flags
& (DDS_PF_RGB | DDS_PF_LUMINANCE | DDS_PF_ALPHA
| DDS_PF_ALPHAONLY)))) {
errorf("Image with no data");
return false;
}
// read optional DX10 header
if (m_dds.fmt.fourCC == DDS_4CC_DX10) {
if (!ioread(&m_dx10, sizeof(m_dx10), 1))
return false;
}
// validate the pixel format
// TODO: support DXGI and the "wackier" uncompressed formats
if (m_dds.fmt.flags & DDS_PF_FOURCC && m_dds.fmt.fourCC != DDS_4CC_DXT1
&& m_dds.fmt.fourCC != DDS_4CC_DXT2 && m_dds.fmt.fourCC != DDS_4CC_DXT3
&& m_dds.fmt.fourCC != DDS_4CC_DXT4
&& m_dds.fmt.fourCC != DDS_4CC_DXT5) {
errorf("Unsupported compression type");
return false;
if (m_dds.fmt.flags & DDS_PF_FOURCC) {
m_compression = Compression::None;
switch (m_dds.fmt.fourCC) {
case DDS_4CC_DXT1: m_compression = Compression::DXT1; break;
case DDS_4CC_DXT2: m_compression = Compression::DXT2; break;
case DDS_4CC_DXT3: m_compression = Compression::DXT3; break;
case DDS_4CC_DXT4: m_compression = Compression::DXT4; break;
case DDS_4CC_DXT5: m_compression = Compression::DXT5; break;
case DDS_4CC_RXGB:
m_compression = Compression::DXT5;
m_dds.fmt.flags &= ~DDS_PF_NORMAL;
break;
case DDS_4CC_ATI1: m_compression = Compression::BC4; break;
case DDS_4CC_ATI2: m_compression = Compression::BC5; break;
case DDS_4CC_BC4U: m_compression = Compression::BC4; break;
case DDS_4CC_BC5U: m_compression = Compression::BC5; break;
case DDS_4CC_DX10: {
switch (m_dx10.dxgiFormat) {
case DDS_FORMAT_BC4_UNORM: m_compression = Compression::BC4; break;
case DDS_FORMAT_BC5_UNORM: m_compression = Compression::BC5; break;
case DDS_FORMAT_BC6H_UF16:
m_compression = Compression::BC6HU;
break;
case DDS_FORMAT_BC6H_SF16:
m_compression = Compression::BC6HS;
break;
case DDS_FORMAT_BC7_UNORM: m_compression = Compression::BC7; break;
}
} break;
}
if (m_compression == Compression::None) {
errorf("Unsupported compression type");
return false;
}
}
// treat BC5 as normal maps if global attribute is set
if ((m_compression == Compression::BC5)
&& OIIO::get_int_attribute("dds:bc5normal")) {
m_dds.fmt.flags |= DDS_PF_NORMAL;
}
// determine the number of channels we have
if (m_dds.fmt.flags & DDS_PF_FOURCC) {
// squish decompresses everything to RGBA anyway
/*if (m_dds.fmt.fourCC == DDS_4CC_DXT1)
m_nchans = 3; // no alpha in DXT1
else*/
m_nchans = 4;
if (m_compression != Compression::None) {
m_nchans = GetChannelCount(m_compression,
m_dds.fmt.flags & DDS_PF_NORMAL);
} else {
m_nchans = ((m_dds.fmt.flags & DDS_PF_LUMINANCE) ? 1 : 3)
+ ((m_dds.fmt.flags & DDS_PF_ALPHA) ? 1 : 0);
// also calculate bytes per pixel and the bit shifts
m_Bpp = (m_dds.fmt.bpp + 7) >> 3;
if (!(m_dds.fmt.flags & DDS_PF_LUMINANCE)) {
calc_shifts(m_dds.fmt.rmask, m_redL, m_redR);
calc_shifts(m_dds.fmt.gmask, m_greenL, m_greenR);
calc_shifts(m_dds.fmt.bmask, m_blueL, m_blueR);
calc_shifts(m_dds.fmt.amask, m_alphaL, m_alphaR);
for (int i = 0; i < 4; ++i)
calc_shifts(m_dds.fmt.masks[i], m_BitCounts[i], m_RightShifts[i]);
m_nchans = 3;
if (m_dds.fmt.flags & DDS_PF_LUMINANCE) {
// we treat luminance as one channel;
// move next channel (possible alpha) info
// after it
m_nchans = 1;
m_dds.fmt.masks[1] = m_dds.fmt.masks[3];
m_BitCounts[1] = m_BitCounts[3];
m_RightShifts[1] = m_RightShifts[3];
} else if (m_dds.fmt.flags & DDS_PF_ALPHAONLY) {
// alpha-only image; move alpha info
// into the first slot
m_nchans = 1;
m_dds.fmt.masks[0] = m_dds.fmt.masks[3];
m_BitCounts[0] = m_BitCounts[3];
m_RightShifts[0] = m_RightShifts[3];
}
if (m_dds.fmt.flags & DDS_PF_ALPHA)
m_nchans++;
}
// fix depth, pitch and mipmaps for later use, if needed
@@ -288,7 +501,8 @@ DDSInput::open(const std::string& name, ImageSpec& newspec)
} else
m_nfaces = 1;
seek_subimage(0, 0);
if (!seek_subimage(0, 0))
return false;
newspec = spec();
return true;
}
@@ -296,25 +510,25 @@ DDSInput::open(const std::string& name, ImageSpec& newspec)
inline void
DDSInput::calc_shifts(int mask, int& left, int& right)
DDSInput::calc_shifts(uint32_t mask, uint32_t& count, uint32_t& right)
{
if (mask == 0) {
left = right = 0;
count = right = 0;
return;
}
int i, tmp = mask;
for (i = 0; i < 32; i++, tmp >>= 1) {
if (tmp & 1)
int i;
for (i = 0; i < 32; i++, mask >>= 1) {
if (mask & 1)
break;
}
right = i;
for (i = 0; i < 8; i++, tmp >>= 1) {
if (!(tmp & 1))
for (i = 0; i < 32; i++, mask >>= 1) {
if (!(mask & 1))
break;
}
left = 8 - i;
count = i;
}
@@ -334,7 +548,9 @@ DDSInput::internal_seek_subimage(int cubeface, int miplevel, unsigned int& w,
// we can easily calculate the offsets because both compressed and
// uncompressed images have predictable length
// calculate the offset; start with after the header
unsigned int ofs = 128;
unsigned int ofs = sizeof(dds_header);
if (m_dds.fmt.fourCC == DDS_4CC_DX10)
ofs += sizeof(dds_header_dx10);
unsigned int len;
// this loop is used to iterate over cube map sides, or run once in the
// case of ordinary 2D or 3D images
@@ -347,28 +563,20 @@ DDSInput::internal_seek_subimage(int cubeface, int miplevel, unsigned int& w,
// don't skip at all, so just add the offset and continue
if (m_dds.mipmaps < 2) {
if (j > 0) {
if (m_dds.fmt.flags & DDS_PF_FOURCC)
// only check for DXT1 - all other formats have same block
// size
len = squish::GetStorageRequirements(w, h,
m_dds.fmt.fourCC
== DDS_4CC_DXT1
? squish::kDxt1
: squish::kDxt5);
if (m_compression != Compression::None)
len = GetStorageRequirements(w, h, m_compression);
else
len = w * h * d * m_Bpp;
ofs += len;
}
continue;
}
for (int i = 0; i < miplevel; i++) {
if (m_dds.fmt.flags & DDS_PF_FOURCC)
// only check for DXT1 - all other formats have same block size
len = squish::GetStorageRequirements(w, h,
m_dds.fmt.fourCC
== DDS_4CC_DXT1
? squish::kDxt1
: squish::kDxt5);
// On the target cube face seek to the selected mip level. On previous faces
// seek past all levels.
int seekLevel = (j == cubeface) ? miplevel : m_dds.mipmaps;
for (int i = 0; i < seekLevel; i++) {
if (m_compression != Compression::None)
len = GetStorageRequirements(w, h, m_compression);
else
len = w * h * d * m_Bpp;
ofs += len;
@@ -384,7 +592,7 @@ DDSInput::internal_seek_subimage(int cubeface, int miplevel, unsigned int& w,
}
}
// seek to the offset we've found
fseek(m_file, ofs, SEEK_SET);
ioseek(ofs, SEEK_SET);
}
@@ -412,6 +620,7 @@ DDSInput::seek_subimage(int subimage, int miplevel)
// for cube maps, the seek will be performed when reading a tile instead
unsigned int w = 0, h = 0, d = 0;
TypeDesc::BASETYPE basetype = GetBaseType(m_compression);
if (m_dds.caps.flags2 & DDS_CAPS2_CUBEMAP) {
// calc sizes separately for cube maps
w = m_dds.width;
@@ -430,9 +639,9 @@ DDSInput::seek_subimage(int subimage, int miplevel)
}
// create imagespec for the 3x2 cube map layout
#ifdef DDS_3X2_CUBE_MAP_LAYOUT
m_spec = ImageSpec(w * 3, h * 2, m_nchans, TypeDesc::UINT8);
#else // 1x6 layout
m_spec = ImageSpec(w, h * 6, m_nchans, TypeDesc::UINT8);
m_spec = ImageSpec(w * 3, h * 2, m_nchans, basetype);
#else // 1x6 layout
m_spec = ImageSpec(w, h * 6, m_nchans, basetype);
#endif // DDS_3X2_CUBE_MAP_LAYOUT
m_spec.depth = d;
m_spec.tile_width = m_spec.full_width = w;
@@ -441,28 +650,59 @@ DDSInput::seek_subimage(int subimage, int miplevel)
} else {
internal_seek_subimage(0, miplevel, w, h, d);
// create imagespec
m_spec = ImageSpec(w, h, m_nchans, TypeDesc::UINT8);
m_spec = ImageSpec(w, h, m_nchans, basetype);
m_spec.depth = d;
}
// fill the imagespec
if (m_dds.fmt.flags & DDS_PF_FOURCC) {
std::string tempstr = "";
tempstr += ((char*)&m_dds.fmt.fourCC)[0];
tempstr += ((char*)&m_dds.fmt.fourCC)[1];
tempstr += ((char*)&m_dds.fmt.fourCC)[2];
tempstr += ((char*)&m_dds.fmt.fourCC)[3];
m_spec.attribute("compression", tempstr);
if (m_compression != Compression::None) {
const char* str = nullptr;
switch (m_compression) {
case Compression::None: break;
case Compression::DXT1: str = "DXT1"; break;
case Compression::DXT2: str = "DXT2"; break;
case Compression::DXT3: str = "DXT3"; break;
case Compression::DXT4: str = "DXT4"; break;
case Compression::DXT5: str = "DXT5"; break;
case Compression::BC4: str = "BC4"; break;
case Compression::BC5: str = "BC5"; break;
case Compression::BC6HU: str = "BC6HU"; break;
case Compression::BC6HS: str = "BC6HS"; break;
case Compression::BC7: str = "BC7"; break;
}
if (str != nullptr)
m_spec.attribute("compression", str);
}
m_spec.attribute("oiio:BitsPerSample", m_dds.fmt.bpp);
if (m_dds.fmt.bpp
&& (m_dds.fmt.flags
& (DDS_PF_RGB | DDS_PF_LUMINANCE | DDS_PF_YUV | DDS_PF_ALPHAONLY))) {
if (m_dds.fmt.bpp != 8 && m_dds.fmt.bpp != 16 && m_dds.fmt.bpp != 24
&& m_dds.fmt.bpp != 32) {
errorfmt(
"Unsupported DDS bit depth: {} (maybe it's a corrupted file?)",
m_dds.fmt.bpp);
return false;
}
m_spec.attribute("oiio:BitsPerSample", m_dds.fmt.bpp);
}
// linear color space for HDR-ish images
if (basetype == TypeDesc::HALF || basetype == TypeDesc::FLOAT)
m_spec.attribute("oiio:ColorSpace", "linear");
m_spec.default_channel_names();
// Special case: if a 2-channel DDS RG or YA?
if (m_nchans == 2 && (m_dds.fmt.flags & DDS_PF_LUMINANCE)
&& (m_dds.fmt.flags & DDS_PF_ALPHA)) {
m_spec.channelnames[0] = "Y";
m_spec.channelnames[1] = "A";
}
// detect texture type
if (m_dds.caps.flags2 & DDS_CAPS2_VOLUME) {
m_spec.attribute("texturetype", "Volume Texture");
m_spec.attribute("textureformat", "Volume Texture");
} else if (m_dds.caps.flags2 & DDS_CAPS2_CUBEMAP) {
m_spec.attribute("texturetype", "Environment");
m_spec.attribute("textureformat", "CubeFace Environment");
// check available cube map sides
std::string sides = "";
@@ -495,7 +735,6 @@ DDSInput::seek_subimage(int subimage, int miplevel)
}
m_spec.attribute("dds:CubeMapSides", sides);
} else {
m_spec.attribute("texturetype", "Plain Texture");
m_spec.attribute("textureformat", "Plain Texture");
}
@@ -504,35 +743,24 @@ DDSInput::seek_subimage(int subimage, int miplevel)
return true;
}
bool
DDSInput::internal_readimg(unsigned char* dst, int w, int h, int d)
{
if (m_dds.fmt.flags & DDS_PF_FOURCC) {
if (m_compression != Compression::None) {
// compressed image
int flags = 0;
switch (m_dds.fmt.fourCC) {
case DDS_4CC_DXT1: flags = squish::kDxt1; break;
// DXT2 and 3 are the same, only 2 has pre-multiplied alpha
case DDS_4CC_DXT2:
case DDS_4CC_DXT3: flags = squish::kDxt3; break;
// DXT4 and 5 are the same, only 4 has pre-multiplied alpha
case DDS_4CC_DXT4:
case DDS_4CC_DXT5: flags = squish::kDxt5; break;
}
// create source buffer
std::vector<squish::u8> tmp(
squish::GetStorageRequirements(w, h, flags));
size_t bufsize = GetStorageRequirements(w, h, m_compression);
std::unique_ptr<uint8_t[]> tmp(new uint8_t[bufsize]);
// load image into buffer
if (!fread(&tmp[0], tmp.size(), 1))
if (!ioread(tmp.get(), bufsize, 1))
return false;
// decompress image
squish::DecompressImage(dst, w, h, &tmp[0], flags);
tmp.clear();
DecompressImage(dst, w, h, tmp.get(), m_compression, m_dds.fmt,
threads());
tmp.reset();
// correct pre-multiplied alpha, if necessary
if (m_dds.fmt.fourCC == DDS_4CC_DXT2
|| m_dds.fmt.fourCC == DDS_4CC_DXT4) {
if (m_compression == Compression::DXT2
|| m_compression == Compression::DXT4) {
int k;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
@@ -547,29 +775,39 @@ DDSInput::internal_readimg(unsigned char* dst, int w, int h, int d)
}
}
} else {
// uncompressed image
// HACK: shortcut for luminance
if (m_dds.fmt.flags & DDS_PF_LUMINANCE) {
return fread(dst, w * m_Bpp, h);
// uncompressed image:
// check if we can just directly copy pixels without any processing
bool direct = false;
if (m_spec.nchannels == m_Bpp) {
direct = true;
for (int ch = 0; ch < m_spec.nchannels; ++ch) {
if ((m_dds.fmt.masks[ch] != (0xFFu << (ch * 8)))
|| (m_RightShifts[ch] != uint32_t(ch * 8))
|| (m_BitCounts[ch] != 8u)) {
direct = false;
break;
}
}
}
if (direct) {
return ioread(dst, w * m_Bpp, h);
}
int k, pixel = 0;
std::unique_ptr<uint8_t[]> tmp(new uint8_t[w * m_Bpp]);
for (int z = 0; z < d; z++) {
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
if (!fread(&pixel, 1, m_Bpp))
return false;
k = (z * h * w + y * w + x) * m_spec.nchannels;
dst[k + 0] = ((pixel & m_dds.fmt.rmask) >> m_redR)
<< m_redL;
dst[k + 1] = ((pixel & m_dds.fmt.gmask) >> m_greenR)
<< m_greenL;
dst[k + 2] = ((pixel & m_dds.fmt.bmask) >> m_blueR)
<< m_blueL;
if (m_dds.fmt.flags & DDS_PF_ALPHA)
dst[k + 3] = ((pixel & m_dds.fmt.amask) >> m_alphaR)
<< m_alphaL;
if (!ioread(tmp.get(), w, m_Bpp))
return false;
size_t k = (z * h * w + y * w) * m_spec.nchannels;
for (int x = 0; x < w; x++, k += m_spec.nchannels) {
uint32_t pixel = 0;
memcpy(&pixel, tmp.get() + x * m_Bpp, m_Bpp);
for (int ch = 0; ch < m_spec.nchannels; ++ch) {
dst[k + ch]
= bit_range_convert((pixel & m_dds.fmt.masks[ch])
>> m_RightShifts[ch],
m_BitCounts[ch], 8);
}
}
}
}
@@ -582,7 +820,7 @@ DDSInput::internal_readimg(unsigned char* dst, int w, int h, int d)
bool
DDSInput::readimg_scanlines()
{
//std::cerr << "[dds] readimg: " << ftell (m_file) << "\n";
//std::cerr << "[dds] readimg: " << ftell() << "\n";
// resize destination buffer
m_buf.resize(m_spec.scanline_bytes() * m_spec.height * m_spec.depth
/*/ (1 << m_miplevel)*/);
@@ -597,8 +835,7 @@ bool
DDSInput::readimg_tiles()
{
// resize destination buffer
m_buf.resize(m_spec.tile_bytes());
OIIO_ASSERT(m_buf.size() >= m_spec.tile_bytes());
return internal_readimg(&m_buf[0], m_spec.tile_width, m_spec.tile_height,
m_spec.tile_depth);
}
@@ -608,11 +845,6 @@ DDSInput::readimg_tiles()
bool
DDSInput::close()
{
if (m_file) {
fclose(m_file);
m_file = NULL;
}
init(); // Reset to initial state
return true;
}
@@ -667,11 +899,11 @@ DDSInput::read_native_tile(int subimage, int miplevel, int x, int y, int z,
internal_seek_subimage(((x / m_spec.tile_width) << 1)
+ y / m_spec.tile_height,
m_miplevel, w, h, d);
#else // 1x6 layout
#else // 1x6 layout
internal_seek_subimage(y / m_spec.tile_height, m_miplevel, w, h, d);
#endif // DDS_3X2_CUBE_MAP_LAYOUT
if (!w && !h && !d)
// face not present in file, black-pad the image
#endif // DDS_3X2_CUBE_MAP_LAYOUT
m_buf.resize(m_spec.tile_bytes()); // resize destination buffer
if (!w && !h && !d) // face not present in file, black-pad the image
memset(&m_buf[0], 0, m_spec.tile_bytes());
else
readimg_tiles();
-52
View File
@@ -1,52 +0,0 @@
1.10
* Iterative cluster fit is now considered to be a new compression mode
* The core cluster fit is now 4x faster using contributions by Ignacio
Castano from NVIDIA
* The single colour lookup table has been halved by exploiting symmetry
1.9
* Added contributed SSE1 truncate implementation
* Changed use of SQUISH_USE_SSE to be 1 for SSE and 2 for SSE2 instructions
* Cluster fit is now iterative to further reduce image error
1.8
* Switched from using floor to trunc for much better SSE performance (again)
* Xcode build now expects libpng in /usr/local for extra/squishpng
1.7
* Fixed floating-point equality issue in clusterfit sort (x86 affected only)
* Implemented proper SSE(2) floor function for 50% speedup on SSE builds
* The range fit implementation now uses the correct colour metric
1.6
* Fixed bug in CompressImage where masked pixels were not skipped over
* DXT3 and DXT5 alpha compression now properly use the mask to ignore pixels
* Fixed major DXT1 bug that can generate unexpected transparent pixels
1.5
* Added CompressMasked function to handle incomplete DXT blocks more cleanly
* Added kWeightColourByAlpha flag for better quality images when alpha blending
1.4
* Fixed stack overflow in rangefit
1.3
* Worked around SSE floor implementation bug, proper fix needed!
* This release has visual studio and makefile builds that work
1.2
* Added provably optimal single colour compressor
* Added extra/squishgen.cpp that generates single colour lookup tables
1.1
* Fixed a DXT1 colour output bug
* Changed argument order for Decompress function to match Compress
* Added GetStorageRequirements function
* Added CompressImage function
* Added DecompressImage function
* Moved squishtool.cpp to extra/squishpng.cpp
* Added extra/squishtest.cpp
1.0
* Initial release
-35
View File
@@ -1,35 +0,0 @@
LICENSE
-------
The squish library is distributed under the terms and conditions of the MIT
license. This license is specified at the top of each source file and must be
preserved in its entirety.
BUILDING AND INSTALLING THE LIBRARY
-----------------------------------
If you are using Visual Studio 2003 or above under Windows then load the Visual
Studio 2003 project in the vs7 folder. By default, the library is built using
SSE2 optimisations. To change this either change or remove the SQUISH_USE_SSE=2
from the preprocessor symbols.
If you are using a Mac then load the Xcode 2.2 project in the distribution. By
default, the library is built using Altivec optimisations. To change this
either change or remove SQUISH_USE_ALTIVEC=1 from the preprocessor symbols. I
guess I'll have to think about changing this for the new Intel Macs that are
rolling out...
If you are using unix then first edit the config file in the base directory of
the distribution, enabling Altivec or SSE with the USE_ALTIVEC or USE_SSE
variables, and editing the optimisation flags passed to the C++ compiler if
necessary. Then make can be used to build the library, and make install (from
the superuser account) can be used to install (into /usr/local by default).
REPORTING BUGS OR FEATURE REQUESTS
----------------------------------
Feedback can be sent to Simon Brown (the developer) at si@sjbrown.co.uk
New releases are announced on the squish library homepage at
http://sjbrown.co.uk/?code=squish
-349
View File
@@ -1,349 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#include "alpha.h"
#include <climits>
#include <algorithm>
namespace squish {
static int FloatToInt( float a, int limit )
{
// use ANSI round-to-zero behaviour to get round-to-nearest
int i = ( int )( a + 0.5f );
// clamp to the limit
if( i < 0 )
i = 0;
else if( i > limit )
i = limit;
// done
return i;
}
void CompressAlphaDxt3( u8 const* rgba, int mask, void* block )
{
u8* bytes = reinterpret_cast< u8* >( block );
// quantise and pack the alpha values pairwise
for( int i = 0; i < 8; ++i )
{
// quantise down to 4 bits
float alpha1 = ( float )rgba[8*i + 3] * ( 15.0f/255.0f );
float alpha2 = ( float )rgba[8*i + 7] * ( 15.0f/255.0f );
int quant1 = FloatToInt( alpha1, 15 );
int quant2 = FloatToInt( alpha2, 15 );
// set alpha to zero where masked
int bit1 = 1 << ( 2*i );
int bit2 = 1 << ( 2*i + 1 );
if( ( mask & bit1 ) == 0 )
quant1 = 0;
if( ( mask & bit2 ) == 0 )
quant2 = 0;
// pack into the byte
bytes[i] = ( u8 )( quant1 | ( quant2 << 4 ) );
}
}
void DecompressAlphaDxt3( u8* rgba, void const* block )
{
u8 const* bytes = reinterpret_cast< u8 const* >( block );
// unpack the alpha values pairwise
for( int i = 0; i < 8; ++i )
{
// quantise down to 4 bits
u8 quant = bytes[i];
// unpack the values
u8 lo = quant & 0x0f;
u8 hi = quant & 0xf0;
// convert back up to bytes
rgba[8*i + 3] = lo | ( lo << 4 );
rgba[8*i + 7] = hi | ( hi >> 4 );
}
}
static void FixRange( int& min, int& max, int steps )
{
if( max - min < steps )
max = std::min( min + steps, 255 );
if( max - min < steps )
min = std::max( 0, max - steps );
}
static int FitCodes( u8 const* rgba, int mask, u8 const* codes, u8* indices )
{
// fit each alpha value to the codebook
int err = 0;
for( int i = 0; i < 16; ++i )
{
// check this pixel is valid
int bit = 1 << i;
if( ( mask & bit ) == 0 )
{
// use the first code
indices[i] = 0;
continue;
}
// find the least error and corresponding index
int value = rgba[4*i + 3];
int least = INT_MAX;
int index = 0;
for( int j = 0; j < 8; ++j )
{
// get the squared error from this code
int dist = ( int )value - ( int )codes[j];
dist *= dist;
// compare with the best so far
if( dist < least )
{
least = dist;
index = j;
}
}
// save this index and accumulate the error
indices[i] = ( u8 )index;
err += least;
}
// return the total error
return err;
}
static void WriteAlphaBlock( int alpha0, int alpha1, u8 const* indices, void* block )
{
u8* bytes = reinterpret_cast< u8* >( block );
// write the first two bytes
bytes[0] = ( u8 )alpha0;
bytes[1] = ( u8 )alpha1;
// pack the indices with 3 bits each
u8* dest = bytes + 2;
u8 const* src = indices;
for( int i = 0; i < 2; ++i )
{
// pack 8 3-bit values
int value = 0;
for( int j = 0; j < 8; ++j )
{
int index = *src++;
value |= ( index << 3*j );
}
// store in 3 bytes
for( int j = 0; j < 3; ++j )
{
int byte = ( value >> 8*j ) & 0xff;
*dest++ = ( u8 )byte;
}
}
}
static void WriteAlphaBlock5( int alpha0, int alpha1, u8 const* indices, void* block )
{
// check the relative values of the endpoints
if( alpha0 > alpha1 )
{
// swap the indices
u8 swapped[16];
for( int i = 0; i < 16; ++i )
{
u8 index = indices[i];
if( index == 0 )
swapped[i] = 1;
else if( index == 1 )
swapped[i] = 0;
else if( index <= 5 )
swapped[i] = 7 - index;
else
swapped[i] = index;
}
// write the block
WriteAlphaBlock( alpha1, alpha0, swapped, block );
}
else
{
// write the block
WriteAlphaBlock( alpha0, alpha1, indices, block );
}
}
static void WriteAlphaBlock7( int alpha0, int alpha1, u8 const* indices, void* block )
{
// check the relative values of the endpoints
if( alpha0 < alpha1 )
{
// swap the indices
u8 swapped[16];
for( int i = 0; i < 16; ++i )
{
u8 index = indices[i];
if( index == 0 )
swapped[i] = 1;
else if( index == 1 )
swapped[i] = 0;
else
swapped[i] = 9 - index;
}
// write the block
WriteAlphaBlock( alpha1, alpha0, swapped, block );
}
else
{
// write the block
WriteAlphaBlock( alpha0, alpha1, indices, block );
}
}
void CompressAlphaDxt5( u8 const* rgba, int mask, void* block )
{
// get the range for 5-alpha and 7-alpha interpolation
int min5 = 255;
int max5 = 0;
int min7 = 255;
int max7 = 0;
for( int i = 0; i < 16; ++i )
{
// check this pixel is valid
int bit = 1 << i;
if( ( mask & bit ) == 0 )
continue;
// incorporate into the min/max
int value = rgba[4*i + 3];
if( value < min7 )
min7 = value;
if( value > max7 )
max7 = value;
if( value != 0 && value < min5 )
min5 = value;
if( value != 255 && value > max5 )
max5 = value;
}
// handle the case that no valid range was found
if( min5 > max5 )
min5 = max5;
if( min7 > max7 )
min7 = max7;
// fix the range to be the minimum in each case
FixRange( min5, max5, 5 );
FixRange( min7, max7, 7 );
// set up the 5-alpha code book
u8 codes5[8];
codes5[0] = ( u8 )min5;
codes5[1] = ( u8 )max5;
for( int i = 1; i < 5; ++i )
codes5[1 + i] = ( u8 )( ( ( 5 - i )*min5 + i*max5 )/5 );
codes5[6] = 0;
codes5[7] = 255;
// set up the 7-alpha code book
u8 codes7[8];
codes7[0] = ( u8 )min7;
codes7[1] = ( u8 )max7;
for( int i = 1; i < 7; ++i )
codes7[1 + i] = ( u8 )( ( ( 7 - i )*min7 + i*max7 )/7 );
// fit the data to both code books
u8 indices5[16];
u8 indices7[16];
int err5 = FitCodes( rgba, mask, codes5, indices5 );
int err7 = FitCodes( rgba, mask, codes7, indices7 );
// save the block with least error
if( err5 <= err7 )
WriteAlphaBlock5( min5, max5, indices5, block );
else
WriteAlphaBlock7( min7, max7, indices7, block );
}
void DecompressAlphaDxt5( u8* rgba, void const* block )
{
// get the two alpha values
u8 const* bytes = reinterpret_cast< u8 const* >( block );
int alpha0 = bytes[0];
int alpha1 = bytes[1];
// compare the values to build the codebook
u8 codes[8];
codes[0] = ( u8 )alpha0;
codes[1] = ( u8 )alpha1;
if( alpha0 <= alpha1 )
{
// use 5-alpha codebook
for( int i = 1; i < 5; ++i )
codes[1 + i] = ( u8 )( ( ( 5 - i )*alpha0 + i*alpha1 )/5 );
codes[6] = 0;
codes[7] = 255;
}
else
{
// use 7-alpha codebook
for( int i = 1; i < 7; ++i )
codes[1 + i] = ( u8 )( ( ( 7 - i )*alpha0 + i*alpha1 )/7 );
}
// decode the indices
u8 indices[16];
u8 const* src = bytes + 2;
u8* dest = indices;
for( int i = 0; i < 2; ++i )
{
// grab 3 bytes
int value = 0;
for( int j = 0; j < 3; ++j )
{
int byte = *src++;
value |= ( byte << 8*j );
}
// unpack 8 3-bit values from it
for( int j = 0; j < 8; ++j )
{
int index = ( value >> 3*j ) & 0x7;
*dest++ = ( u8 )index;
}
}
// write out the indexed codebook values
for( int i = 0; i < 16; ++i )
rgba[4*i + 3] = codes[indices[i]];
}
} // namespace squish
-41
View File
@@ -1,41 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#ifndef SQUISH_ALPHA_H
#define SQUISH_ALPHA_H
#include "squish.h"
namespace squish {
void CompressAlphaDxt3( u8 const* rgba, int mask, void* block );
void CompressAlphaDxt5( u8 const* rgba, int mask, void* block );
void DecompressAlphaDxt3( u8* rgba, void const* block );
void DecompressAlphaDxt5( u8* rgba, void const* block );
} // namespace squish
#endif // ndef SQUISH_ALPHA_H
-392
View File
@@ -1,392 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Copyright (c) 2007 Ignacio Castano icastano@nvidia.com
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#include "clusterfit.h"
#include "colourset.h"
#include "colourblock.h"
#include <cfloat>
namespace squish {
ClusterFit::ClusterFit( ColourSet const* colours, int flags, float* metric )
: ColourFit( colours, flags )
{
// set the iteration count
m_iterationCount = ( m_flags & kColourIterativeClusterFit ) ? kMaxIterations : 1;
// initialise the metric (old perceptual = 0.2126f, 0.7152f, 0.0722f)
if( metric )
m_metric = Vec4( metric[0], metric[1], metric[2], 1.0f );
else
m_metric = VEC4_CONST( 1.0f );
// initialise the best error
m_besterror = VEC4_CONST( FLT_MAX );
// cache some values
int const count = m_colours->GetCount();
Vec3 const* values = m_colours->GetPoints();
// get the covariance matrix
Sym3x3 covariance = ComputeWeightedCovariance( count, values, m_colours->GetWeights() );
// compute the principle component
m_principle = ComputePrincipleComponent( covariance );
}
bool ClusterFit::ConstructOrdering( Vec3 const& axis, int iteration )
{
// cache some values
int const count = m_colours->GetCount();
Vec3 const* values = m_colours->GetPoints();
// build the list of dot products
float dps[16];
u8* order = ( u8* )m_order + 16*iteration;
for( int i = 0; i < count; ++i )
{
dps[i] = Dot( values[i], axis );
order[i] = ( u8 )i;
}
// stable sort using them
for( int i = 0; i < count; ++i )
{
for( int j = i; j > 0 && dps[j] < dps[j - 1]; --j )
{
std::swap( dps[j], dps[j - 1] );
std::swap( order[j], order[j - 1] );
}
}
// check this ordering is unique
for( int it = 0; it < iteration; ++it )
{
u8 const* prev = ( u8* )m_order + 16*it;
bool same = true;
for( int i = 0; i < count; ++i )
{
if( order[i] != prev[i] )
{
same = false;
break;
}
}
if( same )
return false;
}
// copy the ordering and weight all the points
Vec3 const* unweighted = m_colours->GetPoints();
float const* weights = m_colours->GetWeights();
m_xsum_wsum = VEC4_CONST( 0.0f );
for( int i = 0; i < count; ++i )
{
int j = order[i];
Vec4 p( unweighted[j].X(), unweighted[j].Y(), unweighted[j].Z(), 1.0f );
Vec4 w( weights[j] );
Vec4 x = p*w;
m_points_weights[i] = x;
m_xsum_wsum += x;
}
return true;
}
void ClusterFit::Compress3( void* block )
{
// declare variables
int const count = m_colours->GetCount();
Vec4 const two = VEC4_CONST( 2.0 );
Vec4 const one = VEC4_CONST( 1.0f );
Vec4 const half_half2( 0.5f, 0.5f, 0.5f, 0.25f );
Vec4 const zero = VEC4_CONST( 0.0f );
Vec4 const half = VEC4_CONST( 0.5f );
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f );
// prepare an ordering using the principle axis
ConstructOrdering( m_principle, 0 );
// check all possible clusters and iterate on the total order
Vec4 beststart = VEC4_CONST( 0.0f );
Vec4 bestend = VEC4_CONST( 0.0f );
Vec4 besterror = m_besterror;
u8 bestindices[16];
int bestiteration = 0;
int besti = 0, bestj = 0;
// loop over iterations (we avoid the case that all points in first or last cluster)
for( int iterationIndex = 0;; )
{
// first cluster [0,i) is at the start
Vec4 part0 = VEC4_CONST( 0.0f );
for( int i = 0; i < count; ++i )
{
// second cluster [i,j) is half along
Vec4 part1 = ( i == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f );
int jmin = ( i == 0 ) ? 1 : i;
for( int j = jmin;; )
{
// last cluster [j,count) is at the end
Vec4 part2 = m_xsum_wsum - part1 - part0;
// compute least squares terms directly
Vec4 alphax_sum = MultiplyAdd( part1, half_half2, part0 );
Vec4 alpha2_sum = alphax_sum.SplatW();
Vec4 betax_sum = MultiplyAdd( part1, half_half2, part2 );
Vec4 beta2_sum = betax_sum.SplatW();
Vec4 alphabeta_sum = ( part1*half_half2 ).SplatW();
// compute the least-squares optimal points
Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) );
Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor;
Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor;
// clamp to the grid
a = Min( one, Max( zero, a ) );
b = Min( one, Max( zero, b ) );
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
// compute the error (we skip the constant xxsum)
Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum );
Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 );
Vec4 e4 = MultiplyAdd( two, e3, e1 );
// apply the metric to the error term
Vec4 e5 = e4*m_metric;
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
// keep the solution if it wins
if( CompareAnyLessThan( error, besterror ) )
{
beststart = a;
bestend = b;
besti = i;
bestj = j;
besterror = error;
bestiteration = iterationIndex;
}
// advance
if( j == count )
break;
part1 += m_points_weights[j];
++j;
}
// advance
part0 += m_points_weights[i];
}
// stop if we didn't improve in this iteration
if( bestiteration != iterationIndex )
break;
// advance if possible
++iterationIndex;
if( iterationIndex == m_iterationCount )
break;
// stop if a new iteration is an ordering that has already been tried
Vec3 axis = ( bestend - beststart ).GetVec3();
if( !ConstructOrdering( axis, iterationIndex ) )
break;
}
// save the block if necessary
if( CompareAnyLessThan( besterror, m_besterror ) )
{
// remap the indices
u8 const* order = ( u8* )m_order + 16*bestiteration;
u8 unordered[16];
for( int m = 0; m < besti; ++m )
unordered[order[m]] = 0;
for( int m = besti; m < bestj; ++m )
unordered[order[m]] = 2;
for( int m = bestj; m < count; ++m )
unordered[order[m]] = 1;
m_colours->RemapIndices( unordered, bestindices );
// save the block
WriteColourBlock3( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
// save the error
m_besterror = besterror;
}
}
void ClusterFit::Compress4( void* block )
{
// declare variables
int const count = m_colours->GetCount();
Vec4 const two = VEC4_CONST( 2.0f );
Vec4 const one = VEC4_CONST( 1.0f );
Vec4 const onethird_onethird2( 1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f, 1.0f/9.0f );
Vec4 const twothirds_twothirds2( 2.0f/3.0f, 2.0f/3.0f, 2.0f/3.0f, 4.0f/9.0f );
Vec4 const twonineths = VEC4_CONST( 2.0f/9.0f );
Vec4 const zero = VEC4_CONST( 0.0f );
Vec4 const half = VEC4_CONST( 0.5f );
Vec4 const grid( 31.0f, 63.0f, 31.0f, 0.0f );
Vec4 const gridrcp( 1.0f/31.0f, 1.0f/63.0f, 1.0f/31.0f, 0.0f );
// prepare an ordering using the principle axis
ConstructOrdering( m_principle, 0 );
// check all possible clusters and iterate on the total order
Vec4 beststart = VEC4_CONST( 0.0f );
Vec4 bestend = VEC4_CONST( 0.0f );
Vec4 besterror = m_besterror;
u8 bestindices[16];
int bestiteration = 0;
int besti = 0, bestj = 0, bestk = 0;
// loop over iterations (we avoid the case that all points in first or last cluster)
for( int iterationIndex = 0;; )
{
// first cluster [0,i) is at the start
Vec4 part0 = VEC4_CONST( 0.0f );
for( int i = 0; i < count; ++i )
{
// second cluster [i,j) is one third along
Vec4 part1 = VEC4_CONST( 0.0f );
for( int j = i;; )
{
// third cluster [j,k) is two thirds along
Vec4 part2 = ( j == 0 ) ? m_points_weights[0] : VEC4_CONST( 0.0f );
int kmin = ( j == 0 ) ? 1 : j;
for( int k = kmin;; )
{
// last cluster [k,count) is at the end
Vec4 part3 = m_xsum_wsum - part2 - part1 - part0;
// compute least squares terms directly
Vec4 const alphax_sum = MultiplyAdd( part2, onethird_onethird2, MultiplyAdd( part1, twothirds_twothirds2, part0 ) );
Vec4 const alpha2_sum = alphax_sum.SplatW();
Vec4 const betax_sum = MultiplyAdd( part1, onethird_onethird2, MultiplyAdd( part2, twothirds_twothirds2, part3 ) );
Vec4 const beta2_sum = betax_sum.SplatW();
Vec4 const alphabeta_sum = twonineths*( part1 + part2 ).SplatW();
// compute the least-squares optimal points
Vec4 factor = Reciprocal( NegativeMultiplySubtract( alphabeta_sum, alphabeta_sum, alpha2_sum*beta2_sum ) );
Vec4 a = NegativeMultiplySubtract( betax_sum, alphabeta_sum, alphax_sum*beta2_sum )*factor;
Vec4 b = NegativeMultiplySubtract( alphax_sum, alphabeta_sum, betax_sum*alpha2_sum )*factor;
// clamp to the grid
a = Min( one, Max( zero, a ) );
b = Min( one, Max( zero, b ) );
a = Truncate( MultiplyAdd( grid, a, half ) )*gridrcp;
b = Truncate( MultiplyAdd( grid, b, half ) )*gridrcp;
// compute the error (we skip the constant xxsum)
Vec4 e1 = MultiplyAdd( a*a, alpha2_sum, b*b*beta2_sum );
Vec4 e2 = NegativeMultiplySubtract( a, alphax_sum, a*b*alphabeta_sum );
Vec4 e3 = NegativeMultiplySubtract( b, betax_sum, e2 );
Vec4 e4 = MultiplyAdd( two, e3, e1 );
// apply the metric to the error term
Vec4 e5 = e4*m_metric;
Vec4 error = e5.SplatX() + e5.SplatY() + e5.SplatZ();
// keep the solution if it wins
if( CompareAnyLessThan( error, besterror ) )
{
beststart = a;
bestend = b;
besterror = error;
besti = i;
bestj = j;
bestk = k;
bestiteration = iterationIndex;
}
// advance
if( k == count )
break;
part2 += m_points_weights[k];
++k;
}
// advance
if( j == count )
break;
part1 += m_points_weights[j];
++j;
}
// advance
part0 += m_points_weights[i];
}
// stop if we didn't improve in this iteration
if( bestiteration != iterationIndex )
break;
// advance if possible
++iterationIndex;
if( iterationIndex == m_iterationCount )
break;
// stop if a new iteration is an ordering that has already been tried
Vec3 axis = ( bestend - beststart ).GetVec3();
if( !ConstructOrdering( axis, iterationIndex ) )
break;
}
// save the block if necessary
if( CompareAnyLessThan( besterror, m_besterror ) )
{
// remap the indices
u8 const* order = ( u8* )m_order + 16*bestiteration;
u8 unordered[16];
for( int m = 0; m < besti; ++m )
unordered[order[m]] = 0;
for( int m = besti; m < bestj; ++m )
unordered[order[m]] = 2;
for( int m = bestj; m < bestk; ++m )
unordered[order[m]] = 3;
for( int m = bestk; m < count; ++m )
unordered[order[m]] = 1;
m_colours->RemapIndices( unordered, bestindices );
// save the block
WriteColourBlock4( beststart.GetVec3(), bestend.GetVec3(), bestindices, block );
// save the error
m_besterror = besterror;
}
}
} // namespace squish
-61
View File
@@ -1,61 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Copyright (c) 2007 Ignacio Castano icastano@nvidia.com
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#ifndef SQUISH_CLUSTERFIT_H
#define SQUISH_CLUSTERFIT_H
#include "squish.h"
#include "maths.h"
#include "simd.h"
#include "colourfit.h"
namespace squish {
class ClusterFit : public ColourFit
{
public:
ClusterFit( ColourSet const* colours, int flags, float* metric );
private:
bool ConstructOrdering( Vec3 const& axis, int iteration );
virtual void Compress3( void* block );
virtual void Compress4( void* block );
enum { kMaxIterations = 8 };
int m_iterationCount;
Vec3 m_principle;
u8 m_order[16*kMaxIterations];
Vec4 m_points_weights[16];
Vec4 m_xsum_wsum;
Vec4 m_metric;
Vec4 m_besterror;
};
} // namespace squish
#endif // ndef SQUISH_CLUSTERFIT_H
-214
View File
@@ -1,214 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#include "colourblock.h"
namespace squish {
static int FloatToInt( float a, int limit )
{
// use ANSI round-to-zero behaviour to get round-to-nearest
int i = ( int )( a + 0.5f );
// clamp to the limit
if( i < 0 )
i = 0;
else if( i > limit )
i = limit;
// done
return i;
}
static int FloatTo565( Vec3::Arg colour )
{
// get the components in the correct range
int r = FloatToInt( 31.0f*colour.X(), 31 );
int g = FloatToInt( 63.0f*colour.Y(), 63 );
int b = FloatToInt( 31.0f*colour.Z(), 31 );
// pack into a single value
return ( r << 11 ) | ( g << 5 ) | b;
}
static void WriteColourBlock( int a, int b, u8* indices, void* block )
{
// get the block as bytes
u8* bytes = ( u8* )block;
// write the endpoints
bytes[0] = ( u8 )( a & 0xff );
bytes[1] = ( u8 )( a >> 8 );
bytes[2] = ( u8 )( b & 0xff );
bytes[3] = ( u8 )( b >> 8 );
// write the indices
for( int i = 0; i < 4; ++i )
{
u8 const* ind = indices + 4*i;
bytes[4 + i] = ind[0] | ( ind[1] << 2 ) | ( ind[2] << 4 ) | ( ind[3] << 6 );
}
}
void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
{
// get the packed values
int a = FloatTo565( start );
int b = FloatTo565( end );
// remap the indices
u8 remapped[16];
if( a <= b )
{
// use the indices directly
for( int i = 0; i < 16; ++i )
remapped[i] = indices[i];
}
else
{
// swap a and b
std::swap( a, b );
for( int i = 0; i < 16; ++i )
{
if( indices[i] == 0 )
remapped[i] = 1;
else if( indices[i] == 1 )
remapped[i] = 0;
else
remapped[i] = indices[i];
}
}
// write the block
WriteColourBlock( a, b, remapped, block );
}
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block )
{
// get the packed values
int a = FloatTo565( start );
int b = FloatTo565( end );
// remap the indices
u8 remapped[16];
if( a < b )
{
// swap a and b
std::swap( a, b );
for( int i = 0; i < 16; ++i )
remapped[i] = ( indices[i] ^ 0x1 ) & 0x3;
}
else if( a == b )
{
// use index 0
for( int i = 0; i < 16; ++i )
remapped[i] = 0;
}
else
{
// use the indices directly
for( int i = 0; i < 16; ++i )
remapped[i] = indices[i];
}
// write the block
WriteColourBlock( a, b, remapped, block );
}
static int Unpack565( u8 const* packed, u8* colour )
{
// build the packed value
int value = ( int )packed[0] | ( ( int )packed[1] << 8 );
// get the components in the stored range
u8 red = ( u8 )( ( value >> 11 ) & 0x1f );
u8 green = ( u8 )( ( value >> 5 ) & 0x3f );
u8 blue = ( u8 )( value & 0x1f );
// scale up to 8 bits
colour[0] = ( red << 3 ) | ( red >> 2 );
colour[1] = ( green << 2 ) | ( green >> 4 );
colour[2] = ( blue << 3 ) | ( blue >> 2 );
colour[3] = 255;
// return the value
return value;
}
void DecompressColour( u8* rgba, void const* block, bool isDxt1 )
{
// get the block bytes
u8 const* bytes = reinterpret_cast< u8 const* >( block );
// unpack the endpoints
u8 codes[16];
int a = Unpack565( bytes, codes );
int b = Unpack565( bytes + 2, codes + 4 );
// generate the midpoints
for( int i = 0; i < 3; ++i )
{
int c = codes[i];
int d = codes[4 + i];
if( isDxt1 && a <= b )
{
codes[8 + i] = ( u8 )( ( c + d )/2 );
codes[12 + i] = 0;
}
else
{
codes[8 + i] = ( u8 )( ( 2*c + d )/3 );
codes[12 + i] = ( u8 )( ( c + 2*d )/3 );
}
}
// fill in alpha for the intermediate values
codes[8 + 3] = 255;
codes[12 + 3] = ( isDxt1 && a <= b ) ? 0 : 255;
// unpack the indices
u8 indices[16];
for( int i = 0; i < 4; ++i )
{
u8* ind = indices + 4*i;
u8 packed = bytes[4 + i];
ind[0] = packed & 0x3;
ind[1] = ( packed >> 2 ) & 0x3;
ind[2] = ( packed >> 4 ) & 0x3;
ind[3] = ( packed >> 6 ) & 0x3;
}
// store out the colours
for( int i = 0; i < 16; ++i )
{
u8 offset = 4*indices[i];
for( int j = 0; j < 4; ++j )
rgba[4*i + j] = codes[offset + j];
}
}
} // namespace squish
-41
View File
@@ -1,41 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#ifndef SQUISH_COLOURBLOCK_H
#define SQUISH_COLOURBLOCK_H
#include "squish.h"
#include "maths.h"
namespace squish {
void WriteColourBlock3( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block );
void WriteColourBlock4( Vec3::Arg start, Vec3::Arg end, u8 const* indices, void* block );
void DecompressColour( u8* rgba, void const* block, bool isDxt1 );
} // namespace squish
#endif // ndef SQUISH_COLOURBLOCK_H
-54
View File
@@ -1,54 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#include "colourfit.h"
#include "colourset.h"
namespace squish {
ColourFit::ColourFit( ColourSet const* colours, int flags )
: m_colours( colours ),
m_flags( flags )
{
}
ColourFit::~ColourFit()
{
}
void ColourFit::Compress( void* block )
{
bool isDxt1 = ( ( m_flags & kDxt1 ) != 0 );
if( isDxt1 )
{
Compress3( block );
if( !m_colours->IsTransparent() )
Compress4( block );
}
else
Compress4( block );
}
} // namespace squish
-55
View File
@@ -1,55 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#ifndef SQUISH_COLOURFIT_H
#define SQUISH_COLOURFIT_H
#include "squish.h"
#include <climits>
#include "maths.h"
namespace squish {
class ColourSet;
class ColourFit
{
public:
ColourFit( ColourSet const* colours, int flags );
virtual ~ColourFit();
void Compress( void* block );
protected:
virtual void Compress3( void* block ) = 0;
virtual void Compress4( void* block ) = 0;
ColourSet const* m_colours;
int m_flags;
};
} // namespace squish
#endif // ndef SQUISH_COLOURFIT_H
-121
View File
@@ -1,121 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#include "colourset.h"
namespace squish {
ColourSet::ColourSet( u8 const* rgba, int mask, int flags )
: m_count( 0 ),
m_transparent( false )
{
// check the compression mode for dxt1
bool isDxt1 = ( ( flags & kDxt1 ) != 0 );
bool weightByAlpha = ( ( flags & kWeightColourByAlpha ) != 0 );
// create the minimal set
for( int i = 0; i < 16; ++i )
{
// check this pixel is enabled
int bit = 1 << i;
if( ( mask & bit ) == 0 )
{
m_remap[i] = -1;
continue;
}
// check for transparent pixels when using dxt1
if( isDxt1 && rgba[4*i + 3] < 128 )
{
m_remap[i] = -1;
m_transparent = true;
continue;
}
// loop over previous points for a match
for( int j = 0;; ++j )
{
// allocate a new point
if( j == i )
{
// normalise coordinates to [0,1]
float x = ( float )rgba[4*i] / 255.0f;
float y = ( float )rgba[4*i + 1] / 255.0f;
float z = ( float )rgba[4*i + 2] / 255.0f;
// ensure there is always non-zero weight even for zero alpha
float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
// add the point
m_points[m_count] = Vec3( x, y, z );
m_weights[m_count] = ( weightByAlpha ? w : 1.0f );
m_remap[i] = m_count;
// advance
++m_count;
break;
}
// check for a match
int oldbit = 1 << j;
bool match = ( ( mask & oldbit ) != 0 )
&& ( rgba[4*i] == rgba[4*j] )
&& ( rgba[4*i + 1] == rgba[4*j + 1] )
&& ( rgba[4*i + 2] == rgba[4*j + 2] )
&& ( rgba[4*j + 3] >= 128 || !isDxt1 );
if( match )
{
// get the index of the match
int index = m_remap[j];
// ensure there is always non-zero weight even for zero alpha
float w = ( float )( rgba[4*i + 3] + 1 ) / 256.0f;
// map to this point and increase the weight
m_weights[index] += ( weightByAlpha ? w : 1.0f );
m_remap[i] = index;
break;
}
}
}
// square root the weights
for( int i = 0; i < m_count; ++i )
m_weights[i] = std::sqrt( m_weights[i] );
}
void ColourSet::RemapIndices( u8 const* source, u8* target ) const
{
for( int i = 0; i < 16; ++i )
{
int j = m_remap[i];
if( j == -1 )
target[i] = 3;
else
target[i] = source[j];
}
}
} // namespace squish
-58
View File
@@ -1,58 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#ifndef SQUISH_COLOURSET_H
#define SQUISH_COLOURSET_H
#include "squish.h"
#include "maths.h"
namespace squish {
/*! @brief Represents a set of block colours
*/
class ColourSet
{
public:
ColourSet( u8 const* rgba, int mask, int flags );
int GetCount() const { return m_count; }
Vec3 const* GetPoints() const { return m_points; }
float const* GetWeights() const { return m_weights; }
bool IsTransparent() const { return m_transparent; }
void RemapIndices( u8 const* source, u8* target ) const;
private:
int m_count;
Vec3 m_points[16];
float m_weights[16];
int m_remap[16];
bool m_transparent;
};
} // namespace squish
#endif // ndef SQUISH_COLOURSET_H
-49
View File
@@ -1,49 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
#ifndef SQUISH_CONFIG_H
#define SQUISH_CONFIG_H
// Set to 1 when building squish to use Altivec instructions.
#ifndef SQUISH_USE_ALTIVEC
#define SQUISH_USE_ALTIVEC 0
#endif
// Set to 1 or 2 when building squish to use SSE or SSE2 instructions.
#ifndef SQUISH_USE_SSE
#define SQUISH_USE_SSE 0
#endif
// Internally set SQUISH_USE_SIMD when either Altivec or SSE is available.
#if SQUISH_USE_ALTIVEC && SQUISH_USE_SSE
#error "Cannot enable both Altivec and SSE!"
#endif
#if SQUISH_USE_ALTIVEC || SQUISH_USE_SSE
#define SQUISH_USE_SIMD 1
#else
#define SQUISH_USE_SIMD 0
#endif
#endif // ndef SQUISH_CONFIG_H
-259
View File
@@ -1,259 +0,0 @@
/* -----------------------------------------------------------------------------
Copyright (c) 2006 Simon Brown si@sjbrown.co.uk
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-------------------------------------------------------------------------- */
/*! @file
The symmetric eigensystem solver algorithm is from
http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf
*/
#include "maths.h"
#include "simd.h"
#include <cfloat>
namespace squish {
Sym3x3 ComputeWeightedCovariance( int n, Vec3 const* points, float const* weights )
{
// compute the centroid
float total = 0.0f;
Vec3 centroid( 0.0f );
for( int i = 0; i < n; ++i )
{
total += weights[i];
centroid += weights[i]*points[i];
}
if( total > FLT_EPSILON )
centroid /= total;
// accumulate the covariance matrix
Sym3x3 covariance( 0.0f );
for( int i = 0; i < n; ++i )
{
Vec3 a = points[i] - centroid;
Vec3 b = weights[i]*a;
covariance[0] += a.X()*b.X();
covariance[1] += a.X()*b.Y();
covariance[2] += a.X()*b.Z();
covariance[3] += a.Y()*b.Y();
covariance[4] += a.Y()*b.Z();
covariance[5] += a.Z()*b.Z();
}
// return it
return covariance;
}
#if 0
static Vec3 GetMultiplicity1Evector( Sym3x3 const& matrix, float evalue )
{
// compute M
Sym3x3 m;
m[0] = matrix[0] - evalue;
m[1] = matrix[1];
m[2] = matrix[2];
m[3] = matrix[3] - evalue;
m[4] = matrix[4];
m[5] = matrix[5] - evalue;
// compute U
Sym3x3 u;
u[0] = m[3]*m[5] - m[4]*m[4];
u[1] = m[2]*m[4] - m[1]*m[5];
u[2] = m[1]*m[4] - m[2]*m[3];
u[3] = m[0]*m[5] - m[2]*m[2];
u[4] = m[1]*m[2] - m[4]*m[0];
u[5] = m[0]*m[3] - m[1]*m[1];
// find the largest component
float mc = std::fabs( u[0] );
int mi = 0;
for( int i = 1; i < 6; ++i )
{
float c = std::fabs( u[i] );
if( c > mc )
{
mc = c;
mi = i;
}
}
// pick the column with this component
switch( mi )
{
case 0:
return Vec3( u[0], u[1], u[2] );
case 1:
case 3:
return Vec3( u[1], u[3], u[4] );
default:
return Vec3( u[2], u[4], u[5] );
}
}
static Vec3 GetMultiplicity2Evector( Sym3x3 const& matrix, float evalue )
{
// compute M
Sym3x3 m;
m[0] = matrix[0] - evalue;
m[1] = matrix[1];
m[2] = matrix[2];
m[3] = matrix[3] - evalue;
m[4] = matrix[4];
m[5] = matrix[5] - evalue;
// find the largest component
float mc = std::fabs( m[0] );
int mi = 0;
for( int i = 1; i < 6; ++i )
{
float c = std::fabs( m[i] );
if( c > mc )
{
mc = c;
mi = i;
}
}
// pick the first eigenvector based on this index
switch( mi )
{
case 0:
case 1:
return Vec3( -m[1], m[0], 0.0f );
case 2:
return Vec3( m[2], 0.0f, -m[0] );
case 3:
case 4:
return Vec3( 0.0f, -m[4], m[3] );
default:
return Vec3( 0.0f, -m[5], m[4] );
}
}
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
{
// compute the cubic coefficients
float c0 = matrix[0]*matrix[3]*matrix[5]
+ 2.0f*matrix[1]*matrix[2]*matrix[4]
- matrix[0]*matrix[4]*matrix[4]
- matrix[3]*matrix[2]*matrix[2]
- matrix[5]*matrix[1]*matrix[1];
float c1 = matrix[0]*matrix[3] + matrix[0]*matrix[5] + matrix[3]*matrix[5]
- matrix[1]*matrix[1] - matrix[2]*matrix[2] - matrix[4]*matrix[4];
float c2 = matrix[0] + matrix[3] + matrix[5];
// compute the quadratic coefficients
float a = c1 - ( 1.0f/3.0f )*c2*c2;
float b = ( -2.0f/27.0f )*c2*c2*c2 + ( 1.0f/3.0f )*c1*c2 - c0;
// compute the root count check
float Q = 0.25f*b*b + ( 1.0f/27.0f )*a*a*a;
// test the multiplicity
if( FLT_EPSILON < Q )
{
// only one root, which implies we have a multiple of the identity
return Vec3( 1.0f );
}
else if( Q < -FLT_EPSILON )
{
// three distinct roots
float theta = std::atan2( std::sqrt( -Q ), -0.5f*b );
float rho = std::sqrt( 0.25f*b*b - Q );
float rt = std::pow( rho, 1.0f/3.0f );
float ct = std::cos( theta/3.0f );
float st = std::sin( theta/3.0f );
float l1 = ( 1.0f/3.0f )*c2 + 2.0f*rt*ct;
float l2 = ( 1.0f/3.0f )*c2 - rt*( ct + ( float )sqrt( 3.0f )*st );
float l3 = ( 1.0f/3.0f )*c2 - rt*( ct - ( float )sqrt( 3.0f )*st );
// pick the larger
if( std::fabs( l2 ) > std::fabs( l1 ) )
l1 = l2;
if( std::fabs( l3 ) > std::fabs( l1 ) )
l1 = l3;
// get the eigenvector
return GetMultiplicity1Evector( matrix, l1 );
}
else // if( -FLT_EPSILON <= Q && Q <= FLT_EPSILON )
{
// two roots
float rt;
if( b < 0.0f )
rt = -std::pow( -0.5f*b, 1.0f/3.0f );
else
rt = std::pow( 0.5f*b, 1.0f/3.0f );
float l1 = ( 1.0f/3.0f )*c2 + rt; // repeated
float l2 = ( 1.0f/3.0f )*c2 - 2.0f*rt;
// get the eigenvector
if( std::fabs( l1 ) > std::fabs( l2 ) )
return GetMultiplicity2Evector( matrix, l1 );
else
return GetMultiplicity1Evector( matrix, l2 );
}
}
#else
#define POWER_ITERATION_COUNT 8
Vec3 ComputePrincipleComponent( Sym3x3 const& matrix )
{
Vec4 const row0( matrix[0], matrix[1], matrix[2], 0.0f );
Vec4 const row1( matrix[1], matrix[3], matrix[4], 0.0f );
Vec4 const row2( matrix[2], matrix[4], matrix[5], 0.0f );
Vec4 v = VEC4_CONST( 1.0f );
for( int i = 0; i < POWER_ITERATION_COUNT; ++i )
{
// matrix multiply
Vec4 w = row0*v.SplatX();
w = MultiplyAdd(row1, v.SplatY(), w);
w = MultiplyAdd(row2, v.SplatZ(), w);
// get max component from xyz in all channels
Vec4 a = Max(w.SplatX(), Max(w.SplatY(), w.SplatZ()));
// divide through and advance
v = w*Reciprocal(a);
}
return v.GetVec3();
}
#endif
} // namespace squish

Some files were not shown because too many files have changed in this diff Show More