本文介绍了使用 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

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

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 在旋转的位图上以宽度*高度运行,而不是高度*宽度.这应该是:

  • 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 从本机内存恢复图像返回无显示的黑色图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 08-23 09:49