Значения растровых пикселей отличаются после setPixel () и getPixel () для одного и того же пикселя - PullRequest
2 голосов
/ 03 марта 2011

Я разрабатываю стеганографическое приложение для проекта класса, которое позволяет пользователю кодировать изображение секретного сообщения в другом изображении. Я использую Bitmap.getPixel(x,y) для получения информации о пикселях после изменения целочисленного значения пикселя, чтобы оно содержало значение сообщения. Затем я использовал Bitmap.setPixel(x,y), чтобы поместить измененный пиксель в растровое изображение. После декодирования изображения и получения скрытого сообщения я заметил, что некоторые пиксели были обесцвечены. Я обнаружил, что некоторые пиксели не содержат правильное значение после изменения. если я использую

int before = encoded_value;
bitmap.setPixel(x,y, before);
int after = bitamp.getPixel(x,y);

для большинства пикселей до == после, однако для некоторых до! = После. Если я непрерывно изменяю ранее, добавляя или вычитая один (это только слегка меняет цвет в изображении сообщения), а затем снова устанавливаю пиксель, значения до и после все еще различаются. Отключение нескольких пикселей в декодированном изображении не будет таким уж большим делом. Однако, когда один из проблемных пикселей обнаруживается там, где я закодировал информацию об изображении сообщения (размеры изображений), декодированные размеры обычно будут содержать нецифровое значение, такое как «2q3x300». Который будет через исключение, когда приложение пытается превратить эту строку в целочисленные значения. Я также пытался получить и установить пиксели, используя целочисленный буфер, однако те же пиксели вызывают проблемы. Также с помощью некоторой отладки я обнаружил, что определенные пиксели вызывают проблемы, а определенные значения вызывают проблемы, если я кодирую изображение с помощью строки удвоенного размера «213213x300300», строка из которой декодируется как «2q32q3x300300». Я не уверен, если это проблема, которая начинается при декодировании растрового изображения из файла изображения или это ошибка в методах getPixel () и setPixel (). Кажется, что некоторые пиксели немного отключают. В вышеприведенном примере 1 (который содержит значение ascii 49 или 00110001) декодируется как q (который содержит значение ascii 113 или 01110001), только одно битовое значение отличается от набора и получения, однако это может вызвать проблемы с битами. Растровое изображение находится в ARGB_8888 и, следовательно, должно содержать любое значение, которое также может содержаться в целочисленном значении. Чтобы стереография работала, я модифицирую как минимум 2 бита значений альфа, красного, зеленого и синего, чтобы сохранить 1 байт. Я уменьшаю изображение сообщения до RGB_332, чтобы оно могло содержаться в наименьшем количестве битов. Еще один пример - попытка установить пиксель -53029643.

I put           -53029643 = 1111 1100 1101 0110 1101 0100 1111 0101
and get returns -53029387 = 1111 1100 1101 0110 1101 0101 1111 0101
                ----------------------------------------------------XOR
                          = 0000 0000 0000 0000 0000 0001 0000 0000 = 256 

Хотя эти два значения отличаются только младшим битом от значения зеленого цвета. Декодирование этого целочисленного значения путем взятия по меньшей мере 2 битов из каждого бита дает 00100101 вместо 00100001, байты имеют форму RRRGGGBB, таким образом, значение зеленого цвета изменяется с 000 на 001, и результирующая битовая карта будет содержать пиксель со значением зеленого цвета, равным 001000 вместо 000000, поскольку декодированная битовая карта находится в RGB_565, и поэтому десятичное значение от зеленого равно 8 вместо 0. Здесь 3 PNG-изображения: первое - изображение-носитель (изображение, в которое закодировано изображение сообщения), второе это изображение сообщения (изображение, которое закодировано в изображении носителя), а третье - это изображение сообщения после того, как оно было декодировано из изображения носителя.

изображение носителя

carrier image

сообщение image

message image

декодированное изображение сообщения. Это изображение в 8-битном цвете, пиксели, которые являются более красными или зелеными, являются теми, на которых влияет эта ошибка.

decoded message

Ответы [ 4 ]

1 голос
/ 06 мая 2011

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

нефильтрованное

unfiltered

1010 * фильтруют *

filtered

1 голос
/ 18 июля 2012

Это очень похоже на проблему, которая возникла, когда (только на некоторых устройствах) растровые изображения, загруженные из папки drawables, будут слегка изменены.Я решил это, поместив растровые изображения в папку «raw» (например, res \ raw).Надеюсь, это поможет.

0 голосов
/ 28 сентября 2017

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

Кроме того, я сообщил об этой ошибке в Google.

0 голосов
/ 03 марта 2011

Ваш битовый массив, вероятно, настроен как 565, то есть 5 бит для красного, 6 для зеленого, 5 для синего. Таким образом, вы можете иметь только 32 различных значения для красного / синего и 64 для зеленого.

Если вам нужна большая точность, вам нужно создать растровое изображение 8888.

Пример:

Bitmap bitmap = Bitmap.createBitmap(128, 128, Bitmap.Config.ARGB_8888);
...