Получение RGB из образа WIC C++

Я использую WIC для загрузки изображения, а затем хочу получить значения RGB для каждого пикселя. Я дошел до использования getDataPointer() для создания байтового буфера (который я приводил к массиву COLORREF), но после этого все становится странным.

У меня есть 10x10 24bit PNG, с которым я тестирую. Если я смотрю на значение размера, то getDataPointer() дает мне сообщение, что это 300, что имеет смысл, потому что 10 * 10 * 3 (для 3 байтов на пиксель) = 300. Если я получаю getStride(), это дает мне 30, что также делает смысл.

Поэтому я создаю цикл, чтобы пройти через COLORREF с итератором, и условие i потому что я знаю, что в массиве всего 100 пикселей. Затем я использую макросы GetRValue (), GetGValue () и GetBValue(), чтобы получить значения rgb.

Это когда дела идут странно - мое маленькое изображение - это просто тестовое изображение со сплошными красными, зелеными, синими и черными пикселями, но мои значения RGB выходят (255, 0, 0), (0, 255, 0), (27, 255, 36), (0, 0, 0) и т. Д. Кажется, что некоторые значения не получаются должным образом и как-то искажены. Кроме того, последние 20/30 пикселей изображения - это либо сумасшедшие цвета, либо весь черный, что заставляет меня думать, что это какая-то порча.

Я также проверил это с более крупной реальной фотографией, и это выдает все оттенки серого и повторяет один и тот же шаблон, заставляя меня думать, что это - проблема шага, но я не понимаю как, потому что когда я вызываю getPixelFormat(), WIC говорит, что это 24bppBGR или 24bppRGB в зависимости от изображения.

Кто-нибудь знает, что я делаю не так? Разве я не должен использовать COLORREF и макросы или что-то подобное?

Спасибо за ваше время.

РЕДАКТИРОВАТЬ

Хм, у меня все еще есть проблема. Я попытался с другим 24-битным PNG, который PixelFormat () сообщал как 24bppBGR, но кажется, что шаг выключен или что-то в этом роде, потому что он рисует как перекошенный (обязательный тест nyan cat):

Проверьте нагрузку WIC с нянькой, но шаг выключен

РЕДАКТИРОВАТЬ 2

Хорошо, теперь, кажется, у меня есть некоторые, которые работают, а некоторые нет. Некоторые сообщают, что они работают как BGR 24bpp, в то время как другие выглядят как на картинке выше, и если я вычислю шаг, он даст мне сравнение с тем, что должно быть, они отличаются, а также размер буфера также отличается. У меня также есть некоторые изображения BGR 32bpp, и некоторые из них работают, а другие нет. Я что-то здесь упускаю? Что может составить дополнительные байты в буфере?

Вот пример изображения:

24bppBGR JPEG:

width = 126
height = 79
buffer size = 30018
stride = 380

Если я вычислю это:

buffer size should be: width * height * 3 = 126 * 79 * 3 = 29862
difference between calculation and actual buffer size: 30018 - 29862 = 156 bytes

stride size should be: width * 3 = 378
difference between calculation and actual buffer size: 380 - 378 = 2 bytes

I was thinking that we had 2 extra bytes per line but 79 * 2 is 158 not 156 hmm.

Если я сделаю эти вычисления для изображений, которые работали до сих пор, я не найду никакой разницы в вычислениях и значениях, которые код дает мне...

Понимаю ли я, что здесь происходит неправильно? Должны ли эти расчеты работать так, как я думал?

еще раз спасибо

1 ответ

Вы не должны использовать COLORREF и связанные макросы. COLORREF - это 4-байтовый тип, и у вас есть 3-байтовые пиксели. Доступ к данным в виде массива значений COLORREF не будет работать. Вместо этого вам следует обращаться к нему как к массиву байтов, каждый пиксель которого расположен в ((x + y * width) * 3). Порядок отдельных каналов указывается названием формата. Так что если это 24bppBGR, вы бы сделали data[(x + y * width) * 3], чтобы получить синий канал, data[(x + y * width) * 3 + 1] для зеленого и data [(x + y) * ширина) * 3 + 2] для красного.

Если вам действительно нужен массив пикселей, вы можете создать структуру с 3 полями BYTE, но, поскольку значение этих полей зависит от формата пикселя, это может оказаться бесполезным.

Фактически, вы не можете предполагать, что произвольное изображение будет загружаться как 24-битный формат вообще. Количество форматов, которые вы можете получить, больше, чем вы могли бы ожидать, чтобы поддерживать.

Вместо этого вы должны использовать WICConvertBitmapSource для преобразования данных в формат, с которым вы можете работать. Если вы предпочитаете работать с массивом COLORREF и связанными макросами, используйте GUID_WICPixelFormat32bppBGR.

Другие вопросы по тегам