I assumed oiio.FLOAT describes the data type and that script wouldn't know whether the texture it was reading was UINT8 linear, gamma22, or sRGB.
That assumption seems to be correct. I changed the script to UINT8 and I'm still getting basically the same result. Black is 0 and white is 255 but 50% gray should be higher than 128 due to the nonlinear sRGB LUT: $ python ~/scripts-dev/miplevels.py checker_uint8_sRGB.tx > 0 512x512=262144 min=0 med=255 max=255 > 1 256x256=65536 min=0 med=255 max=255 > 2 128x128=16384 min=0 med=255 max=255 > 3 64x64=4096 min=0 med=255 max=255 > 4 32x32=1024 min=127 med=127 max=155 > 5 16x16=256 min=127 med=127 max=142 > 6 8x8=64 min=127 med=127 max=135 > 7 4x4=16 min=127 med=129 max=131 > 8 2x2=4 min=128 med=129 max=129 > 9 1x1=1 min=129 med=129 max=129 > As a sanity check I made a uniform 50% grey texture and the values are at 188, consistent with sRGB 50% grey: $ iinfo --stats grey_float32_lin.tif > grey_float32_lin.tif : 512 x 512, 3 channel, float tiff > Stats Min: 0.500000 0.500000 0.500000 (float) > Stats Max: 0.500000 0.500000 0.500000 (float) > Stats Avg: 0.500000 0.500000 0.500000 (float) > Stats StdDev: 0.000000 0.000000 0.000000 (float) > Stats NanCount: 0 0 0 > Stats InfCount: 0 0 0 > Stats FiniteCount: 262144 262144 262144 > Constant: Yes > Constant Color: 0.500000 0.500000 0.500000 (float) > Monochrome: Yes > $ maketx --oiio -d uint8 --unpremult --colorconvert linear sRGB > grey_float32_lin.tif -o grey_uint8_sRGB.tx > $ python ~/scripts-dev/miplevels.py grey_uint8_sRGB.tx > 0 512x512=262144 min=188 med=188 max=188 > 1 256x256=65536 min=188 med=188 max=188 > 2 128x128=16384 min=188 med=188 max=188 > 3 64x64=4096 min=188 med=188 max=188 > 4 32x32=1024 min=188 med=188 max=188 > 5 16x16=256 min=188 med=188 max=188 > 6 8x8=64 min=188 med=188 max=188 > 7 4x4=16 min=188 med=188 max=188 > 8 2x2=4 min=188 med=188 max=188 > 9 1x1=1 min=188 med=188 max=188 On Sun, 10 Jan 2021 at 18:48, Solomon Boulos <bou...@cs.stanford.edu> wrote: > Doesn’t get as float convert from sRGB to Linear in your miplevels.py? If > you don’t want conversion, open it as int8. > > On Sun, Jan 10, 2021 at 10:39 Søren Ragsdale <sor...@gmail.com> wrote: > >> I have "checker_float32_lin.tif", a simple RGBA black and white >> checkerboard. Each black or white square is 8 pixels wide, and every pixel >> value is either 0.0 or 1.0. >> >> I'm using OIIO to turn this float32 scene-linear TIFF into a uint8 sRGB >> albedo texture: >> >> maketx --oiio -d uint8 --unpremult --colorconvert linear sRGB >> checker_float32_lin.tif -o checker_uint8_sRGB.tx >> >> I've written miplevels.py (see attached) which prints the min, median, >> and max values of the first color channel for each mipmap level of the >> texture. Here's the output: >> >> $ python ~/scripts-dev/miplevels.py checker_uint8_sRGB.tx >>> 0 512x512=262144 min=0.0 med=1.0 max=1.0 >>> 1 256x256=65536 min=0.0 med=1.0 max=1.0 >>> 2 128x128=16384 min=0.0 med=1.0 max=1.0 >>> 3 64x64=4096 min=0.0 med=1.0 max=1.0 >>> 4 32x32=1024 min=0.498039245605 med=0.498039245605 max=0.607843160629 >>> 5 16x16=256 min=0.498039245605 med=0.498039245605 max=0.556862771511 >>> 6 8x8=64 min=0.498039245605 med=0.498039245605 max=0.529411792755 >>> 7 4x4=16 min=0.498039245605 med=0.505882382393 max=0.51372551918 >>> 8 2x2=4 min=0.501960813999 med=0.505882382393 max=0.505882382393 >>> 9 1x1=1 min=0.505882382393 med=0.505882382393 max=0.505882382393 >> >> >> As the mipmaps decrease in size the median value converges on 0.5. Except >> this is a sRGB texture. The value for 50% grey should be around 0.737 in >> sRGB space. >> >> It appears maketx is converting the values from linear to sRGB then >> scaling to create the mipmaps. When the source and destination color space >> are specified I think maketx should scale in scene linear color space, >> *then* convert to sRGB before saving each mipmap. >> >> Is this a bug? Is there a flag or workaround that I should know about? >> >> >> https://paroj.github.io/gltut/Texturing/Tut16%20Mipmaps%20and%20Linearity.html >> _______________________________________________ >> Oiio-dev mailing list >> Oiio-dev@lists.openimageio.org >> http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org >> > _______________________________________________ > Oiio-dev mailing list > Oiio-dev@lists.openimageio.org > http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org >
import sys import OpenImageIO as oiio import numpy as np def miplevels(fpath): b_all = oiio.ImageBuf(fpath) for miplevel in range(0, b_all.nmiplevels): # open the mipmap level b = oiio.ImageBuf(fpath, 0, miplevel) # get all the pixels pixels = b.get_pixels(oiio.UINT8) # slice pixels from the first channel pixels = pixels[::b.nchannels] # sort pixel values pixels = np.sort(pixels) print "{0} {1}x{2}={3} min={4} med={5} max={6}".format( miplevel, b.ymax - b.ymin + 1, b.xmax - b.xmin + 1, len(pixels), pixels[0], pixels[len(pixels) / 2], pixels[-1]) if __name__ == "__main__": miplevels(sys.argv[1])
_______________________________________________ Oiio-dev mailing list Oiio-dev@lists.openimageio.org http://lists.openimageio.org/listinfo.cgi/oiio-dev-openimageio.org