草庐IT

android - 在没有 OutOfMemoryError 或缩小比例的情况下在 Android 中旋转图像

coder 2023-12-06 原文

基本上,我试图在 Android 应用程序中旋转位图(来自图像)。我想这样做的原因是,即使是垂直拍摄的,从相机拍摄的照片(通过 Intent )也会水平显示,并且方向作为元数据保留在图像上。有错请指正。然而,问题是图像加载时会占用大量内存,如果是在手机上用相当好的相机拍摄的,我还没有找到一种方法来旋转和保存它而不会有 OutOfMemoryError 的风险.下面的代码是我:

  1. 载入图片
  2. 检查是否需要旋转
  3. 加载缩小版本以在 ImageView 中显示
  4. 必要时旋转小图像
  5. 在一个单独的线程中;加载、旋转和保存图像,这样以后就不需要了

应用程序保持图像的分辨率很重要,但欢迎使用任何编码技巧。我已经在互联网上搜索了几天,除了我已经实现的内容之外找不到任何东西。这里有关于这个主题的另一个线程,但似乎没有任何解决方案。希望你能帮上忙。

    public Bitmap getBitmap(final Context c) {
    if (bitmap != null)
        return bitmap;

    final int rotate = necessaryRotation(c, file);
    // if(rotate != 0) rotateImageFile(c, rotate);

    try {
        // Get scaled version
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file, options);
        options.inSampleSize = calcInSampleSize(options, 1024, 1024);
        options.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeFile(file, options);

        // rotate?
        bitmap = rotateImage(c,bitmap,rotate);

        System.out.println("Bitmap loaded from file: size="
                + bitmap.getWidth() + "," + bitmap.getHeight());

        System.gc();
    } catch (Exception e) {
        System.err.println("Unable to load image file: "
                + this.getFilename());
    }

    // if rotation is needed, do it in worker thread for next time
    if(rotate != 0){
        Thread t = new Thread(new Runnable(){

            public void run() {
                // load entire image
                try{
                    File imageFile = new File(getFilename());
                    Bitmap huge = Media.getBitmap(c.getContentResolver(),
                    Uri.fromFile(imageFile));

                    huge = rotateImage(c,huge,rotate);

                    // save bitmap properly
                    FileOutputStream out = new FileOutputStream(imageFile);
                    huge.compress(Bitmap.CompressFormat.PNG, 100, out);

                    out.flush();
                    out.close();
                    huge.recycle();
                    huge = null;
                    out = null;
                    System.gc();

                }catch(IOException e){
                    e.printStackTrace();
                }
            }

        });
        t.start();
    }

    return bitmap;
}

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) {
    if (rotate != 0) {
        // rotate
        Matrix m = new Matrix();
        m.postRotate(rotate);
        Bitmap rotImage = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), m, true);
        bitmap.recycle();

        System.out.println("Image (id=" + getId()
                + ") rotated successfully");

        System.gc();

        return rotImage;
    }
    return bitmap;
}

private int necessaryRotation(Context c, String imageFile) {
    int rotate = 0;
    ExifInterface exif;
    try {
        exif = new ExifInterface(imageFile);
        int orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);

        switch (orientation) {
        case ExifInterface.ORIENTATION_ROTATE_270:
            rotate = 270;
            break;
        case ExifInterface.ORIENTATION_ROTATE_180:
            rotate = 180;
            break;
        case ExifInterface.ORIENTATION_ROTATE_90:
            rotate = 90;
            break;
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return rotate;
}

private int calcInSampleSize(BitmapFactory.Options options, int reqWidth,
        int reqHeight) {
    int height = options.outHeight;
    int width = options.outWidth;
    int inSampleSize = 1;
    while (height > reqHeight || width > reqWidth) {
        height /= 2;
        width /= 2;
        inSampleSize *= 2;
    }

    return inSampleSize;
}

如果有任何您需要了解的信息或有任何我可以用来减少内存使用的优化,请写信:)谢谢

最佳答案

试试这个 fragment :

private Bitmap rotateImage(Context c, Bitmap bitmap, int rotate) {
    ....

    // reduce byte per pixel
    bitmap = bitmap.copy(Bitmap.Config.RGB_565, false);

    Bitmap.createBitmap(bitmap,...
}

关于android - 在没有 OutOfMemoryError 或缩小比例的情况下在 Android 中旋转图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11145650/

有关android - 在没有 OutOfMemoryError 或缩小比例的情况下在 Android 中旋转图像的更多相关文章

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  3. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. 没有类的 Ruby 方法? - 2

    大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow

  6. ruby - 在不使用 RVM 的情况下在 Mac 上卸载和升级 Ruby - 2

    我最近决定从我的系统中卸载RVM。在thispage提出的一些论点说服我:实际上,我的决定是,我根本不想担心Ruby的多个版本。我只想使用1.9.2-p290版本而不用担心其他任何事情。但是,当我在我的Mac上运行ruby--version时,它告诉我我的版本是1.8.7。我四处寻找如何简单地从我的Mac上卸载这个Ruby,但奇怪的是我没有找到任何东西。似乎唯一想卸载Ruby的人运行linux,而使用Mac的每个人都推荐RVM。如何从我的Mac上卸载Ruby1.8.7?我想升级到1.9.2-p290版本,并且我希望我的系统上只有一个版本。 最佳答案

  7. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  8. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  9. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  10. ruby - 没有类方法获取 Ruby 类名 - 2

    如何在Ruby中获取BasicObject实例的类名?例如,假设我有这个:classMyObjectSystem我怎样才能使这段代码成功?编辑:我发现Object的实例方法class被定义为returnrb_class_real(CLASS_OF(obj));。有什么方法可以从Ruby中使用它? 最佳答案 我花了一些时间研究irb并想出了这个:classBasicObjectdefclassklass=class这将为任何从BasicObject继承的对象提供一个#class您可以调用的方法。编辑评论中要求的进一步解释:假设你有对象

随机推荐