Самый быстрый способ прочитать 3 байта по заданному адресу указателя?

В настоящее время я читаю пиксельные данные растрового изображения, используя BitmapData, доступный после блокировки растрового изображения. Метод, который я использую, читает каждый байт цвета отдельно и будет медленнее, чем чтение 4-байтового int непосредственно по заданному указателю. Но, к сожалению, мой битовый массив составляет 24 бит на пиксель, что означает, что на пиксель приходится 3 байта, а не 4. Так есть ли способ быстро прочитать всего 3 байта и преобразовать их в int по заданному адресу указателя?

// read pixel color
byte* Pix = (byte*)bmpScan0 + (y * bmpStride) + (x * 3);
byte R = *(Pix + 2);
byte G = *(Pix + 1);
byte B = *(Pix);
int RGB = ((int)R << 16) | ((int)G << 8) | (int)B;

person Robin Rodricks    schedule 26.02.2013    source источник
comment
@MitchWheat А, очень хорошее замечание; форматы пикселей растрового изображения повсюду, черт возьми, от конечности ...   -  person JerKimball    schedule 26.02.2013
comment
Ваш пример кода не совпадает с тем, что вы просите - он показывает чтение 3 байтов в отдельные переменные вместо int с маскировкой 8 старших бит ... Также рассмотрите возможность показать немного больше кода - тот, который у вас есть, похоже, делает много математических для получения следующего байта.   -  person Alexei Levenkov    schedule 26.02.2013
comment
@AlexeiLevenkov - Я обновил свой код, чтобы показать, чего мне нужно достичь.   -  person Robin Rodricks    schedule 26.02.2013
comment
Для меня не похоже на C #: P   -  person Corey    schedule 26.02.2013


Ответы (2)


Вместо нескольких операций - чтения, маскирования и т. Д. - вы можете прочитать полное int по адресу пикселя и замаскировать лишний байт.

int Pix = *(int*)((byte*)bmpScan0 + (y * bmpStride) + (x * 3)) & 0x00FFFFFF;

В зависимости от вашего порядка байтов вам может потребоваться сдвиг вниз вместо маскирования, и ваши цветовые компоненты могут быть перевернуты - BGR вместо RGB.

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

person Corey    schedule 26.02.2013
comment
+1. Я считаю, что это правильный подход (очевидно, вычисление текущего пикселя не требуется, поскольку +=3 должен двигаться следующим образом) ... Но @Geotarget уже отклонил этот подход в ответе JerKimball - поэтому неясно, что ищет OP. - person Alexei Levenkov; 26.02.2013
comment
OP отклонил ответ, потому что он не прочитал 3 байта с 1 строкой кода. Мне действительно не нужны были байты, разделенные на R / G / B. Я просто использовал его, потому что у меня не было другого выбора. - person Robin Rodricks; 26.02.2013
comment
@Geotarget - я подумал, что это было что-то в этом роде. - person Corey; 26.02.2013

Вы имеете в виду что-то вроде:

int foo = *(some pixel address in memory);
byte R = (byte)(foo & 0xff0000 >> 16);
byte G = (byte)(foo & 0x00ff00 >> 8);
byte B = (byte)(foo & 0xff);

Изменить: должен оставить этот ответ неотредактированным, чтобы сохранить преемственность в других комментариях, но больше не применим на основе изменений самого вопроса. :)

person JerKimball    schedule 26.02.2013
comment
Мой код уже быстрее, чем этот метод. Я ищу что-нибудь даже быстрее. - person Robin Rodricks; 26.02.2013