java-证件照合成
工具类:
1 package com.test1; 2 3 import javax.imageio.ImageIO; 4 import javax.swing.*; 5 import java.awt.*; 6 import java.awt.image.BufferedImage; 7 import java.io.ByteArrayInputStream; 8 import java.io.File; 9 import java.io.IOException; 10 import java.net.URL; 11 import java.util.Base64; 12 import java.util.Map; 13 14 /** 15 * @author cjq 16 * 身份证件工具类 17 */ 18 public class IdCardUtil8 { 19 20 private Font font = new Font("黑体", Font.BOLD, 90);// 添加字体的属性设置 21 22 private Graphics2D g = null; 23 24 private int fontsize = 0; 25 26 private int x = 0; 27 28 private int y = 0; 29 30 public static int color_range = 210; 31 32 /** 33 * 导入本地图片到缓冲区 34 */ 35 public BufferedImage loadImageLocal(String imgName) { 36 try { 37 return ImageIO.read(new File(imgName)); 38 } catch (IOException e) { 39 System.out.println(e.getMessage()); 40 } 41 return null; 42 } 43 44 /** 45 * 导入网络图片到缓冲区 46 */ 47 public BufferedImage loadImageUrl(String imgName) { 48 try { 49 URL url = new URL(imgName); 50 return ImageIO.read(url); 51 } catch (IOException e) { 52 System.out.println(e.getMessage()); 53 } 54 return null; 55 } 56 57 /** 58 * 生成新图片到本地 59 */ 60 public void writeImageLocal(String newImage, BufferedImage img) { 61 if (newImage != null && img != null) { 62 try { 63 File outputfile = new File(newImage); 64 ImageIO.write(img, "jpg", outputfile); 65 } catch (IOException e) { 66 System.out.println(e.getMessage()); 67 } 68 } 69 } 70 71 /** 72 * 设定文字的字体等 73 */ 74 public void setFont(String fontStyle, int fontSize) { 75 this.fontsize = fontSize; 76 this.font = new Font(fontStyle, Font.BOLD, fontSize); // 77 } 78 79 /** 80 * 修改图片,返回修改后的图片缓冲区(只输出一行文本) 81 * space 字体间距 82 */ 83 public BufferedImage modifyImage(BufferedImage img, Object content, int x, 84 int y, Integer space) { 85 86 try { 87 int w = img.getWidth(); 88 int h = img.getHeight(); 89 g = img.createGraphics(); 90 g.setBackground(Color.black); 91 g.setColor(Color.black);//设置字体颜色 92 if (this.font != null) { 93 g.setFont(this.font); 94 } 95 // 验证输出位置的纵坐标和横坐标 96 if (x >= h || y >= w) { 97 this.x = h - this.fontsize + 2; 98 this.y = w; 99 } else { 100 this.x = x; 101 this.y = y; 102 } 103 if (content != null) { 104 if (space != null && space > 0) { 105 String lineString = content.toString(); 106 // 绘制字符的时候添加间隔 107 for (int i = 0; i < lineString.length(); i++) { 108 g.drawString(String.valueOf(lineString.charAt(i)), this.x, this.y); 109 this.x += space; 110 } 111 } else { 112 g.drawString(content.toString(), this.x, this.y); 113 } 114 } 115 g.dispose(); 116 } catch (Exception e) { 117 System.out.println(e.getMessage()); 118 } 119 120 return img; 121 } 122 123 /** 124 * 图像合成 125 * 126 * @param b 127 * @param d 128 * @return 129 */ 130 public BufferedImage modifyImagetogeter(BufferedImage b, BufferedImage d, int x, int y) { 131 try { 132 // int w = b.getWidth(); 133 // int h = b.getHeight(); 134 g = d.createGraphics(); 135 g.drawImage(b, x, y, 800, 1000, null); //调整粘贴图片的位置 136 g.dispose(); 137 } catch (Exception e) { 138 System.out.println(e.getMessage()); 139 } 140 return d; 141 } 142 143 /** 144 * 指定身份证号码解析 145 * 146 * @param result 147 * @param idno 148 */ 149 public void defineIdno(Map<String, String> result, String idno) { 150 String sex = idno.substring(16, 17); 151 int i = Integer.parseInt(sex); 152 if (i % 2 == 0) { 153 sex = "女";//M 154 } else { 155 sex = "男";//F 156 } 157 result.put("idCardNo", idno);//更改身份证 158 result.put("year", idno.substring(6, 10));//更改年 159 result.put("month", idno.substring(10, 12));//更改月 160 result.put("day", idno.substring(12, 14));//更改日 161 result.put("sex", sex);//性别 162 } 163 164 165 /** 166 * base64 编码转换为 BufferedImage 167 * 图片白底转透明 168 * 169 * @param base64 170 * @return 171 */ 172 public BufferedImage base64ToBufferedImage(String base64) { 173 Base64.Decoder decoder = Base64.getDecoder(); 174 try { 175 byte[] bytes1 = decoder.decode(base64); 176 ByteArrayInputStream bais = new ByteArrayInputStream(bytes1); 177 BufferedImage bufferedImage = ImageIO.read(bais); 178 // 图片白底转透明 179 ImageIcon imageIcon = new ImageIcon(bufferedImage); 180 BufferedImage bf = new BufferedImage( 181 imageIcon.getIconWidth(), imageIcon.getIconHeight(), 182 BufferedImage.TYPE_4BYTE_ABGR); 183 Graphics2D g2D = (Graphics2D) bf.getGraphics(); 184 g2D.drawImage(imageIcon.getImage(), 0, 0, 185 imageIcon.getImageObserver()); 186 int alpha; 187 for (int j1 = bf.getMinY(); j1 < bf 188 .getHeight(); j1++) { 189 for (int j2 = bf.getMinX(); j2 < bf 190 .getWidth(); j2++) { 191 int rgb = bf.getRGB(j2, j1); 192 if (colorInRange(rgb)) { 193 alpha = 0; 194 } else { 195 alpha = 255; 196 } 197 rgb = (alpha << 24) | (rgb & 0x00ffffff); 198 bf.setRGB(j2, j1, rgb); 199 } 200 } 201 g2D.drawImage(bf, 0, 0, imageIcon.getImageObserver()); 202 return bf; 203 } catch (IOException e) { 204 e.printStackTrace(); 205 } 206 return null; 207 } 208 209 /** 210 * 转rgb 211 * 212 * @param color 213 * @return 214 */ 215 public boolean colorInRange(int color) { 216 int red = (color & 0xff0000) >> 16; 217 int green = (color & 0x00ff00) >> 8; 218 int blue = (color & 0x0000ff); 219 if (red >= color_range && green >= color_range && blue >= color_range) { 220 return true; 221 } 222 return false; 223 } 224 }
证件照正面生成
1 package com.test1; 2 3 import java.awt.image.BufferedImage; 4 import java.util.ArrayList; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 public class IDCardFront8 { 10 /** 11 * 身份证正面 12 * 13 * @param args 14 */ 15 public static void main(String[] args) { 16 IdCardUtil8 tt = new IdCardUtil8(); 17 Map<String, String> result = new HashMap<>(); 18 tt.defineIdno(result, "XXXXXXXXXXXXXXXXXX"); 19 String name = "张三"; 20 String address = "新疆XX县XXXX镇XX社区XXX路XXXX苑一期XX号楼X单元XXX室"; 21 String fileName = "F:\\IdcodeGenerater-master\\" + name + "Front8.jpg"; //生成文件名 22 BufferedImage d = tt.loadImageLocal("F:\\IdcodeGenerater-master\\sfzzm8.jpg"); //证件照正面模板 23 // BufferedImage b = tt.loadImageLocal("F:\\IdcodeGenerater-master\\cjq.jpg"); 24 String base64 = "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAB+AGYDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD2Wiik5pCA9aCQBycVla54gs9AtvPvGPPRVwSa8q8Q/FG9vpXjsGa2hU/KwOCR71VgPX7vVbGwQvdXMcQ9WbrWFd/EXw5aZzds5HZIya8Gv/EN/fyl57p3J65bNZj3DdqLCue+RfFjQHl2t5yJnG4pn9K6HT/FWjanj7JeI+fwP5Hmvl8TMGzU0V/NFICjEY6GiwXPrBXR/usD9DS85r5v0fxtrWlTCSG+kaPvEx+U16h4X+KdhqhWDUgLWc8A5ypP1pWHc9BopqMroGUgqRkEd6dSAKKWigYlNYlUJ9BTqjmZkidgBwpPNAjwH4ieIbnUfEV1A0h8q3kaOMA9hXGNIWU+9aOvObnWrmTAy8hJx61qaL4YW/gWSQsM+gpuSii4wcmcntNOCHGa9EHgS1PAYn/gIp6eAYN2S2V9MCsvbI29gzzgKT0oKkdq9OHgWzHRP/HaZJ4Jsh1X9KPbIXsGebK2Bip4ZWjdXU4IOa7S78I2UcR8sYbtxXHajZvZXDRnOAaqNRSZEqTij6D+Hesf2x4XgZj88CiN/qB/hiurrzP4KS7tCvF44lUdPavTK0ZkLRRRUDEqO4XfBIn95SP0qSmyf6tvpVIR8x3dsP7akTH8Veg6FF5FjGvTArmr2wI8YXsGP9XcOB9AeK6qKRbaPDHFc9V30OyitLmrGQzAGrixqvSs+xu7ZsGRZAfdDW1CkU6b4iCtc6gdbkVjxVeYA5zWoYIwMvWfdy2keQd5PsuaOUSkZFzCpJIrg/Flr/pG7HUE13VxdR7iFDAe64rnPEUAuLUyrzt4q6ekjOr70TqfgnDt0O+b/psv/oNem1wPwgg8nwxM+OJJ8/kAK76u1u55wUUUUhBTHdVHzkAe9PrP1pc6e31FJuyKirux53rGlpB40ubhQCsxLhh0OR/jVgxLEPNwcj0FTT2qrMHUdetW7eASjmuaTu7noRjyqxkXOt3Vt5EcenCZZTwxJyPrjp1roreQM3yoEx1Ap8NlHEjADrTSqxuFHapuMluGBU5NYWq6mdOiDJZrcDODtJz+la83K89M05LcSDLU0xNHOSTpdgrLbmFzj5RyPzrI1S3K2jwrXaXGnxglwOa56/iD3YjI6mlfUdro6r4d24s/CdpCzL5jguyg88muq5rjvDcPlalGqfdRSP0rsq6ou6OCpHldgoooqzMSq97H51s6Edsj61ZpGAYYNS1dDi7O5wMpkVmRhypwas2B6VsajooYyzRn7xLEVlWybFBFc8lY741OY0sg9aozcXOTnbVjzBjJNVpZ0D5LjH1qNzSzG3M0RwqB84z92rVmS1spb72OarfaoX+VWqeGVVGNwz7UbBZiXblENcxcEvqAYe9dHetvQ81R0nSJb+aWQKCkbAE/WnFXJlPlRu+GbUiJ7lhy2Nv0rfFRWlulrbJCgwqKAKmrqirI4Jy5ncKKKKZAUhOB1ArzPVvjDbx5XS7LzR2klYr/AOOj/GuJ1P4j+JNRct/aTW6H/lnAAgH49fzNVYR77LJCIWMkqKpGCSwArkpLm2S9kgiuIpFz8uxwePwrxG71e/uV8y7vJZN399s1f8P37WuoWvlHmVsH8QayqLQ3pOzPY8qycGqstkkjbiuT6VnW+oupCyZArThvojz5i49zXLsdylYhNkMY8sL7ipYIvJ6kmpnv7c8eYM/Ws271RInKIdx9ulJspyuW7mTzGESnJY4A9TXU6PZfYdPjjIAcjc+PWvJfEPiC902FLu2kEMwkGxsBsHnsRVSy+Lfia2kUXC214o6702Mf++cD9K6aS0ucVaXQ90o6V5da/GmFiBeaQ8R9I5N2PzxXS6T8SfD2pssZuvs8jdBMu0fn0rY5jrqKYsiOgdGDqehXkGikM+VJ98QPHSoI90rbscVevGWaVliBMeeC3U/WmRxrFFtFWIivlZ7MbR90ip9Hk2XFpIeqyL/OgMvl7G59qah2KqxoAVbdn8v8P1qZK6Ki7M9kht1miVsZUjipP7HgkGSNv0FY3g7xBDfWaWk8gS4jAABPBHeuwVQcehrklGx2Rlcxm0OHtKxHpio/7MijbaEH1rceMKeKr3DRxRNJI20Dqai1y72PO/HtuEs4k/6bAj8jXDGRluQRXVeNdYGoXywQtlIs856mueitgU3sPmFdVNWRyVNWK6tPNhjgmoJt1pcbSwK4POamlEjNkCqs8LvnlfoTWpidn4J+Id34dSWCUtcWjKNkZbHlkenB4xmiuIihaNcEUUAWAzAk04OW60PUe4imMk2/NmpFHNMjYt1qRvl6UDHbpYXE0MjRyL0ZeorqNJ+I2o2Uaw3qrdqv8Z4b865hPnXmqt0oUnFRKCZak0j0mT4o2pHy2T7uy5A/Wua13x3famrQxhbeI9VVic1x3mHdirVrEskoDDIxmp5Eg9oyW3jkmlDuuABV7kdSB+NVJ7h4/kjOz6VArO4y7lj6mtEtCHJtl15lU8NWVeOzT7xUxUCoJelAmCTTFaKfB9yimSf/2Q=="; 25 BufferedImage b = tt.base64ToBufferedImage(base64); 26 //合并图片 27 tt.writeImageLocal(fileName, tt.modifyImagetogeter(b, d, 1600, 200)); 28 //往图片上写文字 29 tt.writeImageLocal(fileName, tt.modifyImage(d, name, 480, 320, 0)); //姓名 30 tt.writeImageLocal(fileName, tt.modifyImage(d, result.get("sex"), 480, 510, 0)); //性别 31 tt.writeImageLocal(fileName, tt.modifyImage(d, "汉", 1050, 510, 0)); //民族 32 tt.writeImageLocal(fileName, tt.modifyImage(d, result.get("year") + " " + result.get("month") + " " + result.get("day"), 480, 695, 0)); //出生年月 33 34 List<String> data = new ArrayList<String>(); 35 int iLen = address.length(); 36 while (iLen >= 11) { 37 String tmp = address.substring(0, 11); 38 data.add(tmp); 39 address = address.substring(11); 40 iLen = address.length(); 41 } 42 for (int i = 0; i < data.size(); i++) { 43 tt.writeImageLocal(fileName, tt.modifyImage(d, data.get(i), 480, 915 + 90 * i, 0)); //住址 44 } 45 tt.writeImageLocal(fileName, tt.modifyImage(d, result.get("idCardNo"), 890, 1415, 70)); //身份证号 46 System.out.println("身份证正面生成成功~!"); 47 } 48 }
证件照反面生成
1 package com.test1; 2 3 import java.awt.image.BufferedImage; 4 5 public class IDCardReverse8 { 6 7 /** 8 * 身份证反面 9 * 10 * @param args 11 */ 12 public static void main(String[] args) { 13 IdCardUtil8 tt = new IdCardUtil8(); 14 String name = "张三"; 15 String fileName = "F:\\IdcodeGenerater-master\\" + name + "Back8.jpg"; //生成文件名 16 BufferedImage d = tt.loadImageLocal("F:\\IdcodeGenerater-master\\sfzfm8.jpg"); //证件照反面模板 17 String police = "伊宁县公安局"; 18 String userlifeb = "20210329"; 19 String userlifee = "20410329"; 20 StringBuffer sb1 = new StringBuffer(); 21 sb1.append(userlifeb).insert(4, ".").insert(7, ".").append("-").append(userlifee).insert(15, ".").insert(18, "."); 22 //往图片上写文字 23 tt.writeImageLocal(fileName, tt.modifyImage(d, police, 1070, 1220, 0)); //签发机关 24 tt.writeImageLocal(fileName, tt.modifyImage(d, sb1.toString(), 1070, 1390, 0)); //有效期限 25 System.out.println("身份证反面生成成功~!"); 26 } 27 }
参考文献
https://my.oschina.net/u/3563297/blog/1512251
Linux环境下Graphics drawString 中文乱码解决方法
可以有两种方法添加服务器端的中文支持:
在/usr/share/fonts放ttf,ttc等文件 然后给777权限
cd /usr/share/fonts
mkdir winFonts
cp /home/dragon/Desktop/simsun.ttc winFonts
cp /home/dragon/Desktop/simfang.ttf winFonts
cp /home/dragon/Desktop/simhei.ttf winFonts
cp /home/dragon/Desktop/simkai.ttf winFonts
cp /home/dragon/Desktop/msyh.ttc winFonts
cp /home/dragon/Desktop/msyhl.ttc winFonts
cp /home/dragon/Desktop/msyhbd.ttc winFonts
cd winFonts
mkfontdir
mkfontscale
先从本机 C:\Windows\Fonts 拷贝系统文字
如果/home/dragon/Desktop不存在,则先从本机 C:\Windows\Fonts 直接拷贝ttf,ttc等文件到/usr/share/fonts/winFonts下
参考文献:
https://www.jianshu.com/p/0e7c151b8565
https://www.likecs.com/show-308185602.html
当能力支撑不了野心时,就该静下心来学习!