做习题的小伙伴在做试题的时候需要把Word文档中的习题切图制作成试题,由于没注意到Word转出的图片上有很多水印导致制作的资源很不美观。由于涉及的图片数量庞大几千上万张,如果用PS去处理也够我们UI喝一壶的。于是发扬技术解决一切问题的精神写了个图片批量处理水印程序。
效果预览
先看一下原图,是这样的
用程序处理后的结果是介个样子滴:
可以看到,水印基本已经无影无踪了。
分析
要实现这样的一个程序首先要了解关于图像的基本知识。我们平常所看到的JPG,PNG等图像在显示的时候是以像素为单位的。长300宽400像素的图片所有像素为300×400=120000个像素点。在ARGB的图像表示方法中,每个像素点有ARGB四个通道,
A代表透明度,取值范围0~255,
R代表三原色中的红,取值范围0~255,
G代表三原色中的绿,取值范围0~255,
B代表三原色中的蓝,取值范围0~255。
所以存储这些数据只需要4个8位二进制在Java中也就是一个int类型就行啦。所以这张图片显示在屏幕上所占用的内存至少是120000×32个字节。每种颜色都有特定的ARGB取值,所以我们要去除水印就是要把图片中特定范围的ARGB取值改为四个通道取值都是255的白色就行了。有了以上理论知识,再结合Java图像处理相关API,根据目标图像的特征提取出适当ARGB取值范围。可以使用qq或者纳克小工,PS等工具查看水印像素所对应的范围。
然后就可以写出一个去水印程序啦。
上代码
1. package com.jzhung.demo.core.image;
2.
3. import javax.imageio.ImageIO;
4. import javax.imageio.ImageWriter;
5. import javax.imageio.stream.ImageOutputStream;
6. import javax.net.ssl.HttpsURLConnection;
7. import java.awt.*;
8. import java.awt.image.BufferedImage;
9. import java.io.File;
10. import java.io.FileFilter;
11. import java.io.IOException;
12. import java.net.HttpURLConnection;
13. import java.net.URL;
14. import java.util.ArrayList;
15. import java.util.Iterator;
16. import java.util.List;
17. import java.util.Scanner;
18.
19. /**
20. * Created by Jzhung on 2017/2/27.
21. * 文档图片水印处理
22. */
23. public class ImageConverter {
24. private static List<File> fileList = new ArrayList<File>();
25.
26. public static void main(String[] args) {
27. System.out.println("输入需要去水印的图片所在的根目录回车(支持递归子目录):");
28. Scanner input = new Scanner(System.in);
29. String dir = input.nextLine().trim();
30.
31. System.out.println("输入转换后的存储目录:");
32. String saveDir = input.nextLine().trim();
33.
34. System.out.println("输入y开始");
35. String comfrm = input.nextLine().trim();
36. if (comfrm.equals("y")) {
37. convertAllImages(dir, saveDir);
38. } else {
39. System.out.println("您输入的不是y程序,程序退出");
40. }
41.
42. /*String dir = "E:\\data\\Desktop";
43. String saveDir = "E:\\data\\Desktop-convert";*/
44.
45. //replaceFolderImages(dir);
46. /*String srcFile = "E:\\data\\image\\img38.png";
47. String dstFile = "E:\\data\\image\\img38.png";
48. long begin = System.currentTimeMillis();
49. repleaceColor(srcFile, dstFile);
50. long time = System.currentTimeMillis() - begin;
51. System.out.println(time);*/
52. }
53.
54. private static void convertAllImages(String dir, String saveDir) {
55. File dirFile = new File(dir);
56. File saveDirFile = new File(saveDir);
57. dir = dirFile.getAbsolutePath();
58. saveDir = saveDirFile.getAbsolutePath();
59. loadImages(new File(dir));
60. for (File file : fileList) {
61. String filePath = file.getAbsolutePath();
62.
63. String dstPath = saveDir + filePath.substring(filePath.indexOf(dir) + dir.length(), filePath.length());
64. System.out.println("converting: " + filePath);
65. replaceColor(file.getAbsolutePath(), dstPath);
66. }
67. }
68.
69. public static void loadImages(File f) {
70. if (f != null) {
71. if (f.isDirectory()) {
72. File[] fileArray = f.listFiles();
73. if (fileArray != null) {
74. for (int i = 0; i < fileArray.length; i++) {
75. //递归调用
76. loadImages(fileArray[i]);
77. }
78. }
79. } else {
80. String name = f.getName();
81. if (name.endsWith("png") || name.endsWith("jpg")) {
82. fileList.add(f);
83. }
84. }
85. }
86. }
87.
88. private static void replaceFolderImages(String dir) {
89. File dirFile = new File(dir);
90. File[] files = dirFile.listFiles(new FileFilter() {
91. public boolean accept(File file) {
92. String name = file.getName();
93. if (name.endsWith("png") || name.endsWith("jpg")) {
94. return true;
95. }
96. return false;
97. }
98. });
99. for (File img : files) {
100. replaceColor(img.getAbsolutePath(), img.getAbsolutePath());
101. }
102. }
103.
104. private static void replaceColor(String srcFile, String dstFile) {
105. try {
106. Color color = new Color(255, 195, 195);
107. replaceImageColor(srcFile, dstFile, color, Color.WHITE);
108. } catch (IOException e) {
109. e.printStackTrace();
110. }
111. }
112.
113. public static void replaceImageColor(String file, String dstFile, Color srcColor, Color targetColor) throws IOException {
114. URL http;
115. if (file.trim().startsWith("https")) {
116. http = new URL(file);
117. HttpsURLConnection conn = (HttpsURLConnection) http.openConnection();
118. conn.setRequestMethod("GET");
119. } else if (file.trim().startsWith("http")) {
120. http = new URL(file);
121. HttpURLConnection conn = (HttpURLConnection) http.openConnection();
122. conn.setRequestMethod("GET");
123. } else {
124. http = new File(file).toURI().toURL();
125. }
126. BufferedImage bi = ImageIO.read(http.openStream());
127. if(bi == null){
128. return;
129. }
130.
131. Color wColor = new Color(255, 255, 255);
132. for (int i = 0; i < bi.getWidth(); i++) {
133. for (int j = 0; j < bi.getHeight(); j++) {
134. //System.out.println(bi.getRGB(i, j));
135. int color = bi.getRGB(i, j);
136. Color oriColor = new Color(color);
137. int red = oriColor.getRed();
138. int greed = oriColor.getGreen();
139. int blue = oriColor.getBlue();
140. //粉色
141. if (greed < 190 || blue < 190) {
142.
143. } else {
144. if (red == 255 && greed > 180 && blue > 180) {
145. bi.setRGB(i, j, wColor.getRGB());
146. }
147. }
148. }
149. }
150. String type = file.substring(file.lastIndexOf(".") + 1, file.length());
151. Iterator<ImageWriter> it = ImageIO.getImageWritersByFormatName(type);
152. ImageWriter writer = it.next();
153. File f = new File(dstFile);
154. f.getParentFile().mkdirs();
155. ImageOutputStream ios = ImageIO.createImageOutputStream(f);
156. writer.setOutput(ios);
157. writer.write(bi);
158. bi.flush();
159. ios.flush();
160. ios.close();
161. }
162. }