使用 NDK 从本机内存恢复图像会返回无显示的黑色图像 [英] Restoring the image from Native Memory using NDK returns Black Image with No display

查看:12
本文介绍了使用 NDK 从本机内存恢复图像会返回无显示的黑色图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从本机内存中恢复图像(使用 NDK、C/C++),但这会返回一个黑色图像.

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

我在做什么 ::

  • 1)从Drawable中获取图片
  • 2) 对图像应用旋转
  • 3)旋转后对图像应用灰度效果
  • 4)最后我尝试将灰度图像保存在 SD 卡中

  • 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

对于上述所有步骤,我指的是 this 很棒的库,它具有本地存储方法并恢复图像.

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

请注意图像存储在 SD 卡中,但是当我尝试查看图像时,它完全是黑色的,根本没有显示.

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.

我的 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 相同的方法存储和恢复图像).

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

将图像保存到 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;
        }
}

在谷歌搜索时,我发现(可能是我错了)返回本地内存的图像具有 ALPHA_8 位图配置,因此我将配置 ALPHA_8 t0 ARGB_8888 转换,但结果相同.

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.

位图从 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 方法和实现以找到问题.

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.

提前致谢....

编辑 ::

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.

推荐答案

好的,我发现了多个问题和改进提示:

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

  • 第一个 createBitmap 在旋转的位图上以 width*height 运行,而不是 height*width.这应该是:

  • 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);

  • 保存文件时,您没有得到正确的路径(您使用的是硬编码路径,Lint 会发出警告).

  • when saving file you don't get the correct path (you use a hardcoded path, and Lint warns about it).

    jniConvertToGray 不需要遍历数组,只需使用指针即可,因为它只在单个像素上运行.您将位图两次而不是一次存储到 JNI 中(只需执行:存储、旋转、灰度、恢复和免费).

    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.

    您已经对 bitmapWip 进行了旋转和灰度化处理.为什么要新建一个包含内容的位图,在上面做灰度,然后保存?

    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.

    最后,最重要的是:您使用 ALPHA_8 来显示您需要保存到文件的图像.这个配置没有颜色.这是一个面具.为了查看问题,您应该为 imageView 设置背景颜色:

    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...

    如果您在开发的任何阶段成功地将图像保存到文件中并认为它是黑色图像(但大小不为 0),请尝试对其进行编辑并在其后面添加背景.也许你很幸运,只是得到了透明像素......

    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...

    将文件保存为不支持透明度的 jpg 格式这一事实也可能导致意外行为.

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

    为了解决这个问题,您应该使用我使用过的相同技术 - 始终使用单个位图.没必要创造那么多.Java 世界中应该只存在一个,并且应该支持有颜色.

    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.

    这篇关于使用 NDK 从本机内存恢复图像会返回无显示的黑色图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆