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
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.FLOAT)
        # 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

Reply via email to