Отображение 16-битной серой шкалы в 8-битную в PNG - PullRequest
2 голосов
/ 05 апреля 2019

Я пытаюсь декодировать PNG в C # с 16 битами на канал (бит / канал) для изображения в градациях серого.Я полагаю, что я декодирую правильные необработанные значения, однако, когда я преобразовываю в 8bpc для возвращаемых значений, я не вычисляю те же значения, что и System.Drawing, Gimp или SixLabors.ImageSharp.

Учитывая следующие значения байтов:один пиксель в градациях серого:

byte b0 = data[index];
byte b1 = data[index + 1];

Я пробовал следующие сопоставления:

byte result = b0;
byte result = (byte)(255 * (((b0 << 8) + b1)/ushort.MaxValue));
byte result = (byte)(((b0 << 8) + b1)/256.0);

Но ни один из этих подходов не соответствует значениям из другого программного обеспечения, предсказанным для следующих значений:

b0   b1   expected
55   186  55
67   135  67
35   241  36

Я уверен, что неправильно понимаю правильный метод нормализации до значения 8 бит / с.

Это изображение выглядит так:

A 16 by 16 pixel Grayscale image with 16 bpc

1 Ответ

1 голос
/ 06 апреля 2019

Вот официальный метод преобразования битовой глубины:

https://www.w3.org/TR/2003/REC-PNG-20031110/#13Sample-depth-rescaling

output = floor((input * MAXOUTSAMPLE / MAXINSAMPLE) + 0.5)

where

MAXINSAMPLE = (2^sampledepth)-1
MAXOUTSAMPLE = (2^desired_sampledepth)-1

Так что, если я возьму ваш последний пример:

35 << 8 | 241 == 8960 | 241 == 9201
9201 * 255 / 65535 == 2346255 / 65535 == 35
floor(35 + 0.5) == 35

Почему бы не 36?

Возможно, здесь задействована гамма .

Вывод:

Сначала проверьте, правильно ли ваша внутренняя реализация соответствует спецификациям, затем отрегулируйте соответствующим образом.

https://www.w3.org/TR/2003/REC-PNG-20031110/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...