Я всегда делал round(f * 255.0)
.
Нет необходимости в тестировании (особый случай для 1) и / или в других ответах. Является ли это желательным ответом для ваших целей, зависит от того, насколько ваша цель состоит в том, чтобы максимально приблизить входные значения [моя формула] или разделить каждый компонент на 256 равных интервалов [другие формулы].
Возможным недостатком моей формулы является то, что интервалы 0 и 255 имеют только половину ширины других интервалов. За годы использования я еще не видел каких-либо визуальных доказательств того, что это плохо. Наоборот, я обнаружил, что предпочтительнее не попадать ни в одну из крайностей, пока вход не будет достаточно близок к этому - но это вопрос вкуса.
Возможный плюс в том, что [я считаю] относительные значения компонентов R-G-B (немного) более точны для более широкого диапазона входных значений.
Хотя я не пытался это доказать, это мое интуитивное чувство, учитывая, что для каждого компонента, который я округляю, получаем максимально близкое доступное целое число. (Например, я считаю, что если цвет имеет G ~ = 2 x R, эта формула будет чаще оставаться близкой к этому соотношению; хотя разница довольно мала, и есть много других цветов, с которыми формула 256
справляется лучше. Так что это может быть стирка.)
На практике подходы на основе 256
или 255
, по-видимому, дают хорошие результаты.
Другой способ оценить 255
против 256
, это изучить другое направление -
преобразование из байта 0..255 в число с плавающей запятой 0.0..1.0.
Формула, которая преобразует целочисленные значения 0..255 в равноотстоящие значения в диапазоне 0.0..1.0:
f = b / 255.0
В этом направлении не возникает вопроса, использовать ли 255
или 256
: приведенная выше формула равна формуле, которая дает результаты с равным интервалом. Обратите внимание, что он использует 255
.
Чтобы понять связь между формулами 255
в двух направлениях, рассмотрим эту диаграмму, если у вас было только 2 бита, поэтому значения целочисленные значения 0..3:
Диаграмма с использованием 3
для двух битов, аналогично 255
для 8 битов. Преобразование может быть сверху вниз или снизу вверх:
0 --|-- 1 --|-- 2 --|-- 3
0 --|--1/3--|--2/3--|-- 0
1/6 1/2 5/6
|
- это границы между 4 диапазонами. Обратите внимание, что внутри значения с плавающей точкой и целочисленные значения находятся в середине их диапазонов. Обратите внимание, что интервал между всеми значениями является постоянным в обоих представлениях.
Если вы поймете эти диаграммы, вы поймете, почему я предпочитаю формулы на основе 255
перед формулами на основе 256
.
Заявка : Если вы используете / 255.0
при переходе от байт для перемещения, но вы не используете round(f * 255.0)
при переходе к байт float, , тогда увеличивается ошибка "среднего прохождения" . Подробности следуют.
Это легче всего измерить, начиная с числа с плавающей точкой, идущего до байта, затем обратно до числа с плавающей точкой. Для простого анализа используйте 2-битные диаграммы «0..3».
Начните с большого числа значений с плавающей запятой, равномерно распределенных от 0,0 до 1,0.
В оба конца все эти значения будут сгруппированы по значениям 4
.
Диаграмма имеет 6 диапазонов полуинтервалов:
0..1 / 6, 1 / 6..1 / 3, .., 5 / 6..1
Для каждого диапазона средняя ошибка приема-передачи составляет половину диапазона, поэтому 1/12
(минимальная ошибка равна нулю, максимальная ошибка равна 1/6, равномерно распределена).
Все диапазоны дают ту же ошибку; 1/12
- общая средняя ошибка при приеме в оба конца.
Если вместо этого вы используете какую-либо из формул * 256
или * 255.999
, большинство результатов приема-передачи одинаковы, но некоторые перемещаются в соседний диапазон.
Любое изменение в другом диапазоне увеличивает ошибку ; например, если ошибка для одного входа с плавающей запятой ранее была немного меньше , чем 1/6, возвращение центра соседнего диапазона приводит к ошибке немного больше , чем 1/6. Например. 0,18 в оптимальной формуле => байт 1 => число с плавающей запятой 1/3 ~ = 0,333, для ошибки | 0.33-0.18|
= 0.147
; используя 256
формула => байт 0 => с плавающей запятой 0, для ошибки 0.18
, которая является увеличением от оптимальной ошибки 0.147
.
Диаграммы с использованием * 4
с / 3
. Преобразование из одной строки в другую.
Обратите внимание на неровный интервал в первой строке: 0..3 / 8, 3 / 8..5 / 8, 5 / 8..1. Эти расстояния 3/8, 2/8, 3/8.
Обратите внимание, что границы интервала последней строки отличаются от первой строки.
0------|--3/8--|--5/8--|------0
1/4 1/2 3/4
=> 0------|-- 1 --|-- 2 --|------3
=> 0----|---1/3---|---2/3---|----0
1/6 1/2 5/6
Единственный способ избежать этой увеличенной ошибки - использовать другую формулу при переходе от байта к числу с плавающей точкой. Если вы сильно верите в одну из формул 256
, то я оставлю вам выбор оптимальной обратной формулы.
(В байтовом значении он должен возвращать среднюю точку значений с плавающей запятой, которые стали этим байтовым значением. За исключением от 0 до 0 и от 3 до 1. Или, возможно, от 0 до 1/8, от 3 до 7/8! На приведенной выше диаграмме это должен перенести вас из средней линии обратно в верхнюю.)
Но теперь у вас возникнет сложная для защиты ситуация, когда вы взяли одинаково расположенные байтовые значения и преобразовали их в неравно расположенные значения с плавающей точкой.
Это ваши параметры, если вы используете любое значение, отличное от 255
, для целых чисел 0..255: либо увеличение средней ошибки приема-передачи, либо неравномерно распределенные значения в области с плавающей запятой .