This had me stumped for hours! And it revealed a very subtle bug in OIIO's 
reading of TIFF images when restricting the channel range.


> pixels = sourceImg.read_image(0, 3, oiio.UINT8)

Here, you are reading just the first 3 channels of an RGBA image. Seems sane, 
except that this is a peculiar TIFF file -- the metadata says it's 
"unassociated alpha" (that means that the color values are not yet 
"premultiplied" by the alpha). Since OIIO assumes all app-side buffers should 
be premultiplied, it does it for you by multiplying the color channels by the 
alpha channel.

Oh ho, except that you excluded the alpha channel from the read!  Oops.  So the 
RGB values get multiplied by some bogus alpha values, garbage (probably, 
actually, the red value from the next pixel).

I'm working on a true fix -- the read_xxx() functions that take channel ranges 
should skip the automatic premult if the alpha channel was not among those read.

In the mean time, just read all the channels, and I think you'll be fine. 
There's no harm calling ImageBuf.write("blah.jpg") if the buf has 4 channels... 
since JPEG only supports 3, it knows to just write RGB and ignore the alpha.

(Also make resizedImageSpec have 4 channels. The resample() function requires 
that both source and dest images have the same number of channels.)


As an aside, I also want to note that this sequence:

> sourceImg = ImageInput.open(sourcePath)
> spec = sourceImg.spec()
>  
> pixels = sourceImg.read_image(0, 3, oiio.UINT8)
>  
> sourceBufSpec = ImageSpec(spec.width, spec.height, 3, oiio.UINT8)
> sourceBuf = ImageBuf(sourceBufSpec)
> sourceBuf.set_pixels(oiio.ROI.All, pixels)

Is much more complicated than it needs to be. If you're just trying to put 
things into an ImageBuf, you don't need the ImageInput, the read_image, or the 
set_pixels. That whole thing can be collapsed to:

> sourceBuf = ImageBuf(sourcePath)
> spec = sourceBuf.spec()


And finally, I would eliminate these lines entirely:

> # Set input colorspace to linear if converting EXR file
> if sourcePath.split('.')[-1] == 'exr':
>     ImageBufAlgo.colorconvert(resizedBuf, resizedBuf, 'linear', 'sRGB')

That doesn't really make any sense. Just remove those lines. You want to 
convert to sRGB before outputting to JPEG, but there's no reason to convert out 
of linear just because it was originally exr.

        -- lg


> On Dec 31, 2018, at 1:05 PM, Renaud Talon <[email protected]> wrote:
> 
> Hi Larry, thanks a bunch for your help.
>  
> I tried the code you sent me which attempts to read the colorspace of the 
> input image and the result is a now a brighter and desaturated image.
> I uploaded the tiff image I’m using as a source so hopefully you can see the 
> same result on your end.
> 
> <image001.jpg>
>  
> Test Tiff image:
> http://s000.tinyupload.com/?file_id=10327734964867955756 
> <http://s000.tinyupload.com/index.php?file_id=10327734964867955756>
>  
>  
> Updated Code Sample:
>  
> import sys
>  
> from OpenImageIO import OpenImageIO as oiio
> from OpenImageIO import ImageBufAlgo, ImageBuf, ImageSpec, ImageInput
>  
>  
> sourcePath = "C:/temp/ataafm_diff_v001.1005.tif"
> destImgPath = "C:/temp/test_oiio.jpg"
>  
> sourceImg = ImageInput.open(sourcePath)
> spec = sourceImg.spec()
>  
> pixels = sourceImg.read_image(0, 3, oiio.UINT8)
>  
> sourceBufSpec = ImageSpec(spec.width, spec.height, 3, oiio.UINT8)
> sourceBuf = ImageBuf(sourceBufSpec)
> sourceBuf.set_pixels(oiio.ROI.All, pixels)
>  
> resizedImgSpec = ImageSpec(int(120), int(120), 3, oiio.UINT8)
> resizedBuf = ImageBuf(resizedImgSpec)
>  
> ImageBufAlgo.resample(resizedBuf, sourceBuf)
>  
> # Set input colorspace to linear if converting EXR file
> if sourcePath.split('.')[-1] == 'exr':
>     ImageBufAlgo.colorconvert(resizedBuf, resizedBuf, 'linear', 'sRGB')
>  
> if destImgPath.split('.')[-1] == 'jpg':
>     # query input color space, presume linear if there is no such metadata
>     srcColSpace = sourceImg.spec().get_string_attribute('oiio:ColorSpace', 
> 'linear')
>     ImageBufAlgo.colorconvert(resizedBuf, resizedBuf, srcColSpace, 'sRGB')
>  
> resizedBuf.write(destImgPath)
>  
>  
>  
> From: Renaud Talon 
> Sent: Friday, December 28, 2018 1:10 PM
> To: 'Larry Gritz' <[email protected] <mailto:[email protected]>>; 
> OpenImageIO developers <[email protected] 
> <mailto:[email protected]>>; [email protected] 
> <mailto:[email protected]>
> Subject: RE: [Oiio-dev] Tiff image conversion to jpg color shift issue
>  
> oiiotool.exe C:\temp\ataafm_diff_v001.1005.tif -resize 120x120 -o 
> c:/temp/test_oiio_tool.jpg
>  
> From: Larry Gritz <[email protected] <mailto:[email protected]>> 
> Sent: Friday, December 28, 2018 1:05 PM
> To: OpenImageIO developers <[email protected] 
> <mailto:[email protected]>>; Renaud Talon 
> <[email protected] <mailto:[email protected]>>; 
> [email protected] <mailto:[email protected]>
> Subject: Re: [Oiio-dev] Tiff image conversion to jpg color shift issue
>  
> What oiiotool command line did you use when it worked as expected?
> 
> 
> On December 28, 2018 12:36:04 PM PST, Renaud Talon <[email protected] 
> <mailto:[email protected]>> wrote:
> Hi Larry,
>  
> I’m having a problem when making thumbnails from tiff images where the 
> results image is coming out darker and less saturated than the source.
> When using oiiotool.exe it results in a proper output but the issue happens 
> when I do the conversion myself from the python API.
> Any idea why this is happening ?
> Thanks !
>  
> Trimmed down code:
> 
> from OpenImageIO import OpenImageIO as oiio
> from OpenImageIO.OpenImageIO import ImageBufAlgo, ImageBuf, ImageSpec, 
> ImageInput
>  
>  
> sourceImgPath = "C:/temp/ataafm_diff_v001.1005.tif"
>  
> sourceImg = ImageInput.open(sourceImgPath)
> spec = sourceImg.spec()
>  
> pixels = sourceImg.read_image(0, 3, oiio.UINT8)
>  
> sourceBufSpec = ImageSpec(spec.width, spec.height, 3, oiio.UINT8)
> sourceBuf = ImageBuf(sourceBufSpec)
> sourceBuf.set_pixels(oiio.ROI.All, pixels)
>  
> resizedImgSpec = ImageSpec(int(120), int(120), 3, oiio.UINT8)
> resizedBuf = ImageBuf(resizedImgSpec)
>  
> ImageBufAlgo.resample(resizedBuf, sourceBuf)
>  
> # Set input colorspace to linear if converting EXR file
> if sourceImgPath.split('.')[-1] == 'exr':
>     ImageBufAlgo.colorconvert(resizedBuf, resizedBuf, 'linear', 'sRGB')
>  
> resizedBuf.write('C:/temp/test_oiio.jpg')
>  
>  
> 
>  
> Renaud
> 
> -- 
> Larry Gritz
> [email protected] <mailto:[email protected]>
--
Larry Gritz
[email protected]




_______________________________________________
Oiio-dev mailing list
[email protected]
http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org

Reply via email to