I'm testing code from this question:
``
import bpy
width = 800
height = 400
image = bpy.data.images.new("testimagepacked", width=width, height=height,float_buffer=True)
pixels = [None] * width * height
for x in range(0,width):
for y in range(0,height):
pixels[(y*width)+x] = [float(x)/width,float(y)/height,-y+x,1.0]
pixels = [chan for px in pixels for chan in px]
image.pixels = pixels
image.update()
``
I noticed the code above generates different colors depending on the float_buffer being True or False:
From what I understand - pixel (RGBA) values for 8bit are in range from [0..1], so:
1) How is 32bpc different in that regard?
2) Is there a way to create 8 and 32bpc images, that would result in identical (visually) colors from the same code (with different RGB values maybe)?
3) Also - if I had an 8bit image - how could I transfer pixel values to a 32bit image and keep it visually consistent?
EDIT: Investigating the issue, references:
''
import bpy
width = 100
height = 50
image = bpy.data.images.new("float buffer true", width=width, height=height,float_buffer=True)
pixels = [None] * width * height
for x in range(0,width):
for y in range(0,height):
pixels[(y*width)+x] = [float(x)/width,float(y)/height,-y+x,1.0]
pixels = [chan for px in pixels for chan in px]
image.pixels = pixels
image.update()
image = bpy.data.images.new("float buffer false", width=width, height=height,float_buffer=False)
pixels = [None] * width * height
for x in range(0,width):
for y in range(0,height):
pixels[(y*width)+x] = [float(x)/width,float(y)/height,-y+x,1.0]
pixels = [chan for px in pixels for chan in px]
image.pixels = pixels
image.update()
def convert_to_srgb(val):
if (val <= 0.0031308):
return (val * 12.92)
else:
return (1.055*(val**(1.0/2.4))-0.055)
image = bpy.data.images.new("float buffer false converted", width=width, height=height,float_buffer=False)
pixels = [None] * width * height
for x in range(0,width):
for y in range(0,height):
pixels[(y*width)+x] = [ convert_to_srgb(float(x)/width),
convert_to_srgb(float(y)/height),
convert_to_srgb(-y+x),
1.0
]
pixels = [chan for px in pixels for chan in px]
image.pixels = pixels
image.update()
''
This code result:
And color comparison on one point:
So my question now (since the original question found it's answer): is this behavior expected? Am I missing a point here? I mean: if I write a given color value directly to pixel... the result should be the same inspite the fact that image has floating_point buffer True or False? or not? Especially that Blender states it does all color data manipulation in linear values (it still might be true - only 8bit images values seem to be converted on the fly somewhere, where it isn't exposed to the python api?).
Why is this confusing for me? Because I'd understand why 8bpc might store raw pixel data differently from EXR's, like troy_s mentioned (however I'd assume blender should store all image data in a standarized way)... but actually loading for example 16bpc PNG converts it to float_buffer and stores data like 32bpc (EXR) image. That seems very odd and unconsistent to me. I would expect that all images are loaded to blender to fit the float32 buffer, converting (sRGB->linear) all 8bit images to this format as well. Instead what we have here is two different data formats, one (for 8bit) holds sRGB raw values, the other (for anything above) linear values. Confusing.
EDIT:
Digging through Blender source code. So there are two formats to hold image buffer values ('byte' when referring to 8bpc and 'float' for 32bpc), would be great if someone who actually know the design could answer how does that work.
Here PNGs are loaded to different image buffer type, depending on the PNG bpc.
Ok, my assumptions were correct IMB_imbuf_types.h:
``
/* pixels */
/** Image pixel buffer (8bit representation):
* - color space defaults to `sRGB`.
* - alpha defaults to 'straight'.
*/
unsigned int *rect;
/** Image pixel buffer (float representation):
* - color space defaults to 'linear' (`rec709`).
* - alpha defaults to 'premul'.
* \note May need gamma correction to `sRGB` when generating 8bit representations.
* \note Formats that support higher more than 8 but channels load as floats.
*/
``
The question still remains though: why? Wouldn't it be better to convert all images to linear values and single buffer type?