【问题标题】:Getting Thumbnails from sdcard with URI使用 URI 从 sdcard 获取缩略图
【发布时间】:2012-07-02 16:00:10
【问题描述】:

如何使用给定的 URI 从 sdcard 中获取缩略图? 我曾尝试使用 bitmapfactory,但性能不佳或 OutOfMemoryError 我将把缩略图放到包含大量数据的列表视图中 我应该使用缩略图或任何建议吗? 如果要使用缩略图,那么该怎么做...?

提前感谢您的帮助

【问题讨论】:

标签: android image listview uri thumbnails


【解决方案1】:

可以通过以下方法获取图片的缩略图:

private Bitmap getBitmap(String path) {

    Uri uri = getImageUri(path);
    InputStream in = null;
    try {
        final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
        in = mContentResolver.openInputStream(uri);

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(in, null, o);
        in.close();



        int scale = 1;
        while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) {
            scale++;
        }
        Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth       + ", orig-height: " + o.outHeight);

        Bitmap b = null;
        in = mContentResolver.openInputStream(uri);
        if (scale > 1) {
            scale--;
            // scale to max possible inSampleSize that still yields an image
            // larger than target
            o = new BitmapFactory.Options();
            o.inSampleSize = scale;
            b = BitmapFactory.decodeStream(in, null, o);

            // resize to desired dimensions
            int height = b.getHeight();
            int width = b.getWidth();
            Log.d(TAG, "1th scale operation dimenions - width: " + width    + ", height: " + height);

            double y = Math.sqrt(IMAGE_MAX_SIZE
                    / (((double) width) / height));
            double x = (y / height) * width;

            Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x,     (int) y, true);
            b.recycle();
            b = scaledBitmap;

            System.gc();
        } else {
            b = BitmapFactory.decodeStream(in);
        }
        in.close();

        Log.d(TAG, "bitmap size - width: " +b.getWidth() + ", height: " + b.getHeight());
        return b;
    } catch (IOException e) {
        Log.e(TAG, e.getMessage(),e);
        return null;
    }
}

并且在使用位图后总是调用 bitmap.recycle() 方法。它将从内存中清除位图。还要避免代码中的内存泄漏。这将解决您的 OOME。

【讨论】:

  • 编码工作,但即使在我的列表视图中有 10 个项目,滚动也不是那么流畅。我已将 IMAGE MAX SIZE 设置为 100,但仍未解决性能问题。哦,我在我的自定义适配器上使用了回收,得到了runtime exception : canvas trying to use a recycled bitmap
  • 在回收之前检查 if(bitmap != null)。你用的是哪个安卓版本?如果是 3.0 及以上版本,则为 xml 中的 listView 提供 hardwareAccelerated = true
【解决方案2】:
 // Parameters
 int w,h;     

 // First only decode image size
 BitmapFactory.Options opt = new BitmapFactory.Options();
 opt.inJustDecodeBounds = true;
 Bitmap bmp = BitmapFactory.decodeFile(file, opt);

 // Decode small enough image
 int heightRatio = (int)opt.outHeight/h;
 int widthRatio = (int)opt.outWidth/w;
 if (heightRatio > 1 || widthRatio > 1)
 {
      if (heightRatio > widthRatio)
           opt.inSampleSize = heightRatio;
      else
           opt.inSampleSize = widthRatio; 
 }

 opt.inJustDecodeBounds = false;
 bmp = BitmapFactory.decodeFile(file, opt);

【讨论】:

  • 感谢您的回答,顺便说一句,我已经尝试过您的编码,加载速度比我以前的代码快,但是列表视图的滚动不流畅。
【解决方案3】:

使用ThumbnailUtils 类获取图像/视频的缩略图。

【讨论】:

    【解决方案4】:

    尝试使用此代码,它修复了内存不足错误。将高度和宽度更改为您的。这里intent_data2是文件路径。

    public Bitmap custom_SizedImage(String intent_data2) {
            int targetHeight = 534, targetWidth = 534;
            Options options = new Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(intent_data2, options);
            double sampleSize = 0;
            Boolean scaleByHeight = Math.abs(options.outHeight - targetHeight) >= Math
                    .abs(options.outWidth - targetWidth);
    
            if (options.outHeight * options.outWidth * 2 >= 1638) {
                sampleSize = scaleByHeight ? options.outHeight / targetHeight
                        : options.outWidth / targetWidth;
                sampleSize = (int) Math.pow(2d,
                        Math.floor(Math.log(sampleSize) / Math.log(2d)));
            }
            options.inJustDecodeBounds = false;
            options.inTempStorage = new byte[128];
            while (true) {
                try {
                    options.inSampleSize = (int) sampleSize;
                    mBitmap = BitmapFactory.decodeFile(intent_data2, options);
                    Display display = getWindowManager().getDefaultDisplay();
                    int width = display.getWidth();
                    int height = display.getHeight();
                    int screenDiff = height - width;
                    int screenRatio = screenDiff / 3;
                    float scaleFactor = mBitmap.getWidth() / width;
                    float y_Pos = scaleFactor * screenRatio;
                    Matrix matrix = new Matrix();
                    matrix.postScale(0.5f, 0.5f);
                    croppedBitmap = Bitmap.createBitmap(mBitmap, 0, (int) y_Pos,
                            mBitmap.getWidth(), mBitmap.getWidth(), matrix, true);
    
                    scaledBitmap = Bitmap.createBitmap(targetWidth, targetHeight,
                            Config.RGB_565);
    
                    float ratioX = targetWidth / (float) croppedBitmap.getWidth();
                    float ratioY = targetHeight / (float) croppedBitmap.getHeight();
                    float middleX = targetWidth / 2.0f;
                    float middleY = targetHeight / 2.0f;
    
                    Matrix scaleMatrix = new Matrix();
                    scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
    
                    Canvas canvas = new Canvas(scaledBitmap);
                    canvas.setMatrix(scaleMatrix);
                    canvas.drawBitmap(croppedBitmap,
                            middleX - croppedBitmap.getWidth() / 2, middleY
                                    - croppedBitmap.getHeight() / 2, new Paint(
                                    Paint.FILTER_BITMAP_FLAG));
                    //saveImage(scaledBitmap);
    
                    break;
                } catch (Exception ex) {
                    try {
                        sampleSize = sampleSize * 2;
                    } catch (Exception ex1) {
    
                    }
                }
            }
            return scaledBitmap;
    

    }

    【讨论】:

    • 如果您想保存图像,请使用该方法,否则请评论它。
    猜你喜欢
    • 2017-10-21
    • 2015-08-25
    • 2019-12-19
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 2010-11-24
    相关资源
    最近更新 更多