Исключение нулевого указателя при объединении двух растровых изображений

#android

#Android

Вопрос:

Я использую метод combine two Bitmap Images и записываю в SDCard . Приложение. отлично работает в эмуляторе, но когда я попытался выполнить in на реальном устройстве, оно проходит Null Pointer Exception по этой строке cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); , чтобы создать a new Bitmap , на котором я буду рисовать оба изображения, которые должны быть объединены с помощью Canvas .

Теперь, здесь в combineImages(Bitmap background, Bitmap foreground) первом аргументе находится Bitmap from Camera изображение и second is the forefround Gallery item . Растровое изображение, снятое с камеры, — это static Bitmap , я думаю, единственное, что вызывает у меня проблемы. Итак, может ли кто-нибудь дать мне хорошее решение для сохранения изображения, взятого из Camera temporary хранилища, чтобы у меня не возникало проблем с его дальнейшим использованием.

 public void combineImages(Bitmap background, Bitmap foreground) { 

        Bitmap cs = null;
        int width = 0, height = 0;
        width = background.getWidth();
        height = background.getHeight();
        cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas comboImage = new Canvas(cs);
        comboImage.drawBitmap(background, 0, 0, null);
        comboImage.drawBitmap(foreground, 100, 300, null);

        String tmpImg = String.valueOf(System.currentTimeMillis())   ".png";
        OutputStream os = null;
        try {
            os = new FileOutputStream(Environment.getExternalStorageDirectory()   File.separator   tmpImg);
            cs.compress(CompressFormat.PNG, 100, os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  

Вот мой вывод Logcat, когда я попробовал на реальном устройстве.(LG Optimus Black P-970)

 10-04 12:36:08.329: ERROR/AndroidRuntime(16356): FATAL EXCEPTION: main
10-04 12:36:08.329: ERROR/AndroidRuntime(16356): java.lang.NullPointerException
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.graphics.Bitmap.createBitmap(Bitmap.java:469)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at com.cam.GalleryImageSelected.combineImages(GalleryImageSelected.java:66)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at com.cam.GalleryImageSelected$1.onClick(GalleryImageSelected.java:90)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:874)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.widget.AdapterView.performItemClick(AdapterView.java:294)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.widget.ListView.performItemClick(ListView.java:3387)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:2408)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.os.Handler.handleCallback(Handler.java:587)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.os.Handler.dispatchMessage(Handler.java:92)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.os.Looper.loop(Looper.java:123)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at android.app.ActivityThread.main(ActivityThread.java:4627)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at java.lang.reflect.Method.invokeNative(Native Method)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at java.lang.reflect.Method.invoke(Method.java:521)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:876)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:634)
10-04 12:36:08.329: ERROR/AndroidRuntime(16356):     at dalvik.system.NativeStart.main(Native Method)
  

Комментарии:

1. Хорошо, могу ли я узнать причину отрицательного голосования?

2. Вы уверены, что ширина и высота в строке cs = Bitmap.CreateBitmap(ширина, высота, Bitmap.Config. ARGB_8888); больше 0. Просто не могу придумать другую ошибку в этой строке.

3. Да, потому что высота и ширина получены из снимка, сделанного камерой, поэтому очевидно, что они больше 0. Спасибо.

Ответ №1:

Я предполагаю, что проблема может заключаться в размере растрового изображения, которое вы создаете, делая снимок с камеры. Итак, лучше попробуйте использовать Bitmap.createScaledBitmap() метод.

 width = getWindowManager().getDefaultDisplay().getWidth();
height = getWindowManager().getDefaultDisplay().getHeight();

background = Bitmap.createScaledBitmap(background, width, height, true);
  

Это позволит масштабировать изображение в соответствии с высотой-шириной устройства по высоте-ширине. Надеюсь, это поможет.

Комментарии:

1. Спасибо, это сработало, проблема заключалась в том, что размер изображения превышал размер ширины высоты устройства…

Ответ №2:

В принципе, вы не можете получить исключение нулевого указателя в указанной вами строке, предполагая, что Bitmap реализован правильно:

 cs = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  

CreateBitmap является статическим.
Bitmap.Config.ARGB_8888 является статическим.
ширина, высота — целые числа.

Что может быть нулевым? Не могли бы вы опубликовать трассировку стека исключения? Вы уверены в строке?

Комментарии:

1. Пожалуйста, проверьте мой вывод Logcat, я получаю ошибку в строке 66, что я и указал.

2.Похоже на ошибку реализации в классе Bitmap API. Другие столкнулись с той же ошибкой: github.com/guardianproject/SecureSmartCam/issues/73 forum.xda-developers.com/showthread.php?t=613835 Это может быть проблема с памятью: при вызове собственного bitmap create недостаточно памяти, bitmap не создается и возвращается значение null. Класс Bitmap не проверяет, является ли возвращенное растровое изображение нулевым, и пытается установить некоторые параметры. Попробуйте изображение меньшего размера или попробуйте освободить память перед вызовом метода.

3. Я думаю, что наверняка есть какое-то решение. 🙁

4. Все методы CreateBitmap() полагаются на собственную реализацию для выделения памяти. Если метод createNative не может создать растровое изображение, я не могу представить обходной путь. Вы можете повторно использовать свои растровые объекты, например, использовать background или foreground для создания комбинации.

5. Вы также можете попробовать вызвать Bitmap.recycle(), когда вы больше не используете свое растровое изображение. Таким образом, освобождаются собственные выделения.