Android 压缩后位图大小增加

Android 压缩后位图大小增加,android,bitmap,Android,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); BitmapFacto

下面是我用来压缩位图的一段代码:

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
大的大小?

BitmapFactory.Options=new BitmapFactory.Options();
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());
/* isSampleSize将减小位图大小。 如果设置为值>1,则请求解码器对原始图像进行二次采样,返回要保存的较小图像 记忆。样本大小是任一维度中对应于图像中单个像素的像素数 解码位图。例如,inSampleSize==4返回的图像是原始图像宽度/高度的1/4 和像素数的1/16。任意值
BitmapFactory.Options=new BitmapFactory.Options();
/*
isSampleSize将减小位图大小。
如果设置为值>1,则请求解码器对原始图像进行二次采样,返回要保存的较小图像
记忆。样本大小是任一维度中对应于图像中单个像素的像素数
解码位图。例如,inSampleSize==4返回的图像是原始图像宽度/高度的1/4

和像素数的1/16。任何值我也有同样的问题,但我用某种方法解决了。在拍摄完图像后,我在我的相机应用程序中使用了这种方法。我把我的代码放在这里。使用它你会尝试的。 我的方法:

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(上下文上下文,字节[]位映射字节){
Display Display=((WindowManager)context.getSystemService(context.WINDOW_SERVICE)).getDefaultDisplay();
要求宽度,要求高度;
点=新点();
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.HONEYCOMB\u MR2){
显示。getSize(点);
reqWidth=点x;
reqHeight=点y;
}否则{
reqWidth=display.getWidth();
reqHeight=display.getHeight();
}
final BitmapFactory.Options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
options.inMutable=true;
options.inBitmap=BitmapFactory.decodeByteArray(bitmapBytes,0,bitmapBytes.length,选项);
//计算样本大小
options.inSampleSize=计算样本大小(options、reqWidth、reqHeight);
//加载图像并将其大小调整为1/in采样尺寸
//当不希望使用2次方的inSampleSize缩放图像时使用
options.inScaled=true;
options.inDensity=options.outWidth;
options.inTargetDensity=reqWidth*options.inSampleSize;
//使用inSampleSize集合解码位图
options.inJustDecodeBounds=false;//如果设置为true,解码器将返回null(无位图),但仍将设置out…字段,允许调用方查询位图,而无需为其像素分配内存。
options.inpurgable=true;//告诉gc是否需要空闲内存,位图可以被清除
options.inInputShareable=true;//清除位图数据后,将使用哪种引用来恢复位图数据,以及将来何时使用
返回BitmapFactory.decodeByteArray(bitmapBytes,0,bitmapBytes.length,选项);
}
公共静态int-calculateInSampleSize(BitmapFactory.Options选项、int-reqWidth、int-reqHeight){
int initialInSampleSize=计算初始采样(选项、reqWidth、reqHeight);
整数取整样本;

if(initialInSampleSize我也遇到了同样的问题,但我用了一些方法解决了。在拍摄完图像后,我在我的相机应用程序中使用了这种方法。我将代码放在这里。使用它,你会尝试的。 我的方法:

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(上下文上下文,字节[]位映射字节){
Display Display=((WindowManager)context.getSystemService(context.WINDOW_SERVICE)).getDefaultDisplay();
要求宽度,要求高度;
点=新点();
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.HONEYCOMB\u MR2){
显示。getSize(点);
reqWidth=点x;
reqHeight=点y;
}否则{
reqWidth=display.getWidth();
reqHeight=display.getHeight();
}
final BitmapFactory.Options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
options.inMutable=true;
options.inBitmap=BitmapFactory.decodeByteArray(bitmapBytes,0,bitmapBytes.length,选项);
//计算样本大小
options.inSampleSize=计算样本大小(options、reqWidth、reqHeight);
//加载图像并将其大小调整为1/in采样尺寸
//当不希望使用2次方的inSampleSize缩放图像时使用
options.inScaled=true;
options.inDensity=options.outWidth;
options.inTargetDensity=reqWidth*options.inSampleSize;
//使用inSampleSize集合解码位图
options.inJustDecodeBounds=false;//如果设置为true,解码器将返回null(无位图),但仍将设置out…字段,允许调用方查询位图,而无需为其像素分配内存。
options.inpurgable=true;//告诉gc是否需要空闲内存,位图可以被清除
options.inInputShareable=true;//清除位图数据后,将使用哪种引用来恢复位图数据,以及将来何时使用
返回BitmapFactory.decodeByteArray(bitmapBytes,0,bitmapBytes.length,选项);
}
公共静态int-calculateInSampleSize(BitmapFactory.Options选项、int-reqWidth、int-reqHeight){
int initialInSampleSize=计算初始采样(选项、reqWidth、reqHeight);
整数取整样本;

如果(initialInSampleSize),请尝试对
quality
参数使用较小的值进行压缩。尝试对
quality
参数使用较小的值进行压缩。