Android — Понимание кода ImageProcessing

Я новичок в Android ndk. Я начал учиться на примере обработки изображений
гам а также блогом IBM. Я не получаю несколько строк ниже. Может ли кто-нибудь помочь мне понять фрагмент кода? `

static void brightness(AndroidBitmapInfo* info, void* pixels, float brightnessValue){
int xx, yy, red, green, blue;
uint32_t* line;

for(yy = 0; yy < info->height; yy++){
line = (uint32_t*)pixels;
for(xx =0; xx < info->width; xx++){//extract the RGB values from the pixel
red     = (int) ((line[xx] & 0x00FF0000) >> 16);
green   = (int)((line[xx] & 0x0000FF00) >> 8);
blue    = (int) (line[xx] & 0x00000FF );

//manipulate each value
red = rgb_clamp((int)(red * brightnessValue));
green = rgb_clamp((int)(green * brightnessValue));
blue = rgb_clamp((int)(blue * brightnessValue));

// set the new pixel back in
line[xx] =
((red << 16) & 0x00FF0000) |
((green << 8) & 0x0000FF00) |
(blue & 0x000000FF);
}

pixels = (char*)pixels + info->stride;
}
}
`
static int rgb_clamp(int value) {
if(value > 255) {
return 255;
}
if(value < 0) {
return 0;
}
return value;
}

Как извлекается значение RGB и что делает этот rgb_clamp. Почему мы возвращаем новый пиксель и как пиксели = (символ *) пиксели + информация-> шаг вперед; работает?
Я не с / с ++ ребята и не очень разбираюсь в обработке изображений.
Спасибо

1

Решение

Сначала поговорим об одном пикселе. Насколько я могу видеть, это композиция, по крайней мере, из 3 каналов: r, g и b, которые все хранятся в одном uint32_t значение и имеет формат 0x00RRGGBB (32 бита / 4 канала = 8 бит на канал и, следовательно, диапазон значений от 0..255). Итак, чтобы получить разделенные значения r, g и b, вам нужно их замаскировать, что делается в трех строках ниже //extract the RGB values, Например, красный компонент … С маской 0x00FF0000 и & оператор, вы устанавливаете каждый бит на 0, кроме битов, которые установлены в красном канале. Но когда вы просто маскируете их 0x00RRGGBB & 0x00FF0000 = 0x00RR0000Вы бы получили очень большое число. Чтобы получить значение от 0 до 255, вы также должны сдвинуть биты вправо, и это то, что делается с помощью >>-оператором. Итак, для последнего примера: после применения маски вы получаете 0x00RR0000 и сдвигаете это 16-битное значение вправо (>> 16)дает тебе 0x000000RRэто число от 0 до 255. То же самое происходит с зеленым каналом, но с 8-битным сдвигом вправо, и поскольку значение синего уже находится в «правильной» позиции бита, сдвигать не нужно.

Второй вопрос: что rgb_clamp Это легко объяснить. Это гарантирует, что ваши значения r, g или b, умноженные на коэффициент яркости, никогда не превышают диапазон значений 0..255.

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

После обработки одной строки вашего изображения info->stride добавлено, поскольку в целях оптимизации память, вероятно, выровнена, чтобы заполнить 32-байтовые границы, и, таким образом, одна строка может быть длиннее, чем только ширина изображения, и, таким образом, «остаток» байтов добавляется к указателю.

4

Другие решения

Прежде всего, я предлагаю вам прочитать книгу C здесь: http://publications.gbdirect.co.uk/c_book/

Далее я рассмотрю ваши вопросы.

  1. Как извлекаются значения RGB

    line устанавливается для указания на параметр пикселей:

    line = (uint32_t*)pixels;

    То есть pixels является массивом 32-битных целых чисел без знака

    Затем для высоты и ширины растрового изображения значения RGB извлекаются с использованием комбинации побитового ANDing (&) и немного смещается вправо (>>).

    Давайте посмотрим, как вы получаете красный:

    red = (int) ((line[xx] & 0x00FF0000) >> 16);

    Здесь мы получаем текущую строку, а затем И с 0x00FF0000 как маска, это получает биты 24-16 от line, Поэтому, используя в качестве примера код RGB # 123456, мы останемся с 0x00120000 в red переменная. Но он все еще находится в позиции 24-16 бит, поэтому мы сдвигаем вправо 16 бит, чтобы сдвинуть биты вниз до 0x00000012,

    Мы делаем это для зеленого и синего значений, корректируя маску AND и количество битов, чтобы сместить вправо.

    Более подробную информацию о двоичной арифметике можно найти здесь: http://publications.gbdirect.co.uk/c_book/chapter2/expressions_and_arithmetic.html

  2. Что значит rgb_clamp делать

    Эта функция просто гарантирует, что значения красного, зеленого или синего цвета равны 0 или выше или 255 и ниже.

    Если параметр для rbg_clamp Если -20, то он вернет 0, который будет использоваться для установки значения RGB. Если параметр rbg_clamp 270 это вернет 255.

    Значения RGB для каждого цвета не должны превышать 225 или быть ниже 0. В этом примере 255 является самым ярким, а 0 — самым темным значением.

  3. Почему мы устанавливаем пиксель обратно

    Похоже, мы меняем яркость пикселя и возвращаем значение, готовое к отображению.

  4. Как pixels = (char*)pixels + info->stride; Работа?

    Не зная структуры info переменная AndroidBitmapInfo типа, я бы догадался info->stride относится к ширине растрового изображения в байтах, так line станет следующей строкой на следующей итерации цикла.

надеюсь, это поможет

2