将颜色值从float 0..1转换为byte 0..255

fharum 发布于 2019-11-10 c 最后更新 2019-11-10 12:11 313 浏览

将颜色值从float转换为byte的正确方法是什么?起初,我认为b=f255.0应该这样做,但现在我想,在这种情况下,只有确切的1.0将被转换为255,但0.9999已经是254,这可能不是我想要的... 看起来b=f256.0会更好,除非256确实存在PLACEHOLDER_FOR_CODE_6的情况。 最后我使用这个:

#define F2B(f) ((f) >= 1.0 ? 255 : (int)((f)*256.0))
已邀请:

wrerum

赞同来自:

public static void floatToByte(float f)
{
     return (byte)(f * 255 % 256)
}
值< 1准确转换。 转换后,介于255和256之间的值在转换为字节时会浮动到255。 使用%运算符将值> 1循环回0。

mnatus

赞同来自:

我认为正确的是楼层(f * 256),而不是圆形。这会将间隔0..1映射到相等长度的256个区域。 [编辑]并检查256作为特例。

wqui

赞同来自:

我花了一些时间研究这个问题。我认为这个问题在这里:

255 -> 1.0
127 -> 0.5
0   -> 0.0
这意味着0映射到0,1-127(总共127个值)映射0.007874-0.5,并且128-255(总共128个值)映射0.5-1.0。 在1-127范围内,每1点等于1/127,在128-255范围内,每1点等于1/128。这是一个问题,因为它们并不完全相同,但是这个问题是因为127在使用整数时被认为是“中点”而产生的,技术上它应该是127.5 我使用以下公式:
if(v <= 127)
    return 0.5 * v/127.0;
else
    return 0.5 + 0.5 * v/128.0;
从浮点数扩展回整数也是同样有问题的,因为0.5映射到127(0.5 * 2然后应该是127 * 2,但254不是颜色最大值,它是255)
if(n <= 0.5)
   return floor(n*2*127);
else
   return 127 + floor(128*2*(n-0.5));

asaepe

赞同来自:

1.0是唯一可能出错的情况,所以单独处理该案例:

b = floor(f >= 1.0 ? 255 : f * 256.0)
此外,值得强制的是,f确实为0 <= f <= 1以避免由于舍入误差导致的不正确行为(例如,f = 1.0000001)。
f2 = max(0.0, min(1.0, f))
b = floor(f2 == 1.0 ? 255 : f2 * 256.0)
替代安全解决方案
b = (f >= 1.0 ? 255 : (f <= 0.0 ? 0 : (int)floor(f * 256.0)))
要么
b = max(0, min(255, (int)floor(f * 256.0)))

ket

赞同来自:

内容太长未翻译

kalias

赞同来自:

当它比较float时,接受的解决方案失败,因为它是整数。 这段代码工作正常:

float f;
uint8_t i;
//byte to float
f =CLAMP(((float)((i &0x0000ff))) /255.0, 0.0, 1.0);
//float to byte
i =((uint8_t)(255.0f *CLAMP(f, 0.0, 1.0)));
如果你没有CLAMP:
#define CLAMP(value, min, max) (((value) >(max)) ? (max) : (((value) <(min)) ? (min) : (value)))
或者对于全RGB:
integer_color =((uint8_t)(255.0f *CLAMP(float_color.r, 0.0, 1.0)) <<16) |
               ((uint8_t)(255.0f *CLAMP(float_color.g, 0.0, 1.0)) <<8) |
               ((uint8_t)(255.0f *CLAMP(float_color.b, 0.0, 1.0))) & 0xffffff;
float_color.r =CLAMP(((float)((integer_color &0xff0000) >>16)) /255.0, 0.0, 1.0);
float_color.g =CLAMP(((float)((integer_color &0x00ff00) >>8)) /255.0, 0.0, 1.0);
float_color.b =CLAMP(((float)((integer_color &0x0000ff))) /255.0, 0.0, 1.0);

wiusto

赞同来自:

为什么不尝试类似的东西

b=f*255.999
摆脱特殊情况f==1,但0.999仍然是255