如何避免内存不足而前旋转图像?而前、图像、内存不足

2023-09-07 10:21:11 作者:对方网络不佳

public static boolean rotateBitmapByExifAndSave(File targetFile){

  if (targetFile==null || !targetFile.exists() || !targetFile.canRead() || !targetFile.canWrite())
      return false;

    boolean isSucceed = false;
    // detect if photo is need to be rotated
    try {
        final Matrix matrix = new Matrix();

        ExifInterface exifReader = new ExifInterface(targetFile.getAbsolutePath());

        int orientation = exifReader.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
        boolean isRotationNeeded = true;

        switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_90:
            matrix.postRotate(90);
            break;

        case ExifInterface.ORIENTATION_ROTATE_180:
            matrix.postRotate(180);
            break;

        case ExifInterface.ORIENTATION_ROTATE_270:
            matrix.postRotate(270);
            break;

        default: // ExifInterface.ORIENTATION_NORMAL
            // Do nothing. The original image is fine.
            isRotationNeeded = false;
            isSucceed = true;
            break;
        }

        if (isRotationNeeded){
            BitmapFactory.Options bmfOtions = new BitmapFactory.Options();
            Bitmap bitmap = null;
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(targetFile);
                bitmap = BitmapFactory.decodeStream(fileInputStream,null,bmfOtions);
            } catch (FileNotFoundException e){
                isSucceed = false;
            }
            finally {
                if (fileInputStream != null)
                    try {
                        fileInputStream.close();
                    } catch (IOException e) {}
            }
            if (bitmap!=null){
                bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                isSucceed = ImageUtils.saveBitmapToFile(bitmap, targetFile, 100);
                bitmap.recycle();
            }
        }

    } catch (IOException e) {
        Log.e("ImageUtils", e);
    } catch (Exception e) {
        // like there is no EXIF support?
        Log.e("ImageUtils", e);
    } catch (Throwable e) {
        // stupid Out of VM's memory
        Log.e("ImageUtils", e.toString());
    }

    return isSucceed; 
}

我用这个方法来旋转原始照片通过设备的摄像头进行。如今的相机可能会大于8MPix(三星Galaxy S4拥有13万像素的摄像头)。甚至更少万象素摄像头(我的是 5 MP ,2592 x 1944像素这ARGB_888的结合,根据官方的文档需要的 19MB 的RAM),我已经得到了内存不足。所以,问题是如何旋转照片不会丢失它的初始分辨率,因此品质?

I use this method to rotate original photos made by device's camera. Nowadays camera could be bigger than 8MPix (Samsung Galaxy S4 has 13 Mega pixel camera). And even with less MPix camera (mine is 5 MP, 2592 x 1944 pixels which in conjunction of ARGB_888 takes 19Mb of RAM according to official docs) I already got OutOfMemory. So the question is how to rotate the photo WITHOUT loss of it's initial resolution and thus quality?

推荐答案

由于没有答案,我认为是没有答案也许我刚才问的问题有点不正确。它看起来像唯一的选择,这里是to提高了应用程序的堆大小 更新: 还有另一种选择 - 通过NDK / JNI像here或者使用 Android的图片,魔术LIB 。该图像魔术LIB是pretty的冷静,旋转图像你需要的是:

Since there was no answer I assume there is no answer or maybe I just had asked the question a bit incorrectly. It looks like the only option here is to increase the app's heap size UPDATE: There is also another option - to work with bitmaps via NDK/JNI like here or to use Android Image-Magic lib. The Image Magic lib is pretty cool, to rotate an image all you need is:

ImageInfo imageInfo = new ImageInfo(imageFile.getAbsolutePath());
MagickImage magickImage = new MagickImage(imageInfo);
magickImage.setCompression(100); // to minimize loss
magickImage.rotateImage(90.0f).writeImage(imageInfo);

MagickImage有许多其他的图像操作选项,以及。模糊,磨砂,规模,木炭等等。但是它的库的大小是noticable。作者做了伟大的工作,他们涵盖了所有可能的plaforms:arm64-V8A,armeabi,armeabi-V7A,MIPS,MIPS64,X86,x86_64的,所有这些库的最终大小超过36MB。所以,你应该将所有的库成一个APK,也许使用的包装清单通过芯片组来过滤/平台是正确的方式6个不同的版本,之前的想法。 更新 另一种选择是转换不可变的位图到可变(包位图转换为MappedByteBuffer)

MagickImage has many other image manipulating options as well. Blur, matte, scale, charcoal and many more. However its libraries size is noticable. Authors made a great job and they covered all possible plaforms: arm64-v8a, armeabi, armeabi-v7a, mips, mips64, x86, x86_64 and final size of all these libs is over 36Mb. So you should think before adding all the libs into one apk, maybe packaging 6 different versions using manifest to filter by chipset/platform is the right way. UPDATE Another option is to convert Immutable Bitmap into Mutable (wrap bitmaps into MappedByteBuffer)