實現圖片Bitmap簡單編輯的三種方式

最近的安卓開發中遇到了一個看起來比較棘手的問題:三方分享圖片,剛開始的需求僅僅是分享(動漫圖片類app)畫作主圖,使用的是友盟的。友盟支持純圖片分享,要提供一個bitmap

<span style="white-space:pre">		</span>UMImage img = new UMImage(context, bmp);
		//設置微信好友分享內容
		WeiXinShareContent weixinContent = new WeiXinShareContent();
		//設置分享圖片
		weixinContent.setShareImage(img);
		mController.setShareMedia(weixinContent);
		//設置微信朋友圈分享內容
		CircleShareContent circleMedia = new CircleShareContent();
		//設置朋友圈title
		circleMedia.setTitle(title);
		circleMedia.setShareImage(img);
		mController.setShareMedia(circleMedia);
剛開始沒什麼問題。


之後,產品把需求改了,需要在畫作主圖中添加水印表明畫師頭像,畫師名,畫作描述,以及相應的app二維碼圖片;


由於這個功能ios最先開始做,我就向ios取經。而ios那邊的做法是使用view轉bitmap,於是到網上查找相應的資料

   方案一:ios的方案

private Bitmap getShareBitmap() {
		View headerView = LayoutInflater.from(mActivity).inflate(
				R.layout.fragment_share, null);
		SimpleDraweeView img_user = (SimpleDraweeView)headerView.findViewById(R.id.img_user);
		TextView comic_name = (TextView)headerView.findViewById(R.id.comic_name);
		TextView comic_title = (TextView)headerView.findViewById(R.id.comic_title);
		FrescoHelper.displayImage2Cir(img_user, resp.data.avatar, true);
		comic_title.setText(resp.data.content);
		comic_name.setText(resp.data.nickname);
		int name_height = getFontHeight(DisplayUtils.sp2px(getActivity(),18.0f));
		int title_height = getFontHeight(DisplayUtils.sp2px(getActivity(),16.0f));
		int bottom_height = getFontHeight(DisplayUtils.sp2px(getActivity(),14.0f));
		int viewHight = name_height+title_height*2+bottom_height+96+50;
		return	BitmapUtils.getViewBitmap(headerView,(int)StringUtils.getScreenWidth(),viewHight);
	}
 /**
     * 把View繪製到Bitmap上
     * @param view 需要繪製的View
     * @param width 該View的寬度
     * @param height 該View的高度
     * @return 返回Bitmap對象
     */
    public static Bitmap getViewBitmap(View view, int width, int height) {
        Bitmap bitmap = null;
        if (view != null) {
            view.clearFocus();
            view.setPressed(false);
            boolean willNotCache = view.willNotCacheDrawing();
            view.setWillNotCacheDrawing(false);
            int color = view.getDrawingCacheBackgroundColor();
            view.setDrawingCacheBackgroundColor(0);
            float alpha = view.getAlpha();
            view.setAlpha(1.0f);
            if (color != 0) {
                view.destroyDrawingCache();
            }
            int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
            int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
            view.measure(widthSpec, heightSpec);
            view.layout(0, 0, width, height);
            view.buildDrawingCache();
            Bitmap cacheBitmap = view.getDrawingCache();
            if (cacheBitmap == null) {
                Log.e("view.ProcessImageToBlur", "failed getViewBitmap(" + view + ")",
                        new RuntimeException());
                return null;
            }
            bitmap = Bitmap.createBitmap(cacheBitmap);
            cacheBitmap.recycle();
            cacheBitmap = null;
            view.setAlpha(alpha);
            view.destroyDrawingCache();
            view.setWillNotCacheDrawing(willNotCache);
            view.setDrawingCacheBackgroundColor(color);
        }
        return bitmap;
    }
headerView是一個自己佈局的linerLayout形式
這樣看起來是沒什麼問題,一測試對於特別的長圖(畫作主圖個別存在高度是寬度的10倍)會帶導致OOM,方案一捨棄


方案二:自定義拼接bitmap

這個方案需要縮放,否則可能會OOM,縮放分畫師主圖縮放和底部描述縮放兩種

主圖縮放主要是爲了對應長圖,地圖縮放主要是對應於高度不高的短圖,直接上代碼拼接代碼那塊就不貼出來了

private Bitmap createShareBitmap(Bitmap topBtp,Bitmap btnBtp) {
		if (null ==topBtp ||null==btnBtp) {
			Logger.d("src == null");
			return null;
		}
		//頭部的測量寬高
		int topWid = topBtp.getWidth(),topHig = topBtp.getHeight();
		int totalWid,totalHig;
		//底部的測量寬高
		int btnWid = btnBtp.getWidth(),btnhig = btnBtp.getHeight();
		//整體的btn設置
		Bitmap allBtp;
		if(topBtp.getHeight()>2000){
			//頭部的高度大於2K,即爲長圖,縮放底部的Bitmap,保持頭部寬度不變,長圖,高度計算
			totalWid = topWid;
			//縮放底部
			Matrix matrix = new Matrix();
			float scale = (float) topWid / btnWid;
			matrix.postScale(scale, scale);
			//縮放後的底部數據
			Bitmap btnScaleBtp = Bitmap.createBitmap(btnBtp, 0, 0, btnWid, btnhig, matrix, true);
			//總體的高度=縮放後底部高度+頭部高度
			totalHig =topHig+btnScaleBtp.getHeight();
			// 創建位圖
			allBtp = Bitmap.createBitmap(totalWid, totalHig, Bitmap.Config.RGB_565);
			Logger.d("totalWid="+totalWid+"totalHig="+totalHig);
			// 創建一個新的和SRC長度寬度一樣的位圖
			Canvas cv = new Canvas(allBtp);
			// 畫底層圖
			cv.drawBitmap(topBtp, 0, 0, null);// 在 0,0座標開始畫入src
			// 畫水印
			cv.drawBitmap(btnScaleBtp, 0, topHig, null);// 在src的右下角畫入水印
			// 保存位圖
			cv.save(Canvas.ALL_SAVE_FLAG);// 保存
			cv.restore();// 存儲
			recycleBitmap(btnScaleBtp);
			return allBtp;
		}else{
			//頭部的高度小於2K,即爲一般圖,縮放頭部的Bitmap,保持底部寬度不變即屏幕寬度
			totalWid = btnWid;
			//縮放頭部
			Matrix matrix = new Matrix();
			float scale = (float) totalWid / topWid;
			matrix.postScale(scale, scale);
			//縮放後的底部數據
			Bitmap topScaleBtn = Bitmap.createBitmap(topBtp, 0, 0, topWid, topHig, matrix, true);
			//總體的高度=縮放後頭部高度+底部高度
			totalHig =btnhig+topScaleBtn.getHeight();
			// 創建位圖
			allBtp = Bitmap.createBitmap(totalWid, totalHig, Bitmap.Config.RGB_565);
			Logger.d("totalHig="+totalHig+"totalWid="+totalWid);
			// 創建一個新的和SRC長度寬度一樣的位圖
			Canvas cv = new Canvas(allBtp);
			// 畫底層圖
			cv.drawBitmap(topScaleBtn, 0, 0, null);// 在 0,0座標開始畫入src
			// 畫水印
			cv.drawBitmap(btnBtp, 0, topScaleBtn.getHeight(), null);// 在src的右下角畫入水印
			// 保存位圖
			cv.save(Canvas.ALL_SAVE_FLAG);// 保存
			cv.restore();// 存儲
			recycleBitmap(topScaleBtn);
			return allBtp;
		}
	}

暫時是解決問題了,但是感覺繁瑣

方案三:Scrollview截圖

一次無意間查看到關於android截屏的知識,看到關於截取超過屏幕的圖片方法,其中一個ScrollView的截圖方式

很簡單,也分享給大家

/** 
     * 截取scrollview的屏幕 
     * @param scrollView 
     * @return 
     */  
    public static Bitmap getBitmapByView(ScrollView scrollView) {  
        int h = 0;  
        Bitmap bitmap = null;  
        // 獲取scrollview實際高度  
        for (int i = 0; i < scrollView.getChildCount(); i++) {  
            h += scrollView.getChildAt(i).getHeight();  
            scrollView.getChildAt(i).setBackgroundColor(  
                    Color.parseColor("#ffffff"));  
        }  
        // 創建對應大小的bitmap  
        bitmap = Bitmap.createBitmap(scrollView.getWidth(), h,  
                Bitmap.Config.RGB_565);  
        final Canvas canvas = new Canvas(bitmap);  
        scrollView.draw(canvas);  
        return bitmap;  
    }  

ScrollView截屏來源於:點擊打開鏈接





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章