这边做一个博客,专门用来放一些Bitmap的基本操作方法
再分享一个bitmap优化的博客:
缩放(顺带压缩)
/**
* 缩放图片的宽高
* 也可以达到压缩的目的,
* 和修改inSampleSize的方式有异曲同工之妙
* @param bitmap
* @param sx
* @param sy
* @return
*/
public static Bitmap CompressBitmapForScale(Bitmap bitmap, float sx, float sy) {
Matrix matrix = new Matrix();
matrix.setScale(sx, sy);
Bitmap newBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return newBmp;
}
/**
* 压缩成指定宽高
* 其实和CompressBitmapForScale原理是一样的
* 也是改变宽高,只不过这里我们只需要传入原来的bitmap
* 内部自动帮我们算好了缩放比例而已
* @param bitmap
* @param width
* @param height
* @return
*/
public static Bitmap CompressBitmapForWH(Bitmap bitmap, int width, int height) {
return Bitmap.createScaledBitmap(bitmap, width, height, true);
}
压缩
/**
* 通过修改inSampleSize采样率达到压缩目的
* 2代表宽高都除于2,这样图片就变成原来的四分之一
* @param sourceBitmap
* @return
*/
public static Bitmap CompressBitmapForSampleSize(String sourceBitmap) {
BitmapFactory.Options bitmapFactoryOptions = new BitmapFactory.Options();
bitmapFactoryOptions.inJustDecodeBounds = true;
bitmapFactoryOptions.inSampleSize = 2;
// 这里一定要将其设置回false,因为之前我们将其设置成了true
// 设置inJustDecodeBounds为true后,decodeFile并不分配空间,即,BitmapFactory解码出来的Bitmap为Null,但可计算出原始图片的长度和宽度
bitmapFactoryOptions.inJustDecodeBounds = false;
Bitmap bmp = BitmapFactory.decodeFile(sourceBitmap, bitmapFactoryOptions);
return bmp;
}
/**
* 忽略透明度达到压缩目的
* 经过测试,压缩后大小为原来的二分之一
* @param sourceBitmap
* @return
*/
public static Bitmap CompressBitmapForRGB(String sourceBitmap) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
//获取资源图片
return BitmapFactory.decodeFile(sourceBitmap, opt);
}
/**
* 压缩的是只是存储大小,而不是图片在内存的大小
* 具体看:https://www.cnblogs.com/shoneworn/p/6932638.html
* quality:压缩为原来的百分之多少,这里就是10%
* @param bitmap
* @return
*/
public static Bitmap CompressBitmapForQuality(Bitmap bitmap){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
bitmap.compress(Bitmap.CompressFormat.JPEG, 10, baos);
//把压缩后的数据baos存放到ByteArrayInputStream中
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
//把ByteArrayInputStream数据生成图片
Bitmap newBitmap = BitmapFactory.decodeStream(isBm, null, null);
return newBitmap;
}
url转bitmap
public static Bitmap getBitmap(String url) {
URL imageURL = null;
Bitmap bitmap = null;
try {
imageURL = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
HttpURLConnection conn = (HttpURLConnection) imageURL
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
bitmap切片重组
这个主要是加载一个大的bitmap时使用,
将大的bitmap切为多个小的bitmap,并放入列表中
最后也可以选择返回列表,或者遍历列表的bitmap,重组为大的bitmap
public void setBitmapToImg(Bitmap resource, ImageView mImageView1) {
Rect mRect = new Rect();
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
resource.compress(Bitmap.CompressFormat.PNG, 100, baos);
InputStream isBm = new ByteArrayInputStream(baos.toByteArray());
//BitmapRegionDecoder newInstance(InputStream is, boolean isShareable)
//用于创建BitmapRegionDecoder,isBm表示输入流,只有jpeg和png图片才支持这种方式,
// isShareable如果为true,那BitmapRegionDecoder会对输入流保持一个表面的引用,
// 如果为false,那么它将会创建一个输入流的复制,并且一直使用它。即使为true,程序也有可能会创建一个输入流的深度复制。
// 如果图片是逐步解码的,那么为true会降低图片的解码速度。如果路径下的图片不是支持的格式,那就会抛出异常
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(isBm, true);
final int imgWidth = decoder.getWidth();
final int imgHeight = decoder.getHeight();
BitmapFactory.Options opts = new BitmapFactory.Options();
//计算图片要被切分成几个整块,
// 如果sum=0 说明图片的长度不足3000px,不进行切分 直接添加
// 如果sum>0 先添加整图,再添加多余的部分,否则多余的部分不足3000时底部会有空白
int sum = imgHeight / 3000;
int redundant = imgHeight % 3000;
List<Bitmap> bitmapList = new ArrayList<>();
//说明图片的长度 < 3000
if (sum == 0) {
//直接加载
bitmapList.add(resource);
} else {
//说明需要切分图片
for (int i = 0; i < sum; i++) {
//需要注意:mRect.set(left, top, right, bottom)的第四个参数,
//也就是图片的高不能大于这里的4096
mRect.set(0, i * 3000, imgWidth, (i + 1) * 3000);
Bitmap bm = decoder.decodeRegion(mRect, opts);
bitmapList.add(bm);
}
//将多余的不足3000的部分作为尾部拼接
if (redundant > 0) {
mRect.set(0, sum * 3000, imgWidth, imgHeight);
Bitmap bm = decoder.decodeRegion(mRect, opts);
bitmapList.add(bm);
}
}
Bitmap bigbitmap = Bitmap.createBitmap(imgWidth, imgHeight, Bitmap.Config.ARGB_8888);
Canvas bigcanvas = new Canvas(bigbitmap);
Paint paint = new Paint();
int iHeight = 0;
//将之前的bitmap取出来拼接成一个bitmap
for (int i = 0; i < bitmapList.size(); i++) {
Bitmap bmp = bitmapList.get(i);
bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
iHeight += bmp.getHeight();
bmp.recycle();
bmp = null;
}
mImageView1.setImageBitmap(bigbitmap);
} catch (IOException e) {
e.printStackTrace();
}
}