Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

android - Restoring the image from Native Memory using NDK returns Black Image with No display

I am trying to restore the image from Native memory (using NDK,C/C++) but that returns me an Black Image.

What i am doing ::

  • 1)get the image from Drawable
  • 2)apply the rotation to the image
  • 3)After rotation apply the grayscale effect to the image
  • 4)At the end i am trying to save the grayscale image in SD Card

    For all the above steps, i am referring this awesome lib,which have the native method to store and restore the images.

Please note image is being stored in the SD card but when i am trying to see the image,its totally black with no display at all.

My Java Implementation ::

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;
        }
}

I have not make any changes in native method(means using the same method as this lib have for storing and restoring the image).

Saving image to SD Card ::

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;
        }
}

While googling, i found that(may be i am wrong) image which returns for Native Memory have the ALPHA_8 bitmap config,so i convert the config ALPHA_8 t0 ARGB_8888,but the result is same.

Conversion of bitmap from ALPHA_8 to 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 funcation ::

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

I have no clue about where i was wrong. i have checked the lib methods and implmentation again and again to find the issue.

I have spent my many hours on this small issue and it really frustrating me. Let me know please if you need anything else from my side. Please help me to resolve this issue.

Many Thanks in 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);
     }

I have followed your suggestion/steps but the result is same,getting black image with no display.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

ok I've found multiple problems and tips for improvements:

  • the first createBitmap is run with width*height on a bitmap that got rotated instead of height*width. this should be as:

    rotateBitmap(90,_handler);
    tempBmp=getBitmapAndFree();
    bitmapWip=Bitmap.createBitmap(bitmapOrig.getHeight(),bitmapOrig.getWidth(),Config.ALPHA_8);
    
  • when saving file you don't get the correct path (you use a hardcoded path, and Lint warns about it).

  • jniConvertToGray doesn't really need to go over arrays and can just use a pointer, as it just runs on a single pixel. you store the bitmap into JNI twice instead of once (just do: store, rotate, grayscale, restore&free).

  • you don't use the new bitmap after you have finished working on it, so if I call rotation multiple times, it doesn't seem to do anything.

  • you already have bitmapWip rotated and grayscaled. why do you need to make a new bitmap that has its content in it, do a grayscale on it, and then save it ?

  • functions should be named with lowercase letter in the beginning of their names.

  • and finally , the most important thing: you use ALPHA_8 for the image that you show and need to save to file. this configuration has no color. it's a mask. In order to see the problem, you should set a background color to the imageView :

    ivDisplay.setBackgroundColor(0xFFff0000);
    

    before choosing the rotation, you see nothing red. after choosing it, everything you think is white, has actually become red. that's because it's transparent...

    If in any phase of your development you've succeeded saving the image to a file and thought it's a black image (yet the size is not 0) , try to edit it and put a background behind it. Maybe you got lucky and just got transparent pixels...

    Adding the fact that you save the file to a jpg format, which doesn't support transparency, might also contribute to unexpected behaviors.

    in order to solve this, you should use the same technique i've used - use a single bitmap all the time. no need to create so many. only one should exist on the java world, and it should support having colors.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...