Android Bitmapのいくつかの一般的な圧縮方法のまとめ

7451 ワード

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;
}