背景
用戶通過筆在紙上手寫了個人簽名,通過拍照上傳的方式將其筆跡設定為簽名圖片,
如果直接使用此圖片(包括裁剪后的圖片),則在簽名的程序中會簽名圖案中不但有用戶的筆跡,還有紙的顏色背景,效果堪憂,
解決目標
將用戶的手寫筆跡采集,并且背景色是透明的
解決思路
- 用戶選擇已經拍攝的筆跡照片
- 用戶通過裁剪區域選擇手寫筆跡(尺寸為300*120)
- 程式將裁剪好的手寫筆跡區域進行筆跡采集和透明化處理
-將圖片中的黑色像素點1 保留,其他像素點設定為透明 (難點和重點:哪些色值可以被認定為筆跡、用戶拍照時候的光線影響、用戶手寫紙的背景色)
-將圖片保存為手寫區域 - 將處理好的手寫筆跡采集結果給用戶預覽
- 用戶確認后將此手寫筆跡處理后的圖提交給服務端
Android模塊的核心代碼(圖片裁剪不在此范圍)
package cn.org.bjca.wcert.ywq.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Environment;
import java.io.File;
import java.io.FileOutputStream;
/*************************************************************************************************
* <pre>
* @包路徑: cn.org.bjca.wcert.ywq.utils
* @著作權所有: 北京數字認證股份有限公司 (C) 2020
*
* @類描述: 手寫筆跡處理
* @版本: V4.0.0
* @作者 daizhenhong
* @創建時間 2020/11/2 3:50 PM
</pre>
************************************************************************************************/
public class HandSignUtil {
final static String filePathHeader = "file://";
private final static int maxColorBlack = 145;
private final static int mColorDifMax = 14;
/**
* 將已經裁剪了的手寫簽名筆跡圖片進行透明化處理
*
* @param context
* @param imagePath 圖片的檔案地址(前綴是file://)
* @return 經過背景透明化處理后的圖片地址(需要添加file://協議頭)
* @throws Exception
*/
public static String getHandSignByImagePath(Context context, String imagePath) throws Exception {
String path = imagePath.substring(filePathHeader.length());
Bitmap originBitmap = BitmapFactory.decodeFile(path);
Bitmap translateBitmap = translateBitmap(originBitmap);
String filePath = getSaveImagePath(context);
File saveFile = new File(filePath);
translateBitmap.compress(Bitmap.CompressFormat.PNG, 100, new FileOutputStream(saveFile));
return filePathHeader + saveFile.toString();
}
private static String getSaveImagePath(Context context) {
String cachePath = "";
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
File fileParent = new File(cachePath);
if (!fileParent.exists()) {
fileParent.mkdirs();
}
File path = new File(cachePath, System.currentTimeMillis() + ".png");
return path.toString();
}
/**
* 將圖片進行背景透明化處理
*
* @param originBitmap 原始圖片的bitmap物件
* @return 背景透明化處理后的bitmap
*/
private static Bitmap translateBitmap(Bitmap originBitmap) {
Bitmap translateBitmap = originBitmap.copy(Bitmap.Config.ARGB_8888, true);
int nWidth = translateBitmap.getWidth();
int nHeight = translateBitmap.getHeight();
// 由于圖片經過裁剪后是jpeg格式的,如果直接保存成png圖片,會造成透明的背景色變成黑色(因為jpeg圖片沒有alpha通道)
Bitmap resultBitmap = Bitmap.createBitmap(nWidth, nHeight, Bitmap.Config.ARGB_8888);
for (int y = 0; y < nHeight; ++y)
for (int x = 0; x < nWidth; ++x) {
int nPixelColor = originBitmap.getPixel(x, y);
int newColor = getNewColor(nPixelColor);
resultBitmap.setPixel(x, y, newColor);
}
return resultBitmap;
}
/**
* 獲取像素點需要變更的顏色
* 當像素點不是黑色的,則將其設定為透明
*
* @param nPixelColor
* @return
*/
private static int getNewColor(int nPixelColor) {
if (isBlackColor(nPixelColor)) {
return Color.argb(Color.alpha(nPixelColor), Color.red(nPixelColor), Color.green(nPixelColor), Color.blue(nPixelColor));
}
return Color.TRANSPARENT;
}
/**
* 判斷是否是黑色筆跡
*
* @param color 顏色的int值
* @return true-認定為黑色筆跡
*/
private static boolean isBlackColor(int color) {
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
int colorMax = Math.max(Math.max(r, g), b);
int colorMin = Math.min(Math.min(r, g), b);
int dif = colorMax - colorMin;
return colorMax < maxColorBlack && dif <= mColorDifMax;
}
}
黑色像素點我們的計算方式:影像的像素有rgb(jpeg圖片)或rgba組件(png圖片),我們目前的設定是:rgb的最大一項不大于145 ,同時rgb之前的最大差距不能超過14 ??
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/211652.html
標籤:java
