GDI не удается преобразовать в индексированный цвет с точной палитрой? - PullRequest
3 голосов
/ 24 декабря 2009

Резюме

Используя Windows GDI для преобразования 24-битного цвета в индексированный, кажется, что GDI выбирает цвета, которые "достаточно близки", даже если в поставляемой палитре есть точные совпадения.

Кто-нибудь может подтвердить это как проблему GDI, или я где-то ошибаюсь?

Может быть, есть флаг "пожалуйста, проверьте всю палитру на соответствие цветов", который мне не удалось найти?

Примечание: это , а не о квантовании. Источник 24-битный, но содержит 256 или меньше цветов, поэтому точная палитра является тривиальным для вычисления. Проблема в том, что GDI не использует полную палитру.

Обход

Я обошел проблему, сопоставляя цвета самостоятельно, но я бы предпочел использовать GDI, так как он должен быть лучше оптимизирован. Проблема в том, что это «быстро, но неправильно».

Подробное описание

Мое исходное изображение 24-битное, но использует 256 (или менее) цветов. Я генерирую точную палитру для этого и прошу GDI перенести изображение в индексированное растровое изображение, используя эту палитру. Для некоторых пикселей GDI выбирает похожие, но не точные цвета, даже если в других местах палитры есть точные цвета. Это разрушает плавные градиенты.

Эта проблема возникает с:

  • SetDIBitsToDevice
  • StretchDIBits
  • BitBlt
  • StretchBlt

Проблема не возникает с:

  • SetPixel или SetPixelV в цикле (невероятно медленно!)
  • Использование моего собственного кода для сопоставления

Я проверял это на:

  • Windows 7 (аппаратное обеспечение / драйверы NVidia)
  • Windows Vista (аппаратное обеспечение / драйверы ATI)
  • Windows 2000 (оборудование / драйверы VMware)

В каждом тесте я получаю одинаковые результаты. (Не только неправильные цвета, но всегда одни и те же цвета.)

Я не думаю, что проблема заключается в управлении цветом (профили ICM / ICC и т. через заголовок растрового изображения V5, и я не думаю, что это применимо к моей виртуальной машине vanlilla-Win2k.

Тестовый проект

Код для простого тестового проекта Win32 / GDI / VS2008 можно найти здесь:

http://www.pretentiousname.com/data/GdiIndexColor.zip

Функция Test1 в Win32UI.cpp является фактическим тестом. У него есть два массива RGBQUAD, один - исходное изображение, а другой - точная палитра для него. Он проверяет, что палитра действительно точна, а затем просит GDI преобразовать изображение с помощью API, упомянутых выше, каждый раз проверяя результат. Для каждого теста он сообщит вам о первых неправильных пикселях цветов до и после или сообщит, что все пиксели верны, если он работает.

Спасибо!

Спасибо, что прочитали мой вопрос! Извините, если это результат того, что я сделал что-то действительно глупое! : -)

Ответы [ 3 ]

5 голосов
/ 12 ноября 2010

Я столкнулся с точно такой же проблемой, в конце концов связался с Microsoft и предоставил им контрольный пример. В тестовом примере я предоставил градиентное изображение, имеющее 128 цветов в 24-битном DIB, затем преобразовал его в 8-битный DIB, созданный с помощью таблицы цветов, содержащей все 128 цветов из 24-битного изображения. После преобразования 8-битное изображение использовало только 65 из 128 цветов.

Подводя итог их ответу: Это не ошибка, GDI использует достаточно точные вычисления при преобразовании глубины цвета изображения. На самом деле это нигде не задокументировано, и единственный способ обеспечить точное преобразование всех исходных цветов - это вручную манипулировать пикселями.

0 голосов
/ 29 декабря 2009

Я смутно помню, что вам также нужно вызвать RealizePalette(hdc) после выбора палитры в DC. Мы отказались от нашего кода палитры так давно, что его больше нет даже в нашем исходном дереве. По вашему коду я вижу, что вы уже пытались это сделать, но я полагаю, что вы, возможно, захотите поиграть с этим еще немного.

Я помню, что код палитры был довольно хрупким, и мы прекратили его использовать, как только смогли.

Некоторые старые AVI-файлы содержат 8-битное палитризованное видео с палитрой, встроенной в файл, поэтому при воспроизведении кода для этих файлов потребуется загрузить палитру. Я помню, что осознал, что ничего не делал, если вы не были приложением переднего плана, но это ДОЛЖНО применяться только к экранам DC, а не к памяти DC.

Если вы искали пример исходного кода, который может воспроизводить AVI в палитре, вы можете найти что-то, что показывает волшебную формулу для работы палитр.

Извините, я не могу больше помочь.

0 голосов
/ 27 декабря 2009

Используете ли вы SetDIBColorTable () ? Эта статья , по-видимому, подразумевает, что при рисовании в DIB недостаточно вызывать SelectPalette (), но необходимо также вызвать SetDIBColorTable () для установки палитры для DIB:

Однако, если приложение использует раздел DIB, вы создаете логический палитра из таблицы цветов DIB как обычно, а затем также передать DIB таблица цветов в разделе DIB с вызов к SetDIBColorTable (). Несмотря на что такое документация "Платформа SDK" RealizePalette (), по-видимому, подразумевает, RealizePalette () не корректирует таблица цветов секции DIB.

В этой статье содержится дополнительная информация о включении в палитры DIB, которые могут иметь отношение к делу (см. Раздел «Палитры и разделы DIB»).

...