最近公司一个项目需要实现身份证合成,交给了我两张素材图片,需要合成身份证的正反面图片并保存到本地。
背面素材:
正面素材:
拿到图片后,我的第一反应是将图片作为布局背景,然后在布局里面设置年龄、出生年月等等相关信息。编辑好了,预览一切正常,但是一看加载效果:
预览效果:
可能有的同学会讲,这个只是适配的原因,我在布局里面把间距的单位设为PX,会不会解决这个问题呢?理论上是可以解决问题,但是领导又说了,我们合成图片的时候没有时间开启Activity,怎么办?说好的保存图片怎么办?控件都没有加载,怎么获取控件显示的图片呢?
还好,我还可以用canvas,到时候我直接开一个线程,把合成的图片保存下来就可以了,这样可以完成任务了吧?于是我又换一个思路,继续写代码:
```
public class CanvasView {
private Canvas canvas;private Bitmap bitmap;private Context mContext;/**
* 测试身份证背面画面
* @param v
* @return
*/public Bitmap loadBitmapA (View v)
{
mContext = v.getContext();bitmap = BitmapFactory.decodeResource(v.getResources(), R.drawable.e1);Paint p = new Paint();p.setAntiAlias(true);p.setColor(Color.BLACK);Bitmap bp = Bitmap.createBitmap(485,306, Config.ARGB_8888);Bitmap target = Bitmap.createScaledBitmap(bitmap,485,306, false);String SrcGov ="中国境外管理局";String UserTime ="1998.07.18-2018.07.18";//加入画布,待编辑文字和加入bitmap
canvas = new Canvas(bp);canvas.drawRect(0,0,485,306, p);p.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));canvas.drawBitmap(target,0,0, p);canvas.drawText(SrcGov,200,232, p);canvas.drawText(UserTime,200,272, p);return bp;}/**
* 测试身份证正面画面
* @param v
* @return
*/public Bitmap loadBitmapB (View v)
{
mContext = v.getContext();//正面背景
bitmap = BitmapFactory.decodeResource(v.getResources(), R.drawable.b1);//头像
Bitmap bitmapimage = BitmapFactory.decodeResource(v.getResources(), R.drawable.abm);Bitmap target = Bitmap.createBitmap(485,306, Config.ARGB_8888);Bitmap old = Bitmap.createScaledBitmap(bitmap,485,306, false);Paint p = new Paint();p.setAntiAlias(true);p.setColor(Color.BLACK);p.setTextSize(16);String name ="奥巴马";String gender ="男";String nation ="非汉";String BornYear ="1961";String BornMouth ="08";String BornDate ="04";String Adress ="属国美国华盛顿哥伦比亚特区西北宾夕法尼亚大道1600号";String Adress1 = Adress.substring(0,11);String Adress2 = Adress.substring(11,22);String Adress3 = Adress.substring(22);String BornId ="91188219608043621";//加入画布,待编辑文字和加入bitmap
canvas = new Canvas(target);canvas.drawRect(0,0,485,306, p);p.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));canvas.drawBitmap(old,0,0, p);Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);p.setTypeface( font );canvas.drawText(name,90,58, p);canvas.drawText(gender,90,96, p);canvas.drawText(nation,195,96, p);canvas.drawText(BornMouth,170,134, p);canvas.drawText(BornDate,215,134, p);canvas.drawText(BornYear,90,134, p);canvas.drawText(Adress1,90,172, p);canvas.drawText(Adress2,90,192, p);canvas.drawText(Adress3,90,212, p);font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);p.setTypeface(font);canvas.drawText(BornId,168,271, p);canvas.drawBitmap(bitmapimage,280,43, null);return target;}
}
```
代码写完了测试一下:
```
public class ViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view);
ImageView image = (ImageView) findViewById(R.id.View);
// image.setImageBitmap(new CanvasView().loadBitmapA(image));
image.setImageBitmap(new CanvasView().loadBitmapB(image));
}
}
```
反面
正面
刚刚测试完,领导又来了,看了测试结果后说我们现在做的都是头像尺寸固定的,但是在项目实际应用当中,身份证头像的照片尺寸是不确定的,且图片是彩色的,需要将头像的色彩改为黑白色,这几点需要在项目里实现。好吧,领导的想法最重要,有了想法才有看法。为了没有不好的看法,我继续写呗!
```
/**
* 修改图片尺寸
* @param bitmap
* @return
*/
private static Bitmap changeBitmapSize(Bitmap bitmap)
{
int w = bitmap.getWidth();
int h = bitmap.getHeight();
//原图尺寸为102*126,现放大为148*182
//所以长和宽比例分别为1.45 1.44
float radioW = 148.0f/w;
float radioH = 182.0f/h;
Matrix matrix = new Matrix();
matrix.postScale(radioW,radioH); //长和宽放大缩小的比例
return Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
}
```
因为头像尺寸是固定的,而且一般图片差异不会特别大,所以这里就没有使用宽高比,而是暴力地修改了。后面的彩色图片改为黑白图片,我也去给它简单过滤一下就好!
```
/**
* 图片换色,由黑白图片更换为彩色图片
* @param bmpOriginal
* @return
*/
public static Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
```
这下总算搞定了,准备下班了,领导又来了,说是图片的背景颜色有白色、黑色、蓝色,这些颜色必须改成透明色。且头像图片的内容不能变。这个就玩大了,,,我继续上网求助度娘(实际上这一点花了身为小菜的我两天时间)。但是度娘也不是万能的,提供了好多办法都是行不通的,最后,快下班的时候终于搞定了!
```
/**
* 修改背景颜色
* @param bitmap 需要修改的图片
* @param replaceThisColor 修改前的颜色
* @return
*/
public Bitmap createTransparentBitmapFromBitmap(Bitmap bitmap,
int replaceThisColor) {
if (bitmap != null) {
int picw = bitmap.getWidth();
int pich = bitmap.getHeight();
int[] pix = new int[picw * pich];
bitmap.getPixels(pix, 0, picw, 0, 0, picw, pich);
for (int y = 0; y < pich; y++)
{
for (int x = 0; x < picw; x++)
{
int index = y * picw + x;
if (pix[index] == replaceThisColor)
{
pix[index] = Color.TRANSPARENT;
}
}
}
Bitmap bm = Bitmap.createBitmap(pix, picw, pich,
Bitmap.Config.ARGB_8888);
return bm;
}
return null;
}
```
最后将工具类提供一个静态方法供其它使用类调用:
```
package com.hhqy.vicent;
import java.io.File;
import java.io.FileOutputStream;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Typeface;
import android.os.Environment;
import android.widget.Toast;
public class CanvasView {
private static Canvas canvas;
private static Context mContext;
/**
* 仅供测试使用
*/
public static String path;
/**
* 获取合成图片
* @param info 图片文本信息
* @param type 图片类型 1代表正面, 2代表反面
* @param bitmap 合成反面的头像图片
* @param context 获取背景资源用
* @param baseColor 当前图片的背景颜色,透明的话设置为111111111
* 注意:证件地址长度不得超过33个字节
*/
public static void getPicture(String[] info,int type,Bitmap bitmap,Context context,int baseColor){
mContext = context;
if(1==type)
{
saveMyBitmap(loadBitmapA(info), "First_"+System.currentTimeMillis());
return;
}
else
{
saveMyBitmap(loadBitmapB(info,bitmap,baseColor), "Second_"+System.currentTimeMillis());
return ;
}
}
/**
* 将bitmap保存为指定名称图片
* @param mBitmap
* @param bitName
*/
public static void saveMyBitmap(Bitmap mBitmap,String bitName)
{
if(Environment.getExternalStorageState()!=Environment.MEDIA_MOUNTED)
{
File dir=new File(Environment.getExternalStorageDirectory() + "/TestPicture");
if(!dir.exists())dir.mkdirs();
File f = new File(dir, "/"+bitName);
path= f.getAbsolutePath();
try {
FileOutputStream fOut = new FileOutputStream(f);
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
Toast.makeText(mContext, bitName+"保存成功", Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 测试身份证背面画面
* @param v
* @return
*/
public static Bitmap loadBitmapA (String[] info)
{
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.e1);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLACK);
Bitmap bp = Bitmap.createBitmap(485, 306, Config.ARGB_8888);
Bitmap target = Bitmap.createScaledBitmap(bitmap, 485, 306, false);
String SrcGov = info[0];
String UserTime = info[1];
//加入画布,待编辑文字和加入bitmap
canvas = new Canvas(bp);
canvas.drawRect(0, 0, 485, 306, p);
p.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(target, 0, 0, p);
canvas.drawText(SrcGov, 200, 232, p);
canvas.drawText(UserTime, 200, 272, p);
return bp;
}
/**
* 测试身份证正面画面
* @param v
* @return
*/
public static Bitmap loadBitmapB (String[] info,Bitmap bmp,int needReplaseColor)
{
//正面背景
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.b1);
//头像
//彩色变黑白色
bmp = toGrayscale(bmp);
// 修改背景颜色
if(needReplaseColor!=111111111)
bmp = createTransparentBitmapFromBitmap(bmp, needReplaseColor);
//放大图片
bmp = changeBitmapSize(bmp);
Bitmap target = Bitmap.createBitmap(485, 306, Config.ARGB_8888);
Bitmap old = Bitmap.createScaledBitmap(bitmap, 485, 306, false);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.BLACK);
p.setTextSize(16);
String name = info[0];
String gender = info[1];
String nation = info[2];
String date = info[3];
int end = date.lastIndexOf(".");
int start = date.indexOf(".");
String BornYear = date.substring(0,start);
String BornMouth = date.substring(start+1, end);
String BornDate = date.substring(end+1);
String Adress = info[4];
String Adress1 = null;
String Adress2 = null;
String Adress3 = null;
if(Adress.length()>=11)
{
Adress1 = Adress.substring(0, 11);
if(Adress.length()>=22)
{
Adress2 = Adress.substring(11,22);
if(Adress.length()>=22)
{
Adress3 = Adress.substring(22);
}
}
else
{
Adress2 = Adress.substring(11,Adress.length());
}
}
else
{
Adress1 = Adress.substring(0, Adress.length());
}
String BornId = info[5];
//加入画布,待编辑文字和加入bitmap
canvas = new Canvas(target);
canvas.drawRect(0, 0, 485, 306, p);
p.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(old, 0, 0, p);
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
p.setTypeface( font );
canvas.drawText(name, 90, 58, p);
font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
p.setTypeface(font);
canvas.drawText(gender, 90, 96, p);
canvas.drawText(nation, 195, 96, p);
canvas.drawText(BornMouth, 170, 134, p);
canvas.drawText(BornDate, 215, 134, p);
canvas.drawText(BornYear, 90, 134, p);
canvas.drawText(Adress1, 90, 172, p);
if(Adress2!=null)
{
canvas.drawText(Adress2, 90, 192, p);
if(Adress3!=null)
{
canvas.drawText(Adress3, 90, 212, p);
}
}
font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
p.setTypeface(font);
canvas.drawText(BornId, 168, 271, p);
canvas.drawBitmap(bmp, 280, 43, null);
return target;
}
/**
* 修改图片尺寸
* @param bitmap
* @return
*/
private static Bitmap changeBitmapSize(Bitmap bitmap)
{
int w = bitmap.getWidth();
int h = bitmap.getHeight();
//原图尺寸为102*126,现放大为148*182
//所以长和宽比例分别为1.45 1.44
float radioW = 148.0f/w;
float radioH = 182.0f/h;
Matrix matrix = new Matrix();
matrix.postScale(radioW,radioH); //长和宽放大缩小的比例
return Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
}
/**
* 图片换色,由彩色图片更换为黑白颜色
* @param bmpOriginal
* @return
* 注意:经测试,透明图片经此设置的话会讲背景色更改为黑色
*/
public static Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
/**
* 修改背景颜色
* @param bitmap 需要修改的图片
* @param replaceThisColor 修改前的颜色
* @return
*/
public static Bitmap createTransparentBitmapFromBitmap(Bitmap bitmap,
int replaceThisColor) {
if (bitmap != null) {
int picw = bitmap.getWidth();
int pich = bitmap.getHeight();
int[] pix = new int[picw * pich];
bitmap.getPixels(pix, 0, picw, 0, 0, picw, pich);
for (int y = 0; y < pich; y++)
{
for (int x = 0; x < picw; x++)
{
int index = y * picw + x;
if (pix[index] == replaceThisColor)
{
pix[index] = Color.TRANSPARENT;
}
}
}
Bitmap bm = Bitmap.createBitmap(pix, picw, pich,
Bitmap.Config.ARGB_8888);
return bm;
}
return null;
}
}
```
调用方法:
```
//正面测试
// String[] info = {"嵊州市公安局","2000.01.01-2020.01.01"};
// CanvasView.getPicture(info, 1, null, this, 0);
//背面测试
String[] info = {"马云","男","汉","1964.09.10","杭州市西湖区西溪新座5幢706室","330683196309100310"};
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.jack);
CanvasView.getPicture(info, 2, bmp, this, Color.WHITE);
image.setImageBitmap(BitmapFactory.decodeFile(CanvasView.path));
```
最后的测试效果:
正面(反正我是这么定义的)
反面
小菜作品,恳请各位大神斧正!!!!周末愉快,找(动词,寻找的意思。)女朋友去了!
大伙看完了不要忘记点评哦,比较奥巴马的平头太平了!!!
网友评论