0

I am trying to set float value to pixels in an image. But the value as shown after that is different from the value that has been set. It seems this is a precision problem as mention in this answer. My question is are there any way to set the value of the pixel to an exact number (precision reduce is ok).

In my case, 0.11111111 turns into 0.111111119389534. So the difference are small but after a few calculations, it could becomes a huge margin.

Here is my test code in Blender 2.8:

import bpy
import gpu
import bgl
import random
from mathutils import Matrix
from gpu_extras.batch import batch_for_shader
import numpy as np
from math import *
# from gpu_extras.presets import draw_circle_2d
import time

IMAGE_NAME = "Generated Image"
WIDTH = 4
HEIGHT = 4

# print(buffer)
# push buffer to blender image
if IMAGE_NAME in bpy.data.images:
    image = bpy.data.images[IMAGE_NAME]
    if image:
        bpy.data.images.remove(image)
        bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT, alpha=False, float_buffer=True, is_data=True)
else:
    bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT, alpha=False, float_buffer=True, is_data=True)

image = bpy.data.images[IMAGE_NAME]
pixels = list(image.pixels)

#FIXED: set data
for i in range(0, WIDTH*HEIGHT*4, 4):
    pixels[i] = 0.11111111
    pixels[i+1] = 0.22222222
    pixels[i+2] = 0.33333333
    pixels[i+3] = 0.44444444

image.pixels[:] = pixels
image.update()
print(list(image.pixels))
  • 1
    The difference in value is due to the floating point format IEEE-754 not being able to represent all numbers precisely. For single precision (32 bit) this results in the approximation you're seeing. – Robert Gützkow Feb 19 '20 at 15:39
  • I can write an answer for this, but I believe there are plenty of explanations about this topic on the internet, including on StackOverflow. – Robert Gützkow Feb 19 '20 at 15:52
  • I am a newbie in this field, and I was looking for a solution for a few days, so can you share some information about this? I really appreciate your help. – Nguyen Cong Feb 19 '20 at 16:26
  • @Robert I also aware of the reason as in the link I provided in the question, but I don't know how to solve it – Nguyen Cong Feb 19 '20 at 16:27
  • 1
    In these specific circumstance, with an API that requires you to input single precision floats, you simply cannot get an accurate representation of every number due to the limitations of IEEE-754. Therefore there is no solution to your problem. What you can do, when your problem requires many consecutive operations with floating point arithmetic and you're worried about accumulation of errors, is working either with decimals or arbitrary precision floating points (for instance with mpmath). – Robert Gützkow Feb 19 '20 at 17:52
  • 1
    I've been searching for a website that explains this reasonably well, perhaps this one could help you understand floating point numbers. – Robert Gützkow Feb 19 '20 at 17:55
  • @RobertGützkow Thank you very much for your help. Actually I am trying to send data to fragment shader using image texture. I already tried with decimals but because of the incorrect precision in the pixels, the shader can not give correct results. – Nguyen Cong Feb 20 '20 at 01:50

0 Answers0