Восстановление изображения из Native Memory с помощью NDK возвращает черное изображение без дисплея

Я пытаюсь восстановить изображение из Native memory (используя NDK, C/С++), но возвращает черное изображение.

Что я делаю:

  • 1) получить изображение из Drawable
  • 2) примените поворот к изображению
  • 3) После поворота примените эффект серого к изображению
  • 4) В конце я пытаюсь сохранить изображение в оттенках серого на SD-карте

    Для всех вышеперечисленных шагов я обращаюсь к this awesome lib, которые имеют собственный метод для хранения и восстановления изображений.

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

Моя реализация Java:

public boolean onOptionsItemSelected(MenuItem item) 
{
        switch (item.getItemId())
        {
        case R.id.item_rotate_90:
            options.inPreferredConfig = Config.ARGB_8888;
            bitmapOrig = BitmapFactory.decodeResource(this.getResources(), R.drawable.sample_cam,options);
            storeBitmap(bitmapOrig);
            bitmapOrig.recycle();
            rotateBitmap(90,_handler);
            tempBmp=getBitmapAndFree();

            bitmapWip = Bitmap.createBitmap(bitmapOrig.getWidth(),bitmapOrig.getHeight(),Config.ALPHA_8);
            jniConvertToGray(tempBmp,bitmapWip);

            if(bitmapWip!=null)
            {
                try 
                {
                    Bitmap b = Bitmap.createBitmap(bitmapWip.getWidth(),bitmapWip.getHeight(),Bitmap.Config.ARGB_8888);
                    Canvas c = new Canvas(b);
                    Paint paint = new Paint();
                    ColorMatrix cm = new ColorMatrix();
                    ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
                    paint.setColorFilter(f);
                    c.drawBitmap(bitmapWip, 0, 0, paint);

                    storeBitmap(b);
                    SaveGrayScaledImage(b);
                    b.recycle();
                    tempBmp.recycle();

                } catch (IOException e) {
                    e.printStackTrace();
                }
                ivDisplay.setImageBitmap(bitmapWip);
            }
            break;
        }
}

Я не вносил никаких изменений в собственный метод (означает использование того же метода, что и this lib для хранения и восстановления изображения).

Сохранение изображения на SD-карте::

private void SaveGrayScaledImage(Bitmap finalBitmap)throws IOException 
{
        String imageFileName = "Temp" + "_gray";
        File albumF = new File("/mnt/sdcard/","gray_img");
        if(!albumF.exists())
        {
            albumF.mkdirs();
        }
        // File imageF = File.createTempFile(imageFileName, JPEG_FILE_SUFFIX,
        // albumF);
        File imageF = new File(albumF,imageFileName + ".jpeg");

        if (imageF.exists()) {
            imageF.delete();
            imageF.createNewFile();
        }
        try {
            FileOutputStream out = new FileOutputStream(imageF);
            finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            imageF = null;
        }
}

В то время как googling, я обнаружил, что (возможно, я ошибаюсь) изображение, которое возвращает для Native Memory, имеет конфигурацию bitmap ALPHA_8, поэтому я конвертирую конфигурацию ALPHA_8 t0 ARGB_8888, но результат такой же.

Преобразование растрового изображения из ALPHA_8 в ARGB_8888::

Bitmap b = Bitmap.createBitmap(bitmapWip.getWidth(),bitmapWip.getHeight(),Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bitmapWip, 0, 0, paint);

Функциональность StoreBimap::

public void storeBitmap(final Bitmap bitmap)
{
    if(_handler!=null)
        freeBitmap();
    _handler=jniStoreBitmapData(bitmap);
}

Я не знаю, где я был неправ. Я снова и снова проверял методы lib и импликацию, чтобы найти проблему.

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

Большое спасибо в Advance....

EDIT::

bitmapHolder=new JniBitmapHolder();
    final Options options=new Options();
    BitmapFactory.decodeFile(picPath, options);
    options.inJustDecodeBounds=true;
             options.inPreferredConfig=Config.ARGB_8888;
             prepareForDownsampling(options,192,256);
             System.gc();
             bmpGrayscale=BitmapFactory.decodeFile(picPath,options);
             int width = bmpGrayscale.getWidth();
             int height = bmpGrayscale.getHeight();
             bitmapHolder.storeBitmap(bmpGrayscale);
             bmpGrayscale.recycle();


   Bitmap thumbnail = null;
   int rotationInDegrees = 0;
   if (picPath != null) {
    Uri uri = Uri.parse(picPath);
    ExifInterface exif = null;
    try {
     exif = new ExifInterface(uri.getPath());
    } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }

    int rotation = exif.getAttributeInt(
      ExifInterface.TAG_ORIENTATION,
      ExifInterface.ORIENTATION_NORMAL);

    rotationInDegrees = exifToDegrees(rotation);
   }

   rotationInDegrees = 90;


    ByteBuffer _handler =null;
    switch(rotationInDegrees)
               {
               case 90:
                 bitmapHolder.rotateBitmapCw90();
                 break;
               case 180:
                 bitmapHolder.rotateBitmap180();
                 break;

               }



    Bitmap bitmapWip = Bitmap.createBitmap(width,height,Config.ALPHA_8);
    bitmapHolder.bitmapGrayScale(bitmapWip);

     if(bitmapWip!=null){
      File CurrentFile = saveGrayScaledIamge(bitmapWip,
        takePhotoFile);
     }

Я следил за вашими предложениями/шагами, но результат тот же, получив черное изображение без дисплея.

Ответ 1

ok Я нашел несколько проблем и советов по улучшению:

  • первый createBitmap запускается с шириной * height на растровом изображении, которое получило поворот вместо высоты * ширины. это должно быть как:

    rotateBitmap(90,_handler);
    tempBmp=getBitmapAndFree();
    bitmapWip=Bitmap.createBitmap(bitmapOrig.getHeight(),bitmapOrig.getWidth(),Config.ALPHA_8);
    
  • при сохранении файла вы не получите правильный путь (вы используете жесткий путь, и Lint предупреждает об этом).

  • jniConvertToGray действительно не нужно перебирать массивы и может просто использовать указатель, поскольку он просто работает на одном пикселе. вы храните битмап в JNI два раза, а не один раз (просто выполните: сохранение, поворот, оттенки серого, восстановление и свободный).

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

  • у вас уже есть растровое изображение с растровым и серого. почему вам нужно создать новый растровый рисунок, в котором есть его содержимое, сделать оттенки серого на нем, а затем сохранить его?

  • функции должны быть названы строчной буквой в начале их имен.

  • и, наконец, самое главное: вы используете ALPHA_8 для изображения, которое вы показываете и которое нужно сохранить в файл. эта конфигурация не имеет цвета. это маска. Чтобы увидеть проблему, вы должны установить цвет фона для изображения:

    ivDisplay.setBackgroundColor(0xFFff0000);
    

    перед выбором вращения, вы не видите ничего красного. после выбора, все, что вы считаете белым, на самом деле стало красным. что он прозрачен...

    Если на любой стадии вашего развития вам удалось сохранить изображение в файл и подумать, что это черное изображение (но размер не равен 0), попробуйте отредактировать его и поместить за ним фоновый рисунок. Может быть, вам повезло и просто получили прозрачные пиксели...

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

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