重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
我看到好多博客都是这样计算的,但是这样算对吗?有没有哥们试验过这种方法正确性?我觉得看博客要对博主表示怀疑,论证别人写的是否正确。更多详细可以看我的GitHub:https://github.com/yangchong211
网站建设公司,为您提供网站建设,网站制作,网页设计及定制网站建设服务,专注于成都企业网站建设,高端网页制作,对成都混凝土搅拌站等多个行业拥有丰富的网站建设经验的网站建设公司。专业网站设计,网站优化推广哪家好,专业成都网站推广优化,H5建站,响应式网站。
加载一张本地资源图片,那么它占用的内存 = width height nTargetDensity/inDensity nTargetDensity/inDensity 一个像素所占的内存。
@Nullable
public static Bitmap decodeResourceStream(@Nullable Resources res, @Nullable TypedValue value,
@Nullable InputStream is, @Nullable Rect pad, @Nullable Options opts) {
validate(opts);
if (opts == null) {
opts = new Options();
}
if (opts.inDensity == 0 && value != null) {
final int density = value.density;
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
}
}
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
}
return decodeStream(is, pad, opts);
}
质量压缩方法:在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,这样适合去传递二进制的图片数据,比如分享图片,要传入二进制数据过去,限制500kb之内。
/**
* 第一种:质量压缩法
* @param image 目标原图
* @param maxSize 最大的图片大小
* @return bitmap,注意可以测试以下压缩前后bitmap的大小值
*/
public static Bitmap compressImage(Bitmap image , long maxSize) {
int byteCount = image.getByteCount();
Log.i("yc压缩图片","压缩前大小"+byteCount);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 把ByteArrayInputStream数据生成图片
Bitmap bitmap = null;
// 质量压缩方法,options的值是0-100,这里100表示原来图片的质量,不压缩,把压缩后的数据存放到baos中
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
int options = 90;
// 循环判断如果压缩后图片是否大于maxSize,大于继续压缩
while (baos.toByteArray().length > maxSize) {
// 重置baos即清空baos
baos.reset();
// 这里压缩options%,把压缩后的数据存放到baos中
image.compress(Bitmap.CompressFormat.JPEG, options, baos);
// 每次都减少10,当为1的时候停止,options<10的时候,递减1
if(options == 1){
break;
}else if (options <= 10) {
options -= 1;
} else {
options -= 10;
}
}
byte[] bytes = baos.toByteArray();
if (bytes.length != 0) {
// 把压缩后的数据baos存放到bytes中
bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int byteCount1 = bitmap.getByteCount();
Log.i("yc压缩图片","压缩后大小"+byteCount1);
}
return bitmap;
}
/**
/**
什么是采样率压缩?
/**
* 第二种:按采样大小压缩
*
* @param src 源图片
* @param sampleSize 采样率大小
* @param recycle 是否回收
* @return 按采样率压缩后的图片
*/
public static Bitmap compressBySampleSize(final Bitmap src, final int sampleSize, final boolean recycle) {
if (src == null || src.getWidth() == 0 || src.getHeight() == 0) {
return null;
}
Log.i("yc压缩图片","压缩前大小"+src.getByteCount());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
src.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] bytes = baos.toByteArray();
if (recycle && !src.isRecycled()) {
src.recycle();
}
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
Log.i("yc压缩图片","压缩后大小"+bitmap.getByteCount());
return bitmap;
}
/**
/**
Android中使用Matrix对图像进行缩放、旋转、平移、斜切等变换的。
setTranslate(float dx,float dy):控制Matrix进行位移。
setSkew(float kx,float ky):控制Matrix进行倾斜,kx、ky为X、Y方向上的比例。
setSkew(float kx,float ky,float px,float py):控制Matrix以px、py为轴心进行倾斜,kx、ky为X、Y方向上的倾斜比例。
setRotate(float degrees):控制Matrix进行depress角度的旋转,轴心为(0,0)。
setRotate(float degrees,float px,float py):控制Matrix进行depress角度的旋转,轴心为(px,py)。
setScale(float sx,float sy):设置Matrix进行缩放,sx、sy为X、Y方向上的缩放比例。
setScale(float sx,float sy,float px,float py):设置Matrix以(px,py)为轴心进行缩放,sx、sy为X、Y方向上的缩放比例。
/**
* 第三种:按缩放压缩
*
* @param src 源图片
* @param newWidth 新宽度
* @param newHeight 新高度
* @param recycle 是否回收
* @return 缩放压缩后的图片
*/
public static Bitmap compressByScale(final Bitmap src, final int newWidth, final int newHeight, final boolean recycle) {
return scale(src, newWidth, newHeight, recycle);
}
public static Bitmap compressByScale(final Bitmap src, final float scaleWidth, final float scaleHeight, final boolean recycle) {
return scale(src, scaleWidth, scaleHeight, recycle);
}
/**
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
bitmap = null;
}
public void recycle() {
if (!mRecycled && mNativePtr != 0) {
if (nativeRecycle(mNativePtr)) {
// return value indicates whether native pixel object was actually recycled.
// false indicates that it is still in use at the native level and these
// objects should not be collected now. They will be collected later when the
// Bitmap itself is collected.
mNinePatchChunk = null;
}
mRecycled = true;
}
}
Bitmap复用的实验,代码如下所示,然后看打印的日志信息
getByteCount()获取到的是当前图片应当所占内存大小,getAllocationByteCount()获取到的是被复用Bitmap真实占用内存大小。虽然bitmapReuse的内存只有4346880,但是因为是复用的bitmap的内存,因而其真实占用的内存大小是被复用的bitmap的内存大小(1228800)。这也是getAllocationByteCount()可能比getByteCount()大的原因。
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void initBitmap() {
BitmapFactory.Options options = new BitmapFactory.Options();
// 图片复用,这个属性必须设置;
options.inMutable = true;
// 手动设置缩放比例,使其取整数,方便计算、观察数据;
options.inDensity = 320;
options.inTargetDensity = 320;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg_autumn_tree_min, options);
// 对象内存地址;
Log.i("ycBitmap", "bitmap = " + bitmap);
Log.i("ycBitmap", "ByteCount = " + bitmap.getByteCount() + ":::bitmap:AllocationByteCount = " + bitmap.getAllocationByteCount());
// 使用inBitmap属性,这个属性必须设置;
options.inBitmap = bitmap; options.inDensity = 320;
// 设置缩放宽高为原始宽高一半;
options.inTargetDensity = 160;
options.inMutable = true;
Bitmap bitmapReuse = BitmapFactory.decodeResource(getResources(), R.drawable.bg_kites_min, options);
// 复用对象的内存地址;
Log.i("ycBitmap", "bitmapReuse = " + bitmapReuse);
Log.i("ycBitmap", "bitmap:ByteCount = " + bitmap.getByteCount() + ":::bitmap:AllocationByteCount = " + bitmap.getAllocationByteCount());
Log.i("ycBitmap", "bitmapReuse:ByteCount = " + bitmapReuse.getByteCount() + ":::bitmapReuse:AllocationByteCount = " + bitmapReuse.getAllocationByteCount());
//11-26 18:24:07.971 15470-15470/com.yc.cn.ycbanner I/ycBitmap: bitmap = android.graphics.Bitmap@9739bff
//11-26 18:24:07.972 15470-15470/com.yc.cn.ycbanner I/ycBitmap: bitmap:ByteCount = 4346880:::bitmap:AllocationByteCount = 4346880
//11-26 18:24:07.994 15470-15470/com.yc.cn.ycbanner I/ycBitmap: bitmapReuse = android.graphics.Bitmap@9739bff
//11-26 18:24:07.994 15470-15470/com.yc.cn.ycbanner I/ycBitmap: bitmap:ByteCount = 1228800:::bitmap:AllocationByteCount = 4346880
//11-26 18:24:07.994 15470-15470/com.yc.cn.ycbanner I/ycBitmap: bitmapReuse:ByteCount = 1228800:::bitmapReuse:AllocationByteCount = 4346880
}
public final int getAllocationByteCount() {
if (mRecycled) {
Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! "
+ "This is undefined behavior!");
return 0;
}
return nativeGetAllocationByteCount(mNativePtr);
}