以前說過了 重疊部分圖檔合成,今天說一下
canvas.drawBitmap拼接長圖
先上效果gif

需求:多圖拼接長圖,長圖大小 寬度為螢幕,高度自己不變形成比例
核心源碼1.:
final int mScreenWidth = getResources().getDisplayMetrics().widthPixels;
LogUtil.log("mScreenWidth---" + mScreenWidth);
new AsyncTask<List<String>, Void, Bitmap>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
showMyDialog();
}
@Override
protected Bitmap doInBackground(List<String>... lists) {
List<String> list = lists[0];
Bitmap last = null;
for (int i = 0; i < list.size(); i++) {
if (last == null) {
last = PhotoUtils.comp(BitmapFactory.decodeFile(list.get(0)));
} else {
last = PhotoUtils.newBitmap(mScreenWidth, last, PhotoUtils.comp(BitmapFactory.decodeFile(list.get(i))));
}
}
return last;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
dismissMyDialog();
ivLong.setImageBitmap(bitmap);
}
}.execute(pathList);
1.壓縮到不崩潰的加載品質
//圖檔按比例大小壓縮方法(根據Bitmap圖檔壓縮)
public static Bitmap comp(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
if (baos.toByteArray().length / 1024 > 1024) {//判斷如果圖檔大于1M,進行壓縮避免在生成圖檔(BitmapFactory.decodeStream)時溢出
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//這裡壓縮50%,把壓縮後的資料存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//開始讀入圖檔,此時把options.inJustDecodeBounds 設回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
//現在主流手機比較多是800*480分辨率,是以高和寬我們設定為
float hh = 800f;//這裡設定高度為800f
float ww = 480f;//這裡設定寬度為480f
//縮放比。由于是固定比例縮放,隻用高或者寬其中一個資料進行計算即可
int be = 1;//be=1表示不縮放
if (w > h && w > ww) {//如果寬度大的話根據寬度固定大小縮放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的話根據寬度固定大小縮放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;//設定縮放比例
//重新讀入圖檔,注意此時已經把options.inJustDecodeBounds 設回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
. bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
return compressImage(bitmap);//壓縮好比例大小後再進行品質壓縮
}
//一、品質壓縮法
public static Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//品質壓縮方法,這裡100表示不壓縮,把壓縮後的資料存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 100) { //循環判斷如果壓縮後圖檔是否大于100kb,大于繼續壓縮
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//這裡壓縮options%,把壓縮後的資料存放到baos中
options -= 10;//每次都減少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把壓縮後的資料baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream資料生成圖檔
return bitmap;
}
2.具體拼接方法基本原理(下面有進一步優化)
public static Bitmap newBitmap(int width, Bitmap bit1, Bitmap bit2) {
if (width <= 0) {
return null;
}
int h1 = bit1.getHeight() * width / bit1.getWidth();
int h2 = bit2.getHeight() * width / bit2.getWidth();
int height = h1 + h2; //縮放到螢幕寬度時候 合成後的總高度
//建立一個空的Bitmap(記憶體區域),寬度等于第一張圖檔的寬度,高度等于兩張圖檔高度總和
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
//縮放到指定大小的新bitmap
Bitmap newSizeBitmap1 = getNewSizeBitmap(bit1, width, h1);
Bitmap newSizeBitmap2 = getNewSizeBitmap(bit2, width, h2);
//将bitmap放置到繪制區域,并将要拼接的圖檔繪制到指定記憶體區域
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(newSizeBitmap1, 0, 0, null);
canvas.drawBitmap(newSizeBitmap2, 0, h1, null);
return bitmap;
}
//進行優化後的合成方法
/**
* 以第一個圖為準
* 優化算法 1.圖檔不需要鋪滿,隻需要以統一合适的寬度。然後讓imageview自己去鋪滿,不然長圖合成長圖會崩潰,這裡以第一張圖為例
*2.隻縮放不相等寬度的圖檔。已經縮放過的不需要再次縮放
* @param bit1
* @param bit2
* @return
*/
public static Bitmap newBitmap(Bitmap bit1, Bitmap bit2) {
Bitmap newBit = null;
int width = bit1.getWidth();
if (bit2.getWidth() != width) {
int h2 = bit2.getHeight() * width / bit2.getWidth();
newBit = Bitmap.createBitmap(width, bit1.getHeight() + h2, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBit);
Bitmap newSizeBitmap2 = getNewSizeBitmap(bit2, width, h2);
canvas.drawBitmap(bit1, 0, 0, null);
canvas.drawBitmap(newSizeBitmap2, 0, bit1.getHeight(), null);
} else {
newBit = Bitmap.createBitmap(width, bit1.getHeight() + bit2.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBit);
canvas.drawBitmap(bit1, 0, 0, null);
canvas.drawBitmap(bit2, 0, bit1.getHeight(), null);
}
return newBit;
}
public static Bitmap getNewSizeBitmap(Bitmap bitmap, int newWidth, int newHeight) {
float scaleWidth = ((float) newWidth) / bitmap.getWidth();
float scaleHeight = ((float) newHeight) / bitmap.getHeight();
// 取得想要縮放的matrix參數
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 得到新的圖檔
Bitmap bit1Scale = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,
true);
return bit1Scale;
}
3.xml顯示
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_long"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY" />
</FrameLayout>
</ScrollView>