#c #bit-manipulation #bit
#c #битовые манипуляции #бит
Вопрос:
В конкретной графической библиотеке пиксели представлены 32-битными значениями, состоящими из четырех байтов для представления четырех компонентов: КРАСНОГО, ЗЕЛЕНОГО, СИНЕГО и альфа. Доступны следующие определения:
typedef unsigned int Uint32;
typedef unsigned char byte;
enum Color { RED = 0, GREEN = 1, BLUE = 2, ALPHA = 3 };
Теперь нужны две свободные функции:
Byte getColorComponent (Uint32 pixel, Color color);
которая посредством битовых манипуляций извлекает и возвращает значение одного из четырех цветовых компонентов, показанных в аргументе color;
и
void setColorComponent (Uint32 amp; pixel, Byte value, Color color);
которая принимает остановки в байтовом значении в нужном месте (в соответствии с аргументом color) в пикселе.
Ответ таков:
Byte getColorComponent(Uint32 pixel, Color color){ return (pixel >> (3-color)*8) amp; 0xFF; }
void setColorComponent(Uint32amp; pixel, Byte value, Color color){ pixel amp;= ~(0xFF << (3-color) * 8); pixel |= value << (3-color) * 8; }
Мне нужна помощь, чтобы понять ответ.
Ответ №1:
Хороший способ помочь разобраться с такого рода проблемами — использовать обычную ручку и бумагу. Выберите значения для одной или нескольких переменных, подставьте их внутри выражения. Продолжайте заменять вложенные выражения, пока не будет получен результат.
Подобно тому, как вы упрощаете математические выражения.
Например, с помощью getColorComponent
:
Выберите цвет
GREEN
(со значением1
).Выберите значение пикселя
0x8a2be200
(которое имеет непрозрачный сине-фиолетовый цвет, предполагающий RGBA).Исходное выражение
(pixel >> (3 - color) * 8) amp; 0xff
Цепочка подстановок
(0x8a2be200 >> (3 - 1) * 8) amp; 0xff
(0x8a2be200 >> 2 * 8) amp; 0xff
(0x8a2be200 >> 16) amp; 0xff
0x8a2b amp; 0xff
0x2b
С помощью color == GREEN
этого извлекается GREEN
цветовая составляющая 32-разрядного значения цвета RGBA.
Если вы используете любое из других значений перечисления цветов ( RED
, BLUE
или ALPHA
), делая то же самое, вы увидите, что он также извлекает эти компоненты из значения цвета RGBA.
Я оставляю это в качестве упражнения для читателей, чтобы использовать эту технику, чтобы выяснить, что setColorComponent
делает.
В качестве альтернативы, для использования с компьютерами и отладчиками, разбейте сложное выражение на его наименьшие подвыражения, присвоив результаты временным переменным. Затем используйте отладчик, чтобы пошагово просмотреть код построчно, чтобы увидеть, как объединяются результаты.
При этом выражение (pixel >> (3 - color) * 8) amp; 0xff
превратилось бы в инструкции
auto t1 = 3 - color; // 3 - color
auto t2 = t1 * 8; // (3 - color) * 8
auto t3 = pixel >> t2; // pixel >> (3 - color) * 8
auto t4 = t3 amp; 0xff; // (pixel >> (3 - color) * 8) amp;0xff