Android Bitmap 几种常见的压缩方式总结

Bitmap压缩用到的场景:{
1.移动端上传文件需要对本地拍摄保存的文件压缩:图片的缩放比例换算 大小的压缩
2.加载本地图片显示View位图所需要的图片大小并没有那么大
3.图片缓存:请求服务器上的资源缓存到内存或者本地存储提高缓存加载速率
}

Bitmap缓存的优点:1.减少内存开销读取和存储更快 2.提高App流畅度

1.采样率压缩:

    BitmapFactory.Options options = new BitmapFactory.Options(); //获取Bitmap工厂类
    options.inJustDecodeBounds = true; //true 只返回Bitmap宽高 false 返回Bitmap对象实体
    BitmapFactory.decodeFile(fileUrl, options);
    int width = options.outWidth;
    int height = options.outHeight;
    int inSampleSize = 1; //采样率:采样率以1/2++ 形式换算
    //根据输入的宽高换算采样率
    if (height > outHeight || width > outWith) {
     final int halfHeight = height / 2;
     final int halfWidth = width / 2;
     while ((halfHeight / inSampleSize) >= outHeight &&
       (halfWidth / inSampleSize) >= outWith) {
       inSampleSize *= 2;
            }
        }   

2.质量压缩:

 //进行有损压缩
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int options_ = 100;
    actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//质量压缩方法,把压缩后的数据存放到baos中 (100表示不压缩,0表示压缩到最小)

    int baosLength = baos.toByteArray().length;

    while (baosLength / 1024 > maxFileSize) {//循环判断如果压缩后图片是否大于maxMemmorrySize,大于继续压缩
        baos.reset();//重置baos即让下一次的写入覆盖之前的内容
        options_ = Math.max(0, options_ - 10);//图片质量每次减少10
        actualOutBitmap.compress(Bitmap.CompressFormat.JPEG, options_, baos);//将压缩后的图片保存到baos中
        baosLength = baos.toByteArray().length;
        if (options_ == 0)//如果图片的质量已降到最低则,不再进行压缩
            break;
    }
    actualOutBitmap.recycle();

3.缩放法压缩

/**
 * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
 * specified width and height are the same as the current width and height of
 * the source bitmap, the source bitmap is returned and no new bitmap is
 * created.
 *
 * @param src       The source bitmap.
 * @param dstWidth  The new bitmap's desired width.
 * @param dstHeight The new bitmap's desired height.
 * @param filter    true if the source should be filtered.
 * @return The new scaled bitmap or the source bitmap if no scaling is required.
 * @throws IllegalArgumentException if width is <= 0, or height is <= 0
 */
public static Bitmap createScaledBitmap(@NonNull Bitmap src, int dstWidth, int dstHeight,
        boolean filter) {
    Matrix m = new Matrix();

    //换算缩放比例
    final int width = src.getWidth();
    final int height = src.getHeight();
    if (width != dstWidth || height != dstHeight) {
        final float sx = dstWidth / (float) width;
        final float sy = dstHeight / (float) height;
        m.setScale(sx, sy);
    }
    return Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
}


/**
 * Returns an immutable bitmap from subset of the source bitmap,
 * transformed by the optional matrix. The new bitmap may be the
 * same object as source, or a copy may have been made. It is
 * initialized with the same density and color space as the original
 * bitmap.
 *
 * If the source bitmap is immutable and the requested subset is the
 * same as the source bitmap itself, then the source bitmap is
 * returned and no new bitmap is created.
 *
 * @param source   The bitmap we are subsetting
 * @param x        The x coordinate of the first pixel in source
 * @param y        The y coordinate of the first pixel in source
 * @param width    The number of pixels in each row
 * @param height   The number of rows
 * @param m        Optional matrix to be applied to the pixels //设置缩放比例
 * @param filter   true if the source should be filtered.
 *                   Only applies if the matrix contains more than just
 *                   translation.
 * @return A bitmap that represents the specified subset of source
 * @throws IllegalArgumentException if the x, y, width, height values are
 *         outside of the dimensions of the source bitmap, or width is <= 0,
 *         or height is <= 0
 */
public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height,
        @Nullable Matrix m, boolean filter) {

    checkXYSign(x, y);
    checkWidthHeight(width, height);
    if (x + width > source.getWidth()) {
        throw new IllegalArgumentException("x + width must be <= bitmap.width()");
    }
    if (y + height > source.getHeight()) {
        throw new IllegalArgumentException("y + height must be <= bitmap.height()");
    }

    // check if we can just return our argument unchanged
    if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
            height == source.getHeight() && (m == null || m.isIdentity())) {
        return source;
    }

    boolean isHardware = source.getConfig() == Config.HARDWARE;
    if (isHardware) {
        source.noteHardwareBitmapSlowCall();
        source = nativeCopyPreserveInternalConfig(source.mNativePtr);
    }

    int neww = width;
    int newh = height;
    Bitmap bitmap;
    Paint paint;

    Rect srcR = new Rect(x, y, x + width, y + height);
    RectF dstR = new RectF(0, 0, width, height);
    RectF deviceR = new RectF();

    //获取图片原有格式
    //设置压缩  
    Config newConfig = Config.ARGB_8888;
    final Config config = source.getConfig();
    // GIF files generate null configs, assume ARGB_8888
    if (config != null) {
        switch (config) {
            case RGB_565:
                newConfig = Config.RGB_565;
                break;
            case ALPHA_8:
                newConfig = Config.ALPHA_8;
                break;
            case RGBA_F16:
                newConfig = Config.RGBA_F16;
                break;
            //noinspection deprecation
            case ARGB_4444:
            case ARGB_8888:
            default:
                newConfig = Config.ARGB_8888;
                break;
        }
    }

    if (m == null || m.isIdentity()) {
        bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
        paint = null;   // not needed
    } else {
        final boolean transformed = !m.rectStaysRect();

        m.mapRect(deviceR, dstR);

        neww = Math.round(deviceR.width());
        newh = Math.round(deviceR.height());

        Config transformedConfig = newConfig;
        if (transformed) {
            if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) {
                transformedConfig = Config.ARGB_8888;
            }
        }
        bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha());

        paint = new Paint();
        paint.setFilterBitmap(filter);
        if (transformed) {
            paint.setAntiAlias(true);
        }
    }

    nativeCopyColorSpace(source.mNativePtr, bitmap.mNativePtr);

    // The new bitmap was created from a known bitmap source so assume that
    // they use the same density
    bitmap.mDensity = source.mDensity;
    bitmap.setHasAlpha(source.hasAlpha());
    bitmap.setPremultiplied(source.mRequestPremultiplied);

    Canvas canvas = new Canvas(bitmap);
    canvas.translate(-deviceR.left, -deviceR.top);
    canvas.concat(m);
    canvas.drawBitmap(source, srcR, dstR, paint);
    canvas.setBitmap(null);
    if (isHardware) {
        return bitmap.copy(Config.HARDWARE, false);
    }
    return bitmap;
}

猜你喜欢

转载自blog.csdn.net/silencezmz/article/details/79866009