压缩后位图大小会增加

时间:2016-12-29 03:53:31

标签: android bitmap

以下是我用来压缩Bitmap的一段代码:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
System.out.println("before: " + bmp.getByteCount());
bmp.compress(Bitmap.CompressFormat.JPEG, 80, baos);
System.out.println("baos: "  + baos.toByteArray().length);
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap b = BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()), 
           null, options);
System.out.println("after: " + b.getByteCount());

LogCat输出:

12-29 11:45:52.638 18042-18042/com.xxx.yyy I/System.out: before: 653760
12-29 11:45:52.678 18042-18042/com.xxx.yyy I/System.out: baos: 13118
12-29 11:45:52.688 18042-18042/com.xxx.yyy I/System.out: after: 1307520
压缩后

baos的大小似乎是Bitmap的大小,但为什么b.getByteCount()在压缩之前会返回比bmp更大的大小?

2 个答案:

答案 0 :(得分:0)

BitmapFactory.Options options = new BitmapFactory.Options();

 /*
   isSampleSize will reduce your bitmap size.
   If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save
   memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the
   decoded bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original
   and 1/16 the number of pixels. Any value <= 1 is treated the same as 1. Note: the decoder uses a final value based
   on powers of 2, any other value will be rounded down to the nearest power of 2.
 */
options.inSampleSize = 2; 
Bitmap b = BitmapFactory.decodeStream(new  ByteArrayInputStream(baos.toByteArray()), null, options);
System.out.println("after: " + b.getByteCount());

答案 1 :(得分:0)

我有同样的问题,但我解决了使用Some Method.i在我的相机应用程序中使用此方法后,图像Captured.i将我的代码放在这里。使用它你会尝试。 我的方法:

public static Bitmap decodeSampledBitmapFromByte(Context context, byte[] bitmapBytes) {
    Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

    int reqWidth, reqHeight;
    Point point = new Point();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
        display.getSize(point);
        reqWidth = point.x;
        reqHeight = point.y;
    } else {
        reqWidth = display.getWidth();
        reqHeight = display.getHeight();
    }

    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    options.inMutable = true;
    options.inBitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Load & resize the image to be 1/inSampleSize dimensions
    // Use when you do not want to scale the image with a inSampleSize that is a power of 2
    options.inScaled = true;
    options.inDensity = options.outWidth;
    options.inTargetDensity = reqWidth * options.inSampleSize;

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false; // If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.
    options.inPurgeable = true;         // Tell to gc that whether it needs free memory, the Bitmap can be cleared
    options.inInputShareable = true;    // Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future

    return BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length, options);
}

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    int initialInSampleSize = computeInitialSampleSize(options, reqWidth, reqHeight);

    int roundedInSampleSize;
    if (initialInSampleSize <= 8) {
        roundedInSampleSize = 1;
        while (roundedInSampleSize < initialInSampleSize) {
            // Shift one bit to left
            roundedInSampleSize <<= 1;
        }
    } else {
        roundedInSampleSize = (initialInSampleSize + 7) / 8 * 8;
    }

    return roundedInSampleSize;
}

private static int computeInitialSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final double height = options.outHeight;
    final double width = options.outWidth;

    final long maxNumOfPixels = reqWidth * reqHeight;
    final int minSideLength = Math.min(reqHeight, reqWidth);

    int lowerBound = (maxNumOfPixels < 0) ? 1 :
            (int) Math.ceil(Math.sqrt(width * height / maxNumOfPixels));
    int upperBound = (minSideLength < 0) ? 128 :
            (int) Math.min(Math.floor(width / minSideLength),
                    Math.floor(height / minSideLength));

    if (upperBound < lowerBound) {
        // return the larger one when there is no overlapping zone.
        return lowerBound;
    }

    if (maxNumOfPixels < 0 && minSideLength < 0) {
        return 1;
    } else if (minSideLength < 0) {
        return lowerBound;
    } else {
        return upperBound;
    }
}

我认为你需要使用我的方法decodeSampledBitmapFromByte()而不是你的方法 method.you需要将所有方法放在代码中。

使用此代码我得到相同的大小压缩后。我把我的LogCat放在这里。

My Logcate

希望它能帮助你......享受。(: