#java #image-processing #binary #bitwise-operators
#java #обработка изображений #двоичный #побитовые операторы
Вопрос:
Я не знаком с побитовыми операциями. Это алгоритм обработки изображений. Что происходит?
void binarize50(int pixels[]) {
for(int i = 0; i < pixels.length; i ) {
int gray = ((pixels[i] amp; 0xff) ((pixels[i] amp; 0xff00) >> 8) ((pixels[i] amp; 0xff0000) >> 16)) / 3;
pixels[i] = gray < 128 ? 0xff000000 : 0xffffffff;
}
}
Я обнаружил, что (pixels [i] amp; 0xff) просто каким-то образом «нормализуется» и позволяет пикселю / байту становиться положительным значением между 0..255.
Что делает (pixels[i] amp; 0xff00 >> 8) ?
Что такое 0xff00? И почему, если серый <128, пиксель становится 0xff000000 или иначе 0xffffffff?
Ответ №1:
Операция amp; с 0xff
и т.п. применяет битовую маску. Это побитовая операция and . Поскольку int в Java является 32-разрядным, вы можете читать 0xff
as 00000000_00000000_00000000_11111111
, 0xff00
as 00000000_00000000_11111111_00000000
и так далее. Они просто опускают начальные нули.
Итак, если вы это сделаете pixels[i] amp; 0xff
, произойдет то, что вы получите int, последние 8 бит которого совпадают с пикселями [i], а остальные равны нулю.
>>
Оператор — это сдвиг вправо. Это сдвинет битовый шаблон вправо на указанное количество битов. Если b
бы содержался 00110011_11001100_00010110_01001100
, и вы это сделали b >> 8
, вы бы получили 00000000_00110011_11001100_00010110
. Последние 8 бит «выпали», в то время как нули влево были сдвинуты. Я не помню, сдвинется ли эта операция на 1 влево, если начальный бит равен 1, поэтому, возможно, кто-то может подтвердить или опровергнуть это.
Зная это, давайте взглянем на эту строку:
int gray = ((pixels[i] amp; 0xff) ((pixels[i] amp; 0xff00) >> 8) ((pixels[i] amp; 0xff0000) >> 16)) / 3;
Здесь происходит то, что мы создаем int следующим образом (не точный порядок выполнения кода, просто для иллюстрации):
- пиксели [i] маскируются, поэтому сохраняются только последние 8 бит, остальные становятся 0.
- пиксели [i] маскируются, поэтому сохраняются только биты 8-15 (считая справа налево, начиная с 0), остальные становятся 0. Затем этот результат сдвигается на 8 бит вправо. Если бы мы начали с 00001111_00001111_10101010_00110011, это привело бы к 00000000_00000000_00000000_10101010 .
- пиксели [i] маскируются, поэтому сохраняются только биты 16-23, затем сдвигаются на 16 бит вправо.
- результаты вышеуказанных трех операций добавляются и…
- этот результат делится на 3.
Итак, что это дает? Ну, в основном это сводится к тому, что первые 8 бит пикселей [i] игнорируются, а следующие 3 секции по 8 бит каждая интерпретируются как одно значение от 0 до 255, из которого берется среднее значение.
Затем этот результат проверяется на 128. Если значение меньше, для пикселей [i] i устанавливается значение 0xff000000, в противном случае для него устанавливается значение 0xffffffff.
Это типичное изменение битов, с которым вы сталкиваетесь при операциях с цветами, закодированными как целые числа. Вероятно, это схема argb, где первые 8 битов int — это альфа (прозрачность), следующие 8 битов — красные, следующие 8 — зеленые, а последние 8 битов — синие. Или его вариант. 0xff000000 будет полностью непрозрачным черным, а 0xffffffff — полностью непрозрачным белым.
Комментарии:
1. 1, отличный ответ! для тех, кто не так много знает о побитовых операциях! 🙂
Ответ №2:
То, что он делает, зависит от цветовой модели и того, как цвета представлены в памяти.
Я предполагаю, что он превращает обычное изображение ARGB в черно-белое изображение на основе порога 50%. (Все пиксели с «яркостью» менее 50% становятся полностью черными, а все остальные — полностью белыми.)
Что
(pixels[i] amp; 0xff00 >> 8)
делает?
pixel[i]
вы уже знаете 🙂amp; ff00
маскирует биты во втором байте>> 8
сдвигает биты вправо на восемь позиций (т. Е. Делает самый правый байт выпадающим из ребра)
Что такое
0xff00
?
0xff00 — это шестнадцатеричный литерал для значения 65280 (или 1111111100000000 в двоичном формате)
И почему, если серый <128, пиксель становится 0xff000000 или иначе 0xffffffff?
Эта строка:
int gray = ((pixels[i] amp; 0xff)
((pixels[i] amp; 0xff00) >> 8)
((pixels[i] amp; 0xff0000) >> 16)) / 3;
добавляет upp красный, зеленый и синий компоненты и делит его на три (находит среднее значение).
Эта строка
pixels[i] = gray < 128 ? 0xff000000 : 0xffffffff;
предположительно, говорится, что если серость меньше половины, пиксель должен быть полностью черным, в противном случае он должен быть полностью белым.
Комментарии:
1. 1: 0xff000000 означает, что он черный и непрозрачный, если предположить, что его формат ARGB вместо формата RGB.
Ответ №3:
(пиксели [i] amp; 0xff) = значение синего цвета от 0 до 255
(пиксели [i] amp; 0xff00) >> 8 = зеленое значение от 0 до 255
(пиксели [i] amp; 0xff0000) >> 16) = красное значение от 0 до 255
Затем вы берете среднее из 3 значений, найденных выше.
После этого, в зависимости от серости, сделайте его белым или черным, т. Е. Менее 50% серого — это черное, остальное белое.
Ответ №4:
(pixels[i] amp; 0xff00) >> 8
берет второй байт из int, который представляет зеленый цвет — amp;
делает все биты, кроме 8-15 нулевыми, и >>
сдвигает их на 8 бит вправо, поэтому, если число равно (в битах) 0101000100001100:
0101000100001100 amp; 0xff = 0101000100001100 amp; 1111111100000000 = 0101000100000000.
0101000100000000 >> 8 = 01010001
То же самое для ((pixels[i] amp; 0xff0000) >> 16)
.
Нет, вы берете их среднее значение ( /3
) и получаете, ближе ли цвет к белому или черному ( gray < 128
) . В соответствии с этим вы либо делаете пиксель черным, либо белым.
Ответ №5:
0xFF00 это битовая маска означает 1111111100000000 в двоичном представлении.
Итак, когда вы применяете эту маску к числу, вы оставляете более высокие 8 бит.
Оператор >> означает сдвиг вправо. Например, 11110000 >> 2 = 00111100