Skip to content

ImageSpec:set_colorspace() #3734

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/doc/pythonbindings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,22 @@ Section :ref:`sec-ImageSpec`, is replicated for Python.
data types, but not the arbitrary named metadata or channel names.


.. py:method:: bool ImageSpec.set_colorspace (name)

Set metadata to indicate the presumed color space `name`, or clear all
such metadata if `name` is the empty string.

This function was added in version 2.5.

Example:

.. code-block:: python

spec = ImageSpec(...)
spec.set_colorspace ("sRGB")



.. py:method:: ImageSpec.undefined ()

Returns `True` for a newly initialized (undefined) ImageSpec.
Expand Down
9 changes: 9 additions & 0 deletions src/include/OpenImageIO/imageio.h
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,15 @@ class OIIO_API ImageSpec {
deep = other.deep;
}

/// Set the metadata to presume that color space is `name` (or to assume
/// nothing about the color space if `name` is empty). The core operation
/// is to set the "oiio:ColorSpace" attribute, but it also removes or
/// alters several other attributes that may hint color space in ways that
/// might be contradictory or no longer true.
///
/// @version 2.5
void set_colorspace(string_view name);

/// Returns `true` for a newly initialized (undefined) `ImageSpec`.
/// (Designated by no channels and undefined data type -- true of the
/// uninitialized state of an ImageSpec, and presumably not for any
Expand Down
6 changes: 3 additions & 3 deletions src/libOpenImageIO/color_ocio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1823,7 +1823,7 @@ ImageBufAlgo::colorconvert(ImageBuf& dst, const ImageBuf& src, string_view from,
bool ok = colorconvert(dst, src, processor.get(), unpremult, roi, nthreads);
if (ok) {
// DBG("done, setting output colorspace to {}\n", to);
dst.specmod().attribute("oiio:ColorSpace", to);
dst.specmod().set_colorspace(to);
}
return ok;
}
Expand Down Expand Up @@ -2132,7 +2132,7 @@ ImageBufAlgo::ociolook(ImageBuf& dst, const ImageBuf& src, string_view looks,
logtime.stop(); // transition to colorconvert
bool ok = colorconvert(dst, src, processor.get(), unpremult, roi, nthreads);
if (ok)
dst.specmod().attribute("oiio:ColorSpace", to);
dst.specmod().set_colorspace(to);
return ok;
}

Expand Down Expand Up @@ -2267,7 +2267,7 @@ ImageBufAlgo::ociofiletransform(ImageBuf& dst, const ImageBuf& src,
logtime.stop(); // transition to colorconvert
bool ok = colorconvert(dst, src, processor.get(), unpremult, roi, nthreads);
if (ok)
dst.specmod().attribute("oiio:ColorSpace", name);
dst.specmod().set_colorspace(name);
return ok;
}

Expand Down
26 changes: 26 additions & 0 deletions src/libOpenImageIO/formatspec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1222,4 +1222,30 @@ pvt::check_texture_metadata_sanity(ImageSpec& spec)
}



void
ImageSpec::set_colorspace(string_view colorspace)
{
// If we're not changing color space, don't mess with anything
string_view oldspace = get_string_attribute("oiio:ColorSpace");
if (oldspace.size() && colorspace.size() && oldspace == colorspace)
return;

// Set or clear the main "oiio:ColorSpace" attribute
if (colorspace.empty()) {
erase_attribute("oiio:ColorSpace");
} else {
attribute("oiio:ColorSpace", colorspace);
}

// Clear a bunch of other metadata that might contradict the colorspace,
// including some format-specific things that we don't want to propagate
// from input to output if we know that color space transformations have
// occurred.
erase_attribute("Exif:ColorSpace");
erase_attribute("tiff:ColorSpace");
erase_attribute("tiff:PhotometricInterpretation");
}


OIIO_NAMESPACE_END
40 changes: 37 additions & 3 deletions src/oiiotool/oiiotool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2647,11 +2647,45 @@ set_colorconfig(int argc, const char* argv[])



// Special OiiotoolOp whose purpose is to set attributes on the top image.
class OpSetColorSpace final : public OiiotoolOp {
public:
OpSetColorSpace(Oiiotool& ot, string_view opname, cspan<const char*> argv)
: OiiotoolOp(ot, opname, argv, 1)
{
inplace(true); // This action operates in-place
colorspace = args(1);
}
OpSetColorSpace(Oiiotool& ot, string_view opname, int argc,
const char* argv[])
: OpSetColorSpace(ot, opname, { argv, argc })
{
}
bool setup() override
{
ir(0)->metadata_modified(true);
return true;
}
bool impl(span<ImageBuf*> img) override
{
// Because this is an in-place operation, img[0] is the same as
// img[1].
img[0]->specmod().set_colorspace(colorspace);
return true;
}

private:
string_view colorspace;
};



// --iscolorspace
static void
set_colorspace(cspan<const char*> argv)
action_iscolorspace(cspan<const char*> argv)
{
action_sattrib({ argv[0], "oiio:ColorSpace", argv[1] });
OpSetColorSpace op(ot, "iscolorspace", argv);
op();
}


Expand Down Expand Up @@ -6857,7 +6891,7 @@ Oiiotool::getargs(int argc, char* argv[])
.action(set_colorconfig);
ap.arg("--iscolorspace %s:COLORSPACE")
.help("Set the assumed color space (without altering pixels)")
.action(set_colorspace);
.action(action_iscolorspace);
ap.arg("--tocolorspace %s:COLORSPACE")
.help("Convert the current image's pixels to a named color space")
.action(action_tocolorspace);
Expand Down
6 changes: 6 additions & 0 deletions src/python/py_imagespec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ declare_imagespec(py::module& m)
.def("valid_tile_range", &ImageSpec::valid_tile_range, "xbegin"_a,
"xend"_a, "ybegin"_a, "yend"_a, "zbegin"_a, "zend"_a)
.def("copy_dimensions", &ImageSpec::copy_dimensions, "other"_a)
.def(
"set_colorspace",
[](ImageSpec& self, const std::string& cs) {
self.set_colorspace(cs);
},
"name"_a)
// __getitem__ is the dict-like `ImageSpec[key]` lookup
.def("__getitem__",
[](const ImageSpec& self, const std::string& key) {
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-imagespec/ref/out-python3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ Testing construction from ROI:
deep = False


Testing set_colorspace:
after set_colorspace('sRGB'): sRGB
after set_colorspace(''):

Testing global attribute store/retrieve:
get_string_attribute plugin_searchpath : perfect
get_int_attribute plugin_searchpath : 0
Expand Down
4 changes: 4 additions & 0 deletions testsuite/python-imagespec/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ Testing construction from ROI:
deep = False


Testing set_colorspace:
after set_colorspace('sRGB'): sRGB
after set_colorspace(''):

Testing global attribute store/retrieve:
get_string_attribute plugin_searchpath : perfect
get_int_attribute plugin_searchpath : 0
Expand Down
7 changes: 7 additions & 0 deletions testsuite/python-imagespec/src/test_imagespec.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ def print_imagespec (spec, msg="") :
sroi = oiio.ImageSpec (oiio.ROI(0,640,0,480,0,1,0,3), oiio.FLOAT);
print_imagespec (sroi)

print ("\nTesting set_colorspace:")
s = oiio.ImageSpec()
s.set_colorspace("sRGB")
print (" after set_colorspace('sRGB'):", s.get_string_attribute("oiio:ColorSpace"))
s.set_colorspace("")
print (" after set_colorspace(''):", s.get_string_attribute("oiio:ColorSpace"))

# Also test global OIIO functions here
print ("\nTesting global attribute store/retrieve:")
oiio.attribute ("plugin_searchpath", "perfect")
Expand Down