Изменение цвета растрового изображения при сжатии в png - PullRequest
2 голосов
/ 27 февраля 2011

В настоящее время я работаю над приложением Steganogrpahy для Android в качестве проекта класса. Я создал объект, который будет кодировать изображение с другим изображением и возвращать закодированное растровое изображение. Этот код запускается в отдельном потоке.

new Thread(new Runnable()  
{  
   public void run()  
    {  
        Bitmap encoded_image = null;  
        Encryptor encryptor = new Encryptor();  
        encoded_image = encryptor.encode_image_in_image(  
            image_location,message_image_location);  
    }  
}).start();

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

private void pass_image_to_file_browser( Bitmap image )
{
    Intent intent = new Intent(Encrypt.this,FileBrowser.class);
    intent.putExtra( Intent.EXTRA_STREAM, image );
    startActivity( intent );
}

@Override
 public void onCreate(Bundle savedInstanceState) 
 {
    super.onCreate(savedInstanceState);
    Bundle bundle = this.getIntent().getExtras();
    Bitmap image = bundle.getParacable(Intent.EXTRA_STREAM);
 }

Я предполагал, что большое растровое изображение должно быть слишком большим для отправки между действиями с использованием намерения, поэтому я решил просто сохранить изображение во временном местоположении и передать местоположение изображения в вспомогательное действие. Который затем сохраняет изображение PNG, где пользователь указывает и удаляет временный файл изображения.

private void save_bitmap( Bitmap image, String location )
{
    FileOutputStream fileOutputStream = new FileOutputStream(location);
    BufferedOutputStream buffered_output_stream = new 
        BufferOutputStream(fileOutputStream);
    image.compress(CompressFormat.PNG, 0, buffered_output_stream);
    buffered_output_stream.flush();
    buffered_output_stream.close();
}

Это решает проблему отправки большого растрового изображения от одного действия к другому, однако, создало новую проблему, которую я не смог решить. Как временное изображение, которое сохраняется перед передачей местоположения файла в вспомогательное действие, так и файл изображения после повторного сохранения изображения с помощью файлового браузера, у обоих слегка изменился цвет. Это изменение цвета неузнаваемо невооруженным глазом, но при декодировании изображения вызывает много проблем. У меня была одна мысль, что Bitmap.Config меняется с ARGB_8888 на ARGB_4444 или RGB_565, однако после отладки это не так. Растровое изображение создается как ARGB_8888 и сохраняется как растровое изображение ARGB_8888 и никогда не изменяется между ними. Код по-прежнему работает, если я передаю все растровое изображение в файловый браузер и сохраняю растровые изображения одинаково в обоих местах. У меня нет никаких мыслей о том, что еще может быть причиной этого. Я ищу предложения о том, что еще может быть причиной проблемы. Извините, что я собирался публиковать изображения на выходе в обоих случаях, однако переполнение стека не позволило бы мне на моем уровне репутации. Спасибо.

1 Ответ

6 голосов
/ 01 марта 2011

Хорошо, после многих долгих потраченных часов, волнующихся о потоке и алгоритме, который я использовал для кодирования растрового изображения, проблема стала немного проще.При декодировании файла изображения, который должен был быть закодирован сообщением, которое я использовал options.inPreferredConfig = Config.ARGB_8888; Во время отладки я проверял, чтобы убедиться, что это не изменилось на RGB_565.Хотя объект растрового изображения был загружен как ARBG_8888, файл изображения не содержал альфа-канал и, таким образом, хотя растровое изображение содержало байт для уровня альфа и позволяло мне редактировать альфа-байт пикселя до Bitmap.setPixel( x, y, color) объект растрового изображенияпризнал, что у него были установлены альфа-значения.При сжатии растрового изображения, сжатого до RGB_565, так как объект думал, что не было альфа-канала.Каким-то образом эта проблема была решена путем передачи растрового изображения в дочернее действие и его анализа.Я предполагаю, что когда объект воссоздается, альфа-значения, которые я установил, были распознаны.Чтобы решить проблему без передачи растрового изображения в субактивность, необходимо добавить альфа-канал после декодирования растрового изображения из файла.Я нашел функцию для этого здесь .

private Bitmap adjustOpacity( Bitmap bitmap )
{
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    int[] pixels = new int[width * height];
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    dest.setPixels(pixels, 0, width, 0, 0, width, height);
    return dest;
} 

Я не уверен, есть ли более эффективный метод

...