Резюме
Используя 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, упомянутых выше, каждый раз проверяя результат. Для каждого теста он сообщит вам о первых неправильных пикселях цветов до и после или сообщит, что все пиксели верны, если он работает.
Спасибо!
Спасибо, что прочитали мой вопрос! Извините, если это результат того, что я сделал что-то действительно глупое! : -)