Commit 8b9a1faf by zhouxiao

添加指纹图片处理的方法,使其可以成功入库

parent c8108f54
package com.common;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.*;
/**
* Created by luoshaopeng on 2021/8/26.
*/
public class ToolUtil {
//入库处理base64图片所需方法
/**
* 将文件转换成Byte数组
*
* @param pathStr 文件路径
* @return 字节数组
*/
public static byte[] getBytesByFile(String pathStr) {
File file = new File(pathStr);
try {
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
byte[] data = bos.toByteArray();
bos.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @param orgByte bmp源文件字节数组
* @return 字节数组
*/
public static byte[] dealBmpByByte(byte[] orgByte) {
byte[] noHeadByte = subBytes(orgByte, 1078);
byte[] noHeadByteT = new byte[noHeadByte.length];
byte[] highByte = subBytes(orgByte, 22, 26);
int high = byteArrayToInt(highByte);
byte[] widthByte = subBytes(orgByte, 18, 22);
int width = byteArrayToInt(widthByte);
if (high < 0) {
return noHeadByte;
}
byte[][] twoByte = oneByteArrayToTwoByteArray(noHeadByte, Math.abs(width), Math.abs(high));
if (twoByte != null) {
byte[][] twoByteT = reverdraSort(twoByte);
noHeadByteT = twoByteArrayToOneByteArray(twoByteT);
} else {
return null;
}
return noHeadByteT;
}
/**
* 字节数组转base64字符串
*
* @param byteData 字节数组数据
* @return base64字符串
*/
public static String byteArrayToBase64String(byte[] byteData) {
BASE64Encoder encoder = new BASE64Encoder();
return byteData != null ? encoder.encode(byteData) : null;
}
/**
* @param str base64字符串
* @return 字符串
*/
public static String formatBase64String(String str) {
return str.replaceAll("\\s*|\t|\r|\n", "");
}
//出库将base64图片还原成图片str所需方法
/**
* base64字符串转字节数组
*
* @param base64String base64字符串
* @return 字节数组
* @throws IOException
*/
public static byte[] base64StringToByteArray(String base64String) throws IOException {
BASE64Decoder decoder = new BASE64Decoder();
return base64String != null ? decoder.decodeBuffer(base64String) : null;
}
/**
* @param bytes 去了位图文件头等信息的字节数组
* @param width 文件的宽
* @param high 文件的高
* @return 位图信息的字节数组
*/
public static byte[] addHeadImage(byte[] bytes, int width, int high) {
byte[] headbytes = getBmpHead(width, high, true);
byte[] data = new byte[bytes.length + headbytes.length];
data = mergeByteArray(data, headbytes, 0, headbytes.length);
data = mergeByteArray(data, bytes, headbytes.length, data.length);
return data;
}
/**
* 将Byte数组转换成文件
*
* @param bytes 字节数组
* @param filePath 文件路径
* @param fileName 文件名称
*/
public static void getFileByBytes(byte[] bytes, String filePath, String fileName) {
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(filePath);
if (!dir.exists()) {// 判断文件目录是否存在
dir.mkdirs();
}
file = new File(filePath + fileName);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 截取字节数组
*
* @param src 源字节数组
* @param begin 开始位置
* @return 从begin位置截取后的字节数组
*/
public static byte[] subBytes(byte[] src, int begin) {
if (begin > src.length) {
begin = src.length;
}
if (begin < 0) {
begin = 0;
}
byte[] bs = new byte[src.length - begin];
for (int i = begin; i < src.length; i++) {
bs[(i - begin)] = src[i];
}
return bs;
}
/**
* 截取字节数组
*
* @param src 源字节数组
* @param begin 开始位置
* @param end 结束位置
* @return 从begin位置截取后的字节数组
*/
public static byte[] subBytes(byte[] src, int begin, int end) {
if (end > src.length) {
begin = src.length;
}
if (end < 0) {
begin = 0;
}
byte[] bs = new byte[end - begin];
for (int i = begin; i < end; i++) {
bs[(i - begin)] = src[i];
}
return bs;
}
/**
* 字节数组转位Int
*
* @param b 字节数组
* @return int
*/
public static int byteArrayToInt(byte[] b) {
return b[0] & 0xFF | (b[1] & 0xFF) << 8 | (b[2] & 0xFF) << 16 | (b[3] & 0xFF) << 24;
}
/**
* @param src 源字节数组1
* @param byt 源字节数组2
* @param begin 开始
* @param end 结束
* @return 合并后的字节数组
*/
public static byte[] mergeByteArray(byte[] src, byte[] byt, int begin, int end) {
for (int i = begin; i < end; i++) {
src[i] = byt[(i - begin)];
}
return src;
}
/**
* @param oneByte 源字节数组
* @param row 行
* @param column 列
* @return 二维数组
*/
public static byte[][] oneByteArrayToTwoByteArray(byte[] oneByte, int row, int column) {
byte[][] twoByte = new byte[row][column];
if (row * column == oneByte.length) {
for (int i = 0; i < row; i++)
System.arraycopy(oneByte, i * column, twoByte[i], 0, column);
} else {
return (byte[][]) null;
}
return twoByte;
}
/**
* @param twoByte 源二维数组
* @return 字节数组
*/
public static byte[] twoByteArrayToOneByteArray(byte[][] twoByte) {
int len = 0;
for (int i = 0; i < twoByte.length; i++) {
len += twoByte[i].length;
}
byte[] oneByte = new byte[len];
int index = 0;
for (int i = 0; i < twoByte.length; i++) {
for (int j = 0; j < twoByte[i].length; j++) {
oneByte[(index++)] = twoByte[i][j];
}
}
return oneByte;
}
public static void main(String[] args) throws Exception {
byte[][] data = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}};
System.out.println("原数组:");
print(data);
System.out.println("置换后的数组:");
reverdraSort(data);
}
/**
* @param array 二维数组
* @return 二维数组反转后的排序
*/
public static byte[][] reverdraSort(byte[][] array) {
int row = array.length;
int col = array[0].length;
byte[][] arrayT = new byte[row][col];
for (int i = 0; i < row; i++) {
arrayT[i] = array[(row - i - 1)];
}
return arrayT;
}
/**
* @param arr 二维数组
*/
public static void print(byte[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + ",");
}
System.out.println();
}
System.out.println();
}
/**
* 得到位图头文件
* 完整的位图的文件是由:位图文件头,位图信息头,位图颜色表,位图像素数据构成
*
* @param w 图片款
* @param h 图片高
* @param forward 是否正向(旋转)
* @return 得到bmd文件头
*/
public static byte[] getBmpHead(int w, int h, boolean forward) {
byte[] COLOR_TABLE = addBMP8ImageInfosHeaderTable(w, h);
byte[] INFOS = addBMP8ImageInfosHeader(w, h);
byte[] INVERINFOS = addBMP8ImageInfosInvoHeader(w, h);
byte[] HEADER = addBMP8ImageHeader(w * h, COLOR_TABLE.length + INFOS.length);
byte[] BMP8GRAYHEADINFO = mergeBmpHead(HEADER, INFOS, COLOR_TABLE);
byte[] BMP8GRAYHEADINFO_INVER = mergeBmpHead(HEADER, INVERINFOS, COLOR_TABLE);
if (forward) {
return BMP8GRAYHEADINFO;
}
return BMP8GRAYHEADINFO_INVER;
}
/**
* 增加位图颜色表
*
* @param w 位图宽
* @param h 位图高
* @return 字节数组位图信息头
*/
private static byte[] addBMP8ImageInfosHeaderTable(int w, int h) {
byte[] buffer = new byte[1024];
for (int i = 0; i < 256; i++) {
buffer[(0 + 4 * i)] = (byte) i;
buffer[(1 + 4 * i)] = (byte) i;
buffer[(2 + 4 * i)] = (byte) i;
buffer[(3 + 4 * i)] = 0;
}
return buffer;
}
/**
* 增加位图反转信息头
*
* @param w 图片宽
* @param h 图片高
* @return 字节数组位图反转信息头
*/
private static byte[] addBMP8ImageInfosInvoHeader(int w, int h) {
byte[] buffer = new byte[40];
int ll = buffer.length;
buffer[0] = (byte) (ll >> 0);
buffer[1] = (byte) (ll >> 8);
buffer[2] = (byte) (ll >> 16);
buffer[3] = (byte) (ll >> 24);
buffer[4] = (byte) (w >> 0);
buffer[5] = (byte) (w >> 8);
buffer[6] = (byte) (w >> 16);
buffer[7] = (byte) (w >> 24);
buffer[8] = (byte) (h >> 0);
buffer[9] = (byte) (h >> 8);
buffer[10] = (byte) (h >> 16);
buffer[11] = (byte) (h >> 24);
buffer[12] = 1;
buffer[13] = 0;
buffer[14] = 8;
buffer[15] = 0;
buffer[16] = 0;
buffer[17] = 0;
buffer[18] = 0;
buffer[19] = 0;
buffer[20] = 0;
buffer[21] = 0;
buffer[22] = 0;
buffer[23] = 0;
buffer[24] = 32;
buffer[25] = 78;
buffer[26] = 0;
buffer[27] = 0;
buffer[28] = 32;
buffer[29] = 78;
buffer[30] = 0;
buffer[31] = 0;
buffer[32] = 0;
buffer[33] = 0;
buffer[34] = 0;
buffer[35] = 0;
buffer[36] = 0;
buffer[37] = 0;
buffer[38] = 0;
buffer[39] = 0;
return buffer;
}
/**
* 增加位图信息头
*
* @param w 图片宽
* @param h 图片高
* @return 位图信息头
*/
private static byte[] addBMP8ImageInfosHeader(int w, int h) {
byte[] buffer = new byte[40];
int ll = buffer.length;
buffer[0] = (byte) (ll >> 0);
buffer[1] = (byte) (ll >> 8);
buffer[2] = (byte) (ll >> 16);
buffer[3] = (byte) (ll >> 24);
buffer[4] = (byte) (w >> 0);
buffer[5] = (byte) (w >> 8);
buffer[6] = (byte) (w >> 16);
buffer[7] = (byte) (w >> 24);
buffer[8] = (byte) (-h >> 0);
buffer[9] = (byte) (-h >> 8);
buffer[10] = (byte) (-h >> 16);
buffer[11] = (byte) (-h >> 24);
buffer[12] = 1;
buffer[13] = 0;
buffer[14] = 8;
buffer[15] = 0;
buffer[16] = 0;
buffer[17] = 0;
buffer[18] = 0;
buffer[19] = 0;
buffer[20] = 0;
buffer[21] = 0;
buffer[22] = 0;
buffer[23] = 0;
buffer[24] = 32;
buffer[25] = 78;
buffer[26] = 0;
buffer[27] = 0;
buffer[28] = 32;
buffer[29] = 78;
buffer[30] = 0;
buffer[31] = 0;
buffer[32] = 0;
buffer[33] = 0;
buffer[34] = 0;
buffer[35] = 0;
buffer[36] = 0;
buffer[37] = 0;
buffer[38] = 0;
buffer[39] = 0;
return buffer;
}
/**
* 增加位图文件头
*
* @param size 大小
* @param lenH 长度
* @return 位图文件头
*/
private static byte[] addBMP8ImageHeader(int size, int lenH) {
byte[] buffer = new byte[14];
int m_lenH = lenH + buffer.length;
size += m_lenH;
buffer[0] = 66;
buffer[1] = 77;
buffer[2] = (byte) (size >> 0);
buffer[3] = (byte) (size >> 8);
buffer[4] = (byte) (size >> 16);
buffer[5] = (byte) (size >> 24);
buffer[6] = 0;
buffer[7] = 0;
buffer[8] = 0;
buffer[9] = 0;
buffer[10] = (byte) (m_lenH >> 0);
buffer[11] = (byte) (m_lenH >> 8);
buffer[12] = (byte) (m_lenH >> 16);
buffer[13] = (byte) (m_lenH >> 24);
return buffer;
}
/**
* 合并位图数据
*
* @param header 文件头
* @param infos 信息头
* @param color_table 颜色表
* @return 完整的位图字节数组
*/
private static byte[] mergeBmpHead(byte[] header, byte[] infos, byte[] color_table) {
byte[] buffer = new byte[header.length + infos.length + color_table.length];
System.arraycopy(header, 0, buffer, 0, header.length);
System.arraycopy(infos, 0, buffer, header.length, infos.length);
System.arraycopy(color_table, 0, buffer, header.length + infos.length, color_table.length);
return buffer;
}
/**
* @param bytes bmp文件字节数组
* @return bmp文件高
*/
public static Integer getBmpHigh(byte[] bytes) {
Integer high = null;
if ((bytes != null) && (bytes.length > 1078)) {
byte[] highByte = subBytes(bytes, 22, 26);
high = Integer.valueOf(Math.abs(byteArrayToInt(highByte)));
}
return high;
}
}
package com.common;
import net.coobird.thumbnailator.Thumbnails;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.imageio.ImageIO;
import javax.xml.bind.DatatypeConverter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.*;
import java.lang.reflect.Field;
import java.text.DateFormat;
......@@ -47,20 +37,6 @@ public class buildFingerUtil {
out.close();
}
/**
* 将base64字符解码然后Thumbnails图片压缩
* @author zhouxiao
*/
public static String compressPic(String filepath) throws Exception {
ByteArrayOutputStream outstream = null;
byte[] buffer = new byte[1024];
outstream = new ByteArrayOutputStream(buffer.length);
Thumbnails.of(filepath).scale(0.5f).toOutputStream(outstream);
buffer = outstream.toByteArray();
//要去除空格
return new BASE64Encoder().encode(buffer).replaceAll("\\s*|\t|\r|\n","");
}
/**
* 生成通用Element节点
* @param el 根节点的上一个节点
* @param obj 节点属性名
......@@ -161,50 +137,6 @@ public class buildFingerUtil {
return listname;
}
/**
* 将文件读出来并通过base64加密,然后旋转图片
* @param file 根据文件路径new一个file对象
* @return
* @author zhouxiao
* @throws Exception
* size(width,height) 图片长宽
* rotate(角度),正数:顺时针 负数:逆时针
* scale(比例)
* keepAspectRatio(false) 默认是按照比例缩放的
* watermark(位置,水印图,透明度)
* outputFormat(图像格式)
* date:20210415之前这种方法压缩图片并存储xml打开报错
*/
public static String compressPic(File file) throws Exception {
ByteArrayInputStream in = null;
ByteArrayOutputStream outstream = null;
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int)file.length()];
int bytesRead = 0;
ByteArrayOutputStream bao = new ByteArrayOutputStream();
while ((bytesRead = inputFile.read(buffer)) != -1) {
bao.write(buffer, 0, bytesRead);
}
inputFile.close();
byte[] data = bao.toByteArray();
/*inputFile.read(buffer);
inputFile.close();*/
//System.out.println("以上是原始数据");
//System.out.println("下面是压缩后的数据");
in = new ByteArrayInputStream(data);
outstream = new ByteArrayOutputStream(buffer.length);
Thumbnails.of(in).scale(0.4f).rotate(180).toOutputStream(outstream);
//Thumbnails.of(in).size(640,640).keepAspectRatio(false).toOutputStream(outstream);
byte[] baoffer = outstream.toByteArray();
//String bufstr = new BASE64Encoder().encode(baoffer).replaceAll("\\s*|\t|\r|\n","");
//要去除空格
return new BASE64Encoder().encode(baoffer).replaceAll("\\s*|\t|\r|\n","");
}
/**
* 将文件读出来并通过base64加密
* @param file 根据文件路径new一个file对象
* @author zhouxiao
......@@ -235,74 +167,44 @@ public class buildFingerUtil {
writer.flush();
writer.close();
}
/**
* 原样读取图片的二进制字节流
* @param file
* @return
* @author zhouxiao
* @throws Exception
* 目前没用到
*/
public static byte[] readInputStream(File file) throws Exception {
//File file = new File(path);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int)file.length()];
inputFile.read(buffer);
int len = 0;
while ((len = inputFile.read(buffer)) != -1){
outputStream.write(buffer,0,len);
}
inputFile.close();
return outputStream.toByteArray();
}
/**
* 该方法的目的是解析xml文件
* 将xml字符串转换为Document对象
* @author zhouxiao
* @param xmlStr
* @return
*/
public static Document xmlStr2Document(String xmlStr){
Document document = null;
try{
document = DocumentHelper.parseText(xmlStr);
}catch(Exception e){
e.printStackTrace();
}
return document;
}
public static void image2RGB565Bmp(String filePath, String saveFileName) {
try {
BufferedImage sourceImg = ImageIO.read(new File(filePath));
int h = sourceImg.getHeight(), w = sourceImg.getWidth();
int[] pixel = new int[w * h];
PixelGrabber pixelGrabber = new PixelGrabber(sourceImg, 0, 0, w, h, pixel, 0, w);
pixelGrabber.grabPixels();
MemoryImageSource m = new MemoryImageSource(w, h, pixel, 0, w);
Image image = Toolkit.getDefaultToolkit().createImage(m);
BufferedImage buff = new BufferedImage(w, h, BufferedImage.TYPE_USHORT_565_RGB);
buff.createGraphics().drawImage(image, 0, 0 ,null);
ImageIO.write(buff, "bmp", new File(saveFileName));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
* 指纹图片入库-出库流程:
* 入库:
* 将8bit bmp文件转换为1维字节数组,这个数组包含:位图文件头,位图信息头,位图颜色表,位图数据四部分,
* 从数组的1078位置(位图数据从1078开始)开始截取,得到位图数据;
* 从数组的22-26位截取,得到bmp源文件的高;
* 从数组的18-22位截取,得到bmp源文件的宽;
* 然后结合位图数据,源文件的宽,高,将1维数组转换成2维数组并置换排序(Windows扫描默认从低位到高位);
* 将处理完的2维数组转成1维数组;
* 将1维数组转成Base64字符串,并格式化(注意:必须去掉空格,换行符);
* 最后将Base64字符串入库。
*
* 出库:
* 将入库的Base64字符串转成1维数组(位图数据);
* 得到指纹图片的宽高(源数据的宽高是640*640),设置位图文件头,位图信息头,位图颜色表;
* 将位图数据和上面的位图信息合并生成完整的bmp字节数组;
* 最后将字节数组转换成Bmp文件进行显示。
*/
//入库:需要的base64图片去头,按照从上到下扫描顺序
public static String Sbase2Tbase64str(String filename){
//1、将文件转换成Byte数组
byte[] ioByte = ToolUtil.getBytesByFile(filename);
//2、处理base64图片byte数组,去头,翻转
byte[] dealData = ToolUtil.dealBmpByByte(ioByte);
//3、2的字节数组转base64字符串
String base64Str = ToolUtil.byteArrayToBase64String(dealData);
assert base64Str != null;
//4、将3的字符串去空格换行
String formatBase64Str = ToolUtil.formatBase64String(base64Str);
return formatBase64Str;
}
/**
* 去掉图片的base64的头部
* @param baseurl
* @return
* @throws Exception
*/
public static String baseurlPhotos(String baseurl) {
return baseurl.substring(baseurl.indexOf(",") + 1);
//return baseurl.substring(1078,baseurl.length());
//出库:将base64图片加头还原成原图
public static void Tbase2Sbase64str(String formatBase64Str,String filePath,String fileName) throws IOException{
//1、base64字符串转字节数组
byte[] imageBytes = ToolUtil.base64StringToByteArray(formatBase64Str);
//2、将去头后的base64字符串还原,转换成字节数组
byte[] fingerprintBmpByte = ToolUtil.addHeadImage(imageBytes,640,640);
//3、将Byte数组转换成文件
ToolUtil.getFileByBytes(fingerprintBmpByte,filePath,fileName);
}
}
......@@ -16,7 +16,7 @@ import java.io.StringWriter;
import java.util.*;
/**
* Created by founder on 2021/7/2.
* Created by zhouxiao on 2021/7/2.
*/
@Service
public class fingerImgService {
......@@ -85,23 +85,12 @@ public class fingerImgService {
Map<String,String> map = new HashMap<>();
//读取每个图片的二进制流并通过base64加密
File readfile = new File(basePath+"\\"+rybh + "\\" + filelist[i]);
String filname = basePath+"\\"+rybh + "\\" + filelist[i];
try {
//byte[] imgStr = buildFingerUtil.readInputStream(readfile);//原始图片流
String imgStr1 = buildFingerUtil.encodeBase64File(readfile);//解密后的二进制bs64流
//String imgStr1 = buildFingerUtil.compressPic(basePath+"\\"+rybh + "\\" + filelist[i]);//先解压,然后压缩的二进制bs64流
//String imgStr1 = buildFingerUtil.compressPic(readfile);//压缩后的二进制bs64流
//String imgStr = buildFingerUtil.baseurlPhotos(imgStr1);
System.out.println("imgStr1==="+imgStr1);
/*String target = "F:/test/xzzw/eww"+i+".bmp";
buildFingerUtil.decoderBase64File(imgStr,target);
File xsfile = new File(target);
buildFingerUtil.xs(xsfile);*/
String imgStr = buildFingerUtil.Sbase2Tbase64str(filname);//解密后的二进制bs64流
System.out.println("imgStr==="+imgStr);
//处理照片
map.put(readfile.getPath(), imgStr1);
map.put(readfile.getPath(), imgStr);
list.add(map);
}catch(Exception e){
System.out.println("生成文件名和图片流对应关系异常"+e);
......
......@@ -6,7 +6,7 @@ import java.io.IOException;
import java.util.Properties;
/**
* Created by founder on 2021/6/28.
* Created by zhouxiao on 2021/6/28.
*/
@Service
public class fingerInfoAnalyService {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment