Что этот метод Java делает с побитовыми операциями?

#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