代码之家  ›  专栏  ›  技术社区  ›  d-man

android如何创建运行时缩略图

  •  61
  • d-man  · 技术社区  · 14 年前

    我有一个大尺寸的图像。在运行时,我想从存储器中读取图像并对其进行缩放,以使其重量和大小减小,并将其用作缩略图。当用户单击缩略图时,我想显示完整大小的图像。

    9 回复  |  直到 7 年前
        1
  •  44
  •   kakopappa    13 年前

    我的解决方案

    byte[] imageData = null;
    
            try     
            {
    
                final int THUMBNAIL_SIZE = 64;
    
                FileInputStream fis = new FileInputStream(fileName);
                Bitmap imageBitmap = BitmapFactory.decodeStream(fis);
    
                imageBitmap = Bitmap.createScaledBitmap(imageBitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
    
                ByteArrayOutputStream baos = new ByteArrayOutputStream();  
                imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                imageData = baos.toByteArray();
    
            }
            catch(Exception ex) {
    
            }
    
        2
  •  126
  •   Vishnu    11 年前

    试试这个

    Bitmap ThumbImage = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(imagePath), THUMBSIZE, THUMBSIZE);
    

    此实用程序可从API U级别8获得。 [Source]

        3
  •  12
  •   Massimo    7 年前

    我找到的最好的解决办法如下。与其他解决方案相比,该方案不需要加载完整的图像来创建缩略图,因此效率更高! 它的限制是你不能有一个精确宽度和高度的缩略图 但解决办法尽可能接近。

    File file = ...; // the image file
    Options bitmapOptions = new Options();
    
    bitmapOptions.inJustDecodeBounds = true; // obtain the size of the image, without loading it in memory
    BitmapFactory.decodeFile(file.getAbsolutePath(), bitmapOptions);
    
    // find the best scaling factor for the desired dimensions
    int desiredWidth = 400;
    int desiredHeight = 300;
    float widthScale = (float)bitmapOptions.outWidth/desiredWidth;
    float heightScale = (float)bitmapOptions.outHeight/desiredHeight;
    float scale = Math.min(widthScale, heightScale);
    
    int sampleSize = 1;
    while (sampleSize < scale) {
        sampleSize *= 2;
    }
    bitmapOptions.inSampleSize = sampleSize; // this value must be a power of 2,
                                             // this is why you can not have an image scaled as you would like
    bitmapOptions.inJustDecodeBounds = false; // now we want to load the image
    
    // Let's load just the part of the image necessary for creating the thumbnail, not the whole image
    Bitmap thumbnail = BitmapFactory.decodeFile(file.getAbsolutePath(), bitmapOptions);
    
    // Save the thumbnail
    File thumbnailFile = ...;
    FileOutputStream fos = new FileOutputStream(thumbnailFile);
    thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, fos);
    fos.flush();
    fos.close();
    
    // Use the thumbail on an ImageView or recycle it!
    thumbnail.recycle();
    
        4
  •  9
  •   charles young    13 年前

    下面是一个更完整的解决方案,可以将位图缩小到缩略图大小。它在bitmap.createScaledBitmap解决方案上展开,方法是保持图像的纵横比,并将其填充到相同的宽度,以便在ListView中看起来很好。

    另外,最好只进行一次缩放,并将结果位图作为blob存储在sqlite数据库中。为此,我提供了一个关于如何将位图转换为字节数组的片段。

    public static final int THUMBNAIL_HEIGHT = 48;
    public static final int THUMBNAIL_WIDTH = 66;
    
    imageBitmap = BitmapFactory.decodeByteArray(mImageData, 0, mImageData.length);
    Float width  = new Float(imageBitmap.getWidth());
    Float height = new Float(imageBitmap.getHeight());
    Float ratio = width/height;
    imageBitmap = Bitmap.createScaledBitmap(imageBitmap, (int)(THUMBNAIL_HEIGHT*ratio), THUMBNAIL_HEIGHT, false);
    
    int padding = (THUMBNAIL_WIDTH - imageBitmap.getWidth())/2;
    imageView.setPadding(padding, 0, padding, 0);
    imageView.setImageBitmap(imageBitmap);
    
    
    
    ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
    byte[] byteArray = baos.toByteArray();
    
        5
  •  6
  •   Vasily Kabunov Yashvir yadav    7 年前

    使用 BitmapFactory.decodeFile(...) 得到你的 Bitmap 对象并将其设置为 ImageView 具有 ImageView.setImageBitmap() .

    图片框 将布局尺寸设置为较小的值,例如:

    android:layout_width="66dip" android:layout_height="48dip"
    

    添加一个 onClickListener 图片框 并启动一个新活动,在该活动中使用

    android:layout_width="wrap_content" android:layout_height="wrap_content"
    

    或者指定更大的尺寸。

        6
  •  3
  •   user1546570    12 年前
    /**
     * Creates a centered bitmap of the desired size.
     *
     * @param source original bitmap source
     * @param width targeted width
     * @param height targeted height
     * @param options options used during thumbnail extraction
     */
    public static Bitmap extractThumbnail(
            Bitmap source, int width, int height, int options) {
        if (source == null) {
            return null;
        }
    
        float scale;
        if (source.getWidth() < source.getHeight()) {
            scale = width / (float) source.getWidth();
        } else {
            scale = height / (float) source.getHeight();
        }
        Matrix matrix = new Matrix();
        matrix.setScale(scale, scale);
        Bitmap thumbnail = transform(matrix, source, width, height,
                OPTIONS_SCALE_UP | options);
        return thumbnail;
    }
    
        7
  •  1
  •   Sushin Pv    7 年前

    我找到了一个简单的方法

    Bitmap thumbnail = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(mPath),200,200)
    

    句法

    Bitmap thumbnail = ThumbnailUtils.extractThumbnail(Bitmap source,int width,int height)
    

    利用毕加索的依赖性

    编译“com.squareup.picasso:picasso:2.5.2”

    Picasso.with(context)
        .load("file:///android_asset/DvpvklR.png")
        .resize(50, 50)
        .into(imageView2);
    

    参考文献 Picasso

        8
  •  0
  •   S.M.Mousavi    8 年前

    如果您想要高质量的结果,那么使用[RapidDecoder][1]库。简单如下:

    import rapid.decoder.BitmapDecoder;
    ...
    Bitmap bitmap = BitmapDecoder.from(getResources(), R.drawable.image)
                                 .scale(width, height)
                                 .useBuiltInDecoder(true)
                                 .decode();
    

    如果你想缩小到50%以下并得到一个总部结果,别忘了使用内置解码器。

        9
  •  0
  •   Mir-Ismaili    7 年前

    这个答案是基于 https://developer.android.com/topic/performance/graphics/load-bitmap.html (不使用外部库)我做了一些修改,使其功能更好、更实用。

    关于此解决方案的一些注意事项:

    1. 假设你想 保持纵横比 . 换句话说:

      finalWidth / finalHeight == sourceBitmap.getWidth() / sourceBitmap.getWidth() (不考虑铸造和圆整问题)

    2. 假设有两个值( maxWidth 和; maxHeight ) 你想要 任何一个 最终位图的尺寸不超过其相应的值 . 换句话说:

      finalWidth <= maxWidth && finalHeight <= maxHeight

      所以 minRatio 作为计算的基础(参见实现)。 不同于 maxRatio 作为实际计算的基础 . 另外,计算 inSampleSize 已经好多了(逻辑性更强,简洁高效)。

    3. 假设 您希望(至少)最终维度之一 确切地 其对应的最大值的值 (考虑到上述假设,每一个都是可能的) . 换句话说:

      finalWidth == maxWidth || finalHeight == maxHeight

      与基本解决方案相比的最后一步( Bitmap.createScaledBitmap(...) )是为了这个” 确切地 “约束。 最重要的是 你不应该一开始就走这一步 (像 the accepted answer ),因为它在处理大量图像时会消耗大量内存!

    4. 用于解码 file . 你可以改变它就像解码 resource (或所有 BitmapFactory 支持)。

    实施:

    public static Bitmap decodeSampledBitmap(String pathName, int maxWidth, int maxHeight) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(pathName, options);
    
        final float wRatio_inv = (float) options.outWidth / maxWidth,
              hRatio_inv = (float) options.outHeight / maxHeight; // Working with inverse ratios is more comfortable
        final int finalW, finalH, minRatio_inv /* = max{Ratio_inv} */;
    
        if (wRatio_inv > hRatio_inv) {
            minRatio_inv = (int) wRatio_inv;
            finalW = maxWidth;
            finalH = Math.round(options.outHeight / wRatio_inv);
        } else {
            minRatio_inv = (int) hRatio_inv;
            finalH = maxHeight;
            finalW = Math.round(options.outWidth / hRatio_inv);
        }
    
        options.inSampleSize = pow2Ceil(minRatio_inv); // pow2Ceil: A utility function that comes later
        options.inJustDecodeBounds = false; // Decode bitmap with inSampleSize set
    
        return Bitmap.createScaledBitmap(BitmapFactory.decodeFile(pathName, options),
              finalW, finalH, true);
    }
    
    /**
     * @return the largest power of 2 that is smaller than or equal to number. 
     * WARNING: return {0b1000000...000} for ZERO input.
     */
    public static int pow2Ceil(int number) {
        return 1 << -(Integer.numberOfLeadingZeros(number) + 1); // is equivalent to:
        // return Integer.rotateRight(1, Integer.numberOfLeadingZeros(number) + 1);
    }
    

    示例用法,如果您有 imageView 以确定的值 layout_width ( match_parent 或显式值)和 layout_height ( wrap_content )取而代之的是 最大高度 :

    imageView.setImageBitmap(decodeSampledBitmap(filePath, 
            imageView.getWidth(), imageView.getMaxHeight()));