AcademySoftwareFoundation / OpenColorIO

A color management framework for visual effects and animation.
https://opencolorio.org
BSD 3-Clause "New" or "Revised" License
1.76k stars 434 forks source link

Create transform from in memory ICC profile #1850

Closed SRHMorris closed 8 months ago

SRHMorris commented 11 months ago

It looks like there's no way to create a transform from an in memory ICC profile (as an array of bytes, rather than a file on disk).

It's possible I've missed something, but this would be a really nice feature for me for offloading more work to the GPU. I'd be fine with it not supporting everything as I can fallback to performing the transform with LittleCMS.

Use case is I've already loaded an image with an embedded ICC profile into memory. It would be good for this to transform from the input to XYZ D65 (display referred).

doug-walker commented 8 months ago

It's maybe more work than you'd like, but this did become possible as of OCIO 2.2. Here's a rough Python example of how to load a FileTransform from a buffer. Once you have the Processor, you may dispose of the config.

    class CIOPTest(ocio.PyConfigIOProxy):
        def getConfigData(self):
            return ocio.Config.CreateRaw().serialize()

        def getLutData(self, filepath):
            with open(filepath, 'rb') as file_t:
                # This is your buffer.
                return bytearray(file_t.read())

        def getFastLutFileHash(self, filepath):
            import os
            if os.path.isfile(filepath):
                return filepath
            else:
                return ''

    ciop = CIOPTest()
    config = ocio.Config.CreateFromConfigIOProxy(ciop)

    icc_path = '/usr/local/workspace/OpenColorIO/tests/data/files/icc-test-1.icc'

    ft = ocio.FileTransform(icc_path)
    processor = config.getProcessor(ft)
    cpu = processor.getDefaultCPUProcessor()
    print(cpu.applyRGB([0.1,0.2,0.4]))
SRHMorris commented 8 months ago

Thanks @doug-walker that seems to be working perfectly for me

doug-walker commented 8 months ago

Glad it's helpful @SRHMorris ! One additional detail I should mention is that you probably want to modify the getFastLutFileHash implementation from what I put in my very simple example above. This is used by OCIO's file caching mechanism, so it needs to be unique for each different buffer of LUT data that you want to load.

In addition, when you create the FileTransform, the src argument should have the correct extension ('.icc', '.pf', or '.icm' in this case) so that OCIO tries to read it with the correct file format parser first.

SRHMorris commented 8 months ago

@doug-walker Thanks, yes for now I was just using the filename which should be unique in my case, but I'll try to improve that. Good point about the extension!