1,前面有一篇已经介绍tesseract-OCR的简单实用和识别,因识别率不高,特意将图片实用opencv处理后,再次进行识别,经过测试,识别率高了30%左右
2,实用opcv整合tesseract-OCR需要的jar包,此处的识别已经不再通过调用windows系统命令,而通过tesseract-OCR工具类tess4j.jar完成。(实际上tess4j也是调用系统命令)
3,注意到上面有个opencv_java320.dll(32位和64位,根据你的jdk决定,到时我发现在这儿其实好像加载不到,所以使用一下方法)
将opencv_java320.dll加入到系统库的Native library location(如图)
4,上代码,学过java的一看就明白
package com.njupt.zhb.test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
/**
* @author zwp
* @date 创建时间:2017年3月24日 下午5:12:12
* @version 2.0
* @parameter
* @since
* @return
*/
public class Test {
public static String test(String path) {
File imageFile=new File(path);
Tesseract instance=Tesseract.getInstance();
instance.setDatapath("C:\\Program Files (x86)\\Tesseract-OCR\\tessdata");//设置训练库的位置
//instance.setLanguage("chi_sim");//中文识别
instance.setLanguage("eng");//中文识别
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
return result;
} catch (TesseractException e) {
e.printStackTrace();
}
return "";
}
private final String LANG_OPTION = "-l";
private final String EOL = System.getProperty("line.separator");
/**
* 文件位置我防止在,项目同一路径
*/
private String tessPath = new File("tesseract").getAbsolutePath();
/**
* @param imageFile
* 传入的图像文件
* @param imageFormat
* 传入的图像格式
* @return 识别后的字符串
*/
public String recognizeText(File imageFile) throws Exception
{
/**
* 设置输出文件的保存的文件目录
*/
File outputFile = new File(imageFile.getParentFile(), "output");
StringBuffer strB = new StringBuffer();
List cmd = new ArrayList();
String os = System.getProperty("os.name");
if(os.toLowerCase().startsWith("win")){
cmd.add("tesseract");
}else {
cmd.add("tesseract");
}
// cmd.add(tessPath + "\\tesseract");
cmd.add(imageFile.getName());
cmd.add(outputFile.getName());
// cmd.add(LANG_OPTION);
// cmd.add("chi_sim");
cmd.add("digits");
// cmd.add("eng");
// cmd.add("-psm 7");
ProcessBuilder pb = new ProcessBuilder();
/**
*Sets this process builder's working directory.
*/
pb.directory(imageFile.getParentFile());
// cmd.set(1, imageFile.getName());
pb.command(cmd);
pb.redirectErrorStream(true);
Process process = pb.start();
// Process process = pb.command("ipconfig").start();
// System.out.println(System.getenv().get("Path"));
// Process process = pb.command("D:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe",imageFile.getName(),outputFile.getName(),LANG_OPTION,"eng").start();
// tesseract.exe 1.jpg 1 -l chi_sim
// Runtime.getRuntime().exec("tesseract.exe 1.jpg 1 -l chi_sim");
/**
* the exit value of the process. By convention, 0 indicates normal
* termination.
*/
// System.out.println(cmd.toString());
int w = process.waitFor();
if (w == 0)// 0代表正常退出
{
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(outputFile.getAbsolutePath() + ".txt"),
"UTF-8"));
String str;
while ((str = in.readLine()) != null)
{
strB.append(str).append(EOL);
}
in.close();
} else
{
String msg;
switch (w)
{
case 1:
msg = "Errors accessing files. There may be spaces in your image's filename.";
break;
case 29:
msg = "Cannot recognize the image or its selected region.";
break;
case 31:
msg = "Unsupported image format.";
break;
default:
msg = "Errors occurred.";
}
throw new RuntimeException(msg);
}
new File(outputFile.getAbsolutePath() + ".txt").delete();
return strB.toString().replaceAll("\\s*", "");
}
/*public static void main(String[] args) throws Exception {
Tesseract("d:\\2.png");
Tesseract("/2.png");
Tesseract("/3.png");
Tesseract("/4.png");
Tesseract("/5.png");
Tesseract("/6.png");
}
*/
private static void Tesseract(String fileString) throws Exception {
// String filePath = Test.class.getResource(fileString).getFile().toString();
// processImg(filePath);
File file = new File(fileString);
String recognizeText = new Test().recognizeText(file);
System.out.println(recognizeText);
}
}
package com.njupt.zhb.test;
import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.objdetect.CascadeClassifier;
public class Main {
private static final Double avatarSpacePer = 0.16;
private static final Double avatarPer = 0.28;
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* System.loadLibrary("opencv_java320"); Mat m = Mat.eye(3, 3,
* CvType.CV_8UC1); System.out.println("m = " + m.dump());
*/
System.loadLibrary("opencv_java320");
/*
* Mat mat = Imgcodecs.imread("d:/data/1.jpg"); System.out.println(mat);
*/
File file = new File("d:/data");
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
test(f.getPath());
}
}
// test("d:/data/1.png");
}
private static void test(String fileName) {
int index = fileName.lastIndexOf("\\");
String suffix = index != -1 ? fileName.substring(index + 1) : ".png";
int[] rectPosition = detectFace(fileName);
System.out.println("x=" + rectPosition[0] + " y=" + rectPosition[1] + " width=" + rectPosition[2] + " height="
+ rectPosition[3]);
int x = rectPosition[0];
int y = rectPosition[1];
int w = rectPosition[2];
int h = rectPosition[3];
int[] imgRect = new int[2];
try {
imgRect = getImageWidth(fileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
/*
* if(x == 0 || y == 0 || w == 0 || h == 0 ){
* System.out.println("人脸识别失败:" + fileName + " 把身份证变成黑白照片再次进行识别");
* String destFile = "d:/data/temp" + suffix;
* //convertBackWhiteImage(fileName, destFile); changeImge(new
* File(fileName)); rectPosition = detectFace(fileName); // rectPosition
* = detectFace(destFile); System.out.println("x=" + rectPosition[0] +
* " y=" + rectPosition[1] + " width=" + rectPosition[2] + " height=" +
* rectPosition[3]);
*
* x = rectPosition[0]; y = rectPosition[1]; w = rectPosition[2]; h =
* rectPosition[3]; }
*/
if (x == 0 || y == 0 || w == 0 || h == 0) {
x = imgRect[0];
y = imgRect[1];
w = (int) (x * avatarPer);
h = w;
System.out.println("人脸识别失败:" + fileName + " 采用默认识别");
}
/*
* int cutX = x/4 + 20; int cutY = (y + h ) *2;
*/
int cutX = x / 2 - 20;
String destFile = "d:/data/idcard" + suffix;
int width = imgRect[0] - cutX - 30;
// ImageUtils.cut(fileName, destFile, cutX, cutY, width/2, 120);
// ImageUtils.cut(fileName, "d:/data/avatar.jpg", x, y, w, h);
int cutHeight = 140;
int imgHieght = imgRect[1];
int topSpace = (int) (imgHieght * avatarPer);
int height = (int) (imgHieght * avatarSpacePer);
int cutY = y + h + height;
if (imgHieght - cutY < cutHeight - 5) {
cutY = imgHieght - (int) (imgHieght / 3.8) - 10;
}
if (imgHieght < 500) {
cutY = cutY + 20;
}
new Main().cutImage(fileName, destFile, cutX, cutY, width, cutHeight);
Test.test(destFile);
}
/**
* 图片转换成黑白图片
*
* @param fileName
* @param destFile
*/
public static void convertBackWhiteImage(String fileName, String destFile) {
OutputStream output = null;
String suffix = null;
String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
// 获取图片后缀
if (fileName.indexOf(".") > -1) {
suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
} // 类型和图片后缀全部小写,然后判断后缀是否合法
if (suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase() + ",") < 0) {
return;
}
try {
BufferedImage sourceImg = replaceWithWhiteColor(ImageIO.read(new FileInputStream(fileName)));
output = new FileOutputStream(destFile);
ImageIO.write(sourceImg, suffix, output);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (output != null)
try {
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 把图像处理成黑白照片
*
* @param bi
* @return
*/
public static BufferedImage replaceWithWhiteColor(BufferedImage bi) {
int[] rgb = new int[3];
int width = bi.getWidth();
int height = bi.getHeight();
int minx = bi.getMinX();
int miny = bi.getMinY();
/**
*
* 遍历图片的像素,为处理图片上的杂色,所以要把指定像素上的颜色换成目标白色 用二层循环遍历长和宽上的每个像素
*
*/
int hitCount = 0;
for (int i = minx; i < width - 1; i++) {
for (int j = miny; j < height; j++) {
/**
*
* 得到指定像素(i,j)上的RGB值,
*
*/
int pixel = bi.getRGB(i, j);
int pixelNext = bi.getRGB(i + 1, j);
/**
*
* 分别进行位操作得到 r g b上的值
*
*/
rgb[0] = (pixel & 0xff0000) >> 16;
rgb[1] = (pixel & 0xff00) >> 8;
rgb[2] = (pixel & 0xff);
/**
*
* 进行换色操作,我这里是要换成白底,那么就判断图片中rgb值是否在范围内的像素
*
*/
// 经过不断尝试,RGB数值相互间相差15以内的都基本上是灰色,
// 对以身份证来说特别是介于73到78之间,还有大于100的部分RGB值都是干扰色,将它们一次性转变成白色
if ((Math.abs(rgb[0] - rgb[1]) < 15)
&& (Math.abs(rgb[0] - rgb[2]) < 15)
&& (Math.abs(rgb[1] - rgb[2]) < 15) &&
(((rgb[0] > 73) && (rgb[0] < 78)) || (rgb[0] > 100))) {
// 进行换色操作,0xffffff是白色
bi.setRGB(i, j, 0xffffff);
}
}
}
return bi;
}
public static int[] getImageWidth(String fileName) throws FileNotFoundException, IOException {
File picture = new File(fileName);
BufferedImage sourceImg = ImageIO.read(new FileInputStream(picture));
int[] imgRect = new int[2];
imgRect[0] = sourceImg.getWidth();
imgRect[1] = sourceImg.getHeight();
return imgRect;
}
public static int[] detectFace(String fileName) {
int[] rectPosition = new int[4];
CascadeClassifier faceDetector = new CascadeClassifier("./data/lbpcascade_frontalface.xml");
Mat image = Imgcodecs.imread(fileName);
MatOfRect faceDetections = new MatOfRect();
Size minSize = new Size(120, 120);
Size maxSize = new Size(250, 250);
faceDetector.detectMultiScale(image, faceDetections, 1.1f, 4, 0, minSize, maxSize);
System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
for (Rect rect : faceDetections.toArray()) {
System.out.println(rect.toString());
rectPosition[0] = rect.x;
rectPosition[1] = rect.y;
rectPosition[2] = rect.width;
rectPosition[3] = rect.height;
}
/*
* String filename = "d:/data/avatar.jpg";
* System.out.println(String.format("Writing %s", filename));
* Imgcodecs.imwrite(filename, image);
*/
return rectPosition;
}
/**
*
* Title: cutImage
*
*
* Description: 根据原图与裁切size截取局部图片
*
*
* @param srcImg
* 源图片
* @param output
* 图片输出流
* @param rect
* 需要截取部分的坐标和大小
*/
public void cutImage(File srcImg, File destImg, java.awt.Rectangle rect) {
if (srcImg.exists()) {
java.io.FileInputStream fis = null;
ImageInputStream iis = null;
OutputStream output = null;
try {
fis = new FileInputStream(srcImg);
// ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG,
// JPEG, WBMP, GIF, gif]
String types = Arrays.toString(ImageIO.getReaderFormatNames()).replace("]", ",");
String suffix = null;
// 获取图片后缀
if (srcImg.getName().indexOf(".") > -1) {
suffix = srcImg.getName().substring(srcImg.getName().lastIndexOf(".") + 1);
} // 类型和图片后缀全部小写,然后判断后缀是否合法
if (suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase() + ",") < 0) {
return;
}
// 将FileInputStream 转换为ImageInputStream
iis = ImageIO.createImageInputStream(fis);
// 根据图片类型获取该种类型的ImageReader
ImageReader reader = ImageIO.getImageReaders(new FileImageInputStream(srcImg)).next(); // ImageIO.getImageReadersBySuffix(suffix).next();
reader.setInput(iis, true);
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(rect);
BufferedImage bi = reader.read(0, param);
output = new FileOutputStream(destImg);
ImageIO.write(bi, suffix, output);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if (iis != null)
iis.close();
if (output != null)
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
}
}
public void cutImage(String srcImg, String destImg, int x, int y, int width, int height) {
cutImage(new File(srcImg), new File(destImg), new java.awt.Rectangle(x, y, width, height));
}
}
package com.njupt.zhb.test.util;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.simpleimage.ImageRender;
import com.alibaba.simpleimage.SimpleImageException;
import com.alibaba.simpleimage.render.ReadRender;
import com.alibaba.simpleimage.render.ScaleParameter;
import com.alibaba.simpleimage.render.ScaleRender;
import com.alibaba.simpleimage.render.WriteRender;
/**
* 图片处理工具类:
* 功能:缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等
*
*/
public class ImageUtils {
// 缩略图宽度
public static int SMALL_IMG_WIDTH = 240;
// 缩略图高度
public static int SMALL_IMG_HEIGHT = 240;
static {
System.setProperty("com.sun.media.jai.disableMediaLib", "true");
}
/**
* 几种常见的图片格式
*/
public static String IMAGE_TYPE_GIF = "gif";// 图形交换格式
public static String IMAGE_TYPE_JPG = "jpg";// 联合照片专家组
public static String IMAGE_TYPE_JPEG = "jpeg";// 联合照片专家组
public static String IMAGE_TYPE_BMP = "bmp";// 英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式
public static String IMAGE_TYPE_PNG = "png";// 可移植网络图形
public static String IMAGE_TYPE_PSD = "psd";// Photoshop的专用格式Photoshop
/**
* 检查图片类型
*
* @param fileFileName2
* @return
*
*/
public static boolean checkType(String fileFileName) {
if (StringUtils.isBlank(fileFileName)) {
return false;
}
fileFileName = fileFileName.toLowerCase();
if ((!fileFileName.endsWith(IMAGE_TYPE_GIF) && !fileFileName.endsWith(IMAGE_TYPE_JPG)
&& !fileFileName.endsWith(IMAGE_TYPE_JPEG) && !fileFileName.endsWith(IMAGE_TYPE_BMP)
&& !fileFileName.endsWith(IMAGE_TYPE_PNG) && !fileFileName.endsWith(IMAGE_TYPE_PSD))) {
return false;
}
return true;
}
/**
* 程序入口:用于测试
*
* @param args
*/
public static void main2(String[] args) {
// 1-缩放图像:
// 方法一:按比例缩放
ImageUtils.scale("e:/abc.jpg", "e:/abc_scale.jpg", 2, true);// 测试OK
// 方法二:按高度和宽度缩放
ImageUtils.scale2("e:/abc.jpg", "e:/abc_scale2.jpg", 500, 300, true);// 测试OK
// 2-切割图像:
// 方法一:按指定起点坐标和宽高切割
ImageUtils.cut("e:/abc.jpg", "e:/abc_cut.jpg", 0, 0, 400, 400);// 测试OK
// 方法二:指定切片的行数和列数
ImageUtils.cut2("e:/abc.jpg", "e:/", 2, 2);// 测试OK
// 方法三:指定切片的宽度和高度
ImageUtils.cut3("e:/abc.jpg", "e:/", 300, 300);// 测试OK
// 3-图像类型转换:
ImageUtils.convert("e:/abc.jpg", "GIF", "e:/abc_convert.gif");// 测试OK
// 4-彩色转黑白:
ImageUtils.gray("e:/abc.jpg", "e:/abc_gray.jpg");// 测试OK
// 5-给图片添加文字水印:
// 方法一:
ImageUtils.pressText("我是水印文字", "e:/abc.jpg", "e:/abc_pressText.jpg", "宋体", Font.BOLD, Color.white, 80, 0, 0,
0.5f);// 测试OK
// 方法二:
ImageUtils.pressText2("我也是水印文字", "e:/abc.jpg", "e:/abc_pressText2.jpg", "黑体", 36, Color.white, 80, 0, 0, 0.5f);// 测试OK
// 6-给图片添加图片水印:
ImageUtils.pressImage("e:/abc2.jpg", "e:/abc.jpg", "e:/abc_pressImage.jpg", 0, 0, 0.5f);// 测试OK
}
/**
* 缩放图像(按比例缩放)
*
* @param srcImageFile
* 源图像文件地址
* @param result
* 缩放后的图像地址
* @param scale
* 缩放比例
* @param flag
* 缩放选择:true 放大; false 缩小;
*/
public final static void scale(String srcImageFile, String result, int scale, boolean flag) {
try {
synchronized (ImageUtils.class) {
BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
int width = src.getWidth(); // 得到源图宽
int height = src.getHeight(); // 得到源图长
if (flag) {// 放大
width = width * scale;
height = height * scale;
} else {// 缩小
int wScale = width / SMALL_IMG_WIDTH;
int hScale = height / SMALL_IMG_HEIGHT;
scale = wScale > hScale ? hScale : wScale;
scale = scale < 1 ? 1 : scale;
width = width / scale;
height = height / scale;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
ImageIO.write(tag, "JPEG", new File(result));// 输出到文件流
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 缩放图像(按比例缩放)
*
* @param srcImageFile
* 源图像文件地址
* @param result
* 缩放后的图像地址
* @param scale
* 缩放比例
* @param flag
* 缩放选择:true 放大; false 缩小;
*/
public final static void scale(String srcImageFile, String result, int scale, boolean flag, int wd, int he) {
try {
synchronized (ImageUtils.class) {
BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
int width = src.getWidth(); // 得到源图宽
int height = src.getHeight(); // 得到源图长
if (flag) {// 放大
width = width * scale;
height = height * scale;
} else {// 缩小
int wScale = width / wd;
int hScale = height / he;
scale = wScale > hScale ? hScale : wScale;
scale = scale < 1 ? 1 : scale;
width = width / scale;
height = height / scale;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
ImageIO.write(tag, "JPEG", new File(result));// 输出到文件流
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 缩放图像(按比例缩放)
*
* @param srcImageFile
* 源图像文件地址
* @param result
* 缩放后的图像地址
* @param scale
* 缩放比例t
* @param flag
* 缩放选择:true 放大; false 缩小;
*/
public final static void scaleByHeightAndWidth(int hightVal, int widthVal, String srcImageFile, String result, int scale, boolean flag) {
try {
synchronized (ImageUtils.class) {
BufferedImage src = ImageIO.read(new File(srcImageFile)); // 读入文件
int width = src.getWidth(); // 得到源图宽
int height = src.getHeight(); // 得到源图长
if (flag) {// 放大
width = width * scale;
height = height * scale;
} else {// 缩小
int wScale = width / widthVal;
int hScale = height / hightVal;
scale = wScale > hScale ? hScale : wScale;
scale = scale < 1 ? 1 : scale;
width = width / scale;
height = height / scale;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 绘制缩小后的图
g.dispose();
ImageIO.write(tag, "JPEG", new File(result));// 输出到文件流
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 缩放图像(按高度和宽度缩放)
*
* @param srcImageFile
* 源图像文件地址
* @param result
* 缩放后的图像地址
* @param height
* 缩放后的高度
* @param width
* 缩放后的宽度
* @param bb
* 比例不对时是否需要补白:true为补白; false为不补白;
*/
@SuppressWarnings("static-access")
@Deprecated
public final static void scale2(String srcImageFile, String result, int height, int width, boolean bb) {
try {
double ratio = 0.0; // 缩放比例
File f = new File(srcImageFile);
BufferedImage bi = ImageIO.read(f);
Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);
// 计算比例
if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
if (bi.getHeight() > bi.getWidth()) {
ratio = (new Integer(height)).doubleValue() / bi.getHeight();
} else {
ratio = (new Integer(width)).doubleValue() / bi.getWidth();
}
AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
itemp = op.filter(bi, null);
}
if (bb) {// 补白
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
if (width == itemp.getWidth(null))
g.drawImage(itemp, 0, (height - itemp.getHeight(null)) / 2, itemp.getWidth(null),
itemp.getHeight(null), Color.white, null);
else
g.drawImage(itemp, (width - itemp.getWidth(null)) / 2, 0, itemp.getWidth(null),
itemp.getHeight(null), Color.white, null);
g.dispose();
itemp = image;
}
ImageIO.write((BufferedImage) itemp, "JPEG", new File(result));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 缩放图像(按高度和宽度缩放)不裁剪
*
* @param srcImageFile
* 源图像文件地址
* @param result
* 缩放后的图像地址
* @param height
* 缩放后的高度
* @param width
* 缩放后的宽度
* @param bb
* 比例不对时是否需要补白:true为补白; false为不补白;
*/
@SuppressWarnings("static-access")
@Deprecated
public final static void scaleWithoutCut(String srcImageFile, String result, int height, int width, boolean bb) {
try {
File f = new File(srcImageFile);
BufferedImage bi = ImageIO.read(f);
int width1 = bi.getWidth(); // 得到源图宽
int height1 = bi.getHeight(); // 得到源图长
Image itemp = bi.getScaledInstance(width, height, bi.SCALE_SMOOTH);// 创建此图像的缩放版本。返回一个新的
// Image
// 对象,默认情况下,该对象按指定的
// width
// 和
// height
// 呈现图像。即使已经完全加载了初始源图像,新的
// Image
// 对象也可以被异步加载。
AffineTransformOp op = new AffineTransformOp(
AffineTransform.getScaleInstance(height1 / height, width1 / width), null);
itemp = op.filter(bi, null);
ImageIO.write((BufferedImage) itemp, "JPEG", new File(result));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 图像切割(按指定起点坐标和宽高切割)
*
* @param srcImageFile
* 源图像地址
* @param result
* 切片后的图像地址
* @param x
* 目标切片起点坐标X
* @param y
* 目标切片起点坐标Y
* @param width
* 目标切片宽度
* @param height
* 目标切片高度
*/
public final static void cut(String srcImageFile, String result, int x, int y, int width, int height) {
try {
// 读取源图像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getHeight(); // 源图宽度
int srcHeight = bi.getWidth(); // 源图高度
if (srcWidth > 0 && srcHeight > 0) {
Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
// 四个参数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
ImageFilter cropFilter = new CropImageFilter(x, y, width, height);
Image img = Toolkit.getDefaultToolkit()
.createImage(new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, width, height, null); // 绘制切割后的图
g.dispose();
// 输出为文件
ImageIO.write(tag, "JPEG", new File(result));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 图像切割(按指定起点坐标和宽高切割)无压缩
*
* @param srcImageFile
* 源图像地址
* @param result
* 切片后的图像地址
* @param x
* 目标切片起点坐标X
* @param y
* 目标切片起点坐标Y
* @param width
* 目标切片宽度
* @param height
* 目标切片高度
*/
public final static void cutWithoutScale(String srcImageFile, String result, int x, int y, int width, int height) {
try {
// 读取源图像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getHeight(); // 源图宽度
int srcHeight = bi.getWidth(); // 源图高度
if (srcWidth > 0 && srcHeight > 0) {
Image image = bi.getSubimage(x, y, width, height);
// 四个参数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
ImageFilter cropFilter = new CropImageFilter(x, y, width, height);
Image img = Toolkit.getDefaultToolkit()
.createImage(new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, width, height, null); // 绘制切割后的图
g.dispose();
// 输出为文件
ImageIO.write(tag, "JPEG", new File(result));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 图像切割(指定切片的行数和列数)
*
* @param srcImageFile
* 源图像地址
* @param descDir
* 切片目标文件夹
* @param rows
* 目标切片行数。默认2,必须是范围 [1, 20] 之内
* @param cols
* 目标切片列数。默认2,必须是范围 [1, 20] 之内
*/
public final static void cut2(String srcImageFile, String descDir, int rows, int cols) {
try {
if (rows <= 0 || rows > 20)
rows = 2; // 切片行数
if (cols <= 0 || cols > 20)
cols = 2; // 切片列数
// 读取源图像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getHeight(); // 源图宽度
int srcHeight = bi.getWidth(); // 源图高度
if (srcWidth > 0 && srcHeight > 0) {
Image img;
ImageFilter cropFilter;
Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
int destWidth = srcWidth; // 每张切片的宽度
int destHeight = srcHeight; // 每张切片的高度
// 计算切片的宽度和高度
if (srcWidth % cols == 0) {
destWidth = srcWidth / cols;
} else {
destWidth = (int) Math.floor(srcWidth / cols) + 1;
}
if (srcHeight % rows == 0) {
destHeight = srcHeight / rows;
} else {
destHeight = (int) Math.floor(srcWidth / rows) + 1;
}
// 循环建立切片
// 改进的想法:是否可用多线程加快切割速度
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 四个参数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
cropFilter = new CropImageFilter(j * destWidth, i * destHeight, destWidth, destHeight);
img = Toolkit.getDefaultToolkit()
.createImage(new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, null); // 绘制缩小后的图
g.dispose();
// 输出为文件
ImageIO.write(tag, "JPEG", new File(descDir + "_r" + i + "_c" + j + ".jpg"));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 图像切割(指定切片的宽度和高度)
*
* @param srcImageFile
* 源图像地址
* @param descDir
* 切片目标文件夹
* @param destWidth
* 目标切片宽度。默认200
* @param destHeight
* 目标切片高度。默认150
*/
public final static void cut3(String srcImageFile, String descDir, int destWidth, int destHeight) {
try {
if (destWidth <= 0)
destWidth = 200; // 切片宽度
if (destHeight <= 0)
destHeight = 150; // 切片高度
// 读取源图像
BufferedImage bi = ImageIO.read(new File(srcImageFile));
int srcWidth = bi.getHeight(); // 源图宽度
int srcHeight = bi.getWidth(); // 源图高度
if (srcWidth > destWidth && srcHeight > destHeight) {
Image img;
ImageFilter cropFilter;
Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
int cols = 0; // 切片横向数量
int rows = 0; // 切片纵向数量
// 计算切片的横向和纵向数量
if (srcWidth % destWidth == 0) {
cols = srcWidth / destWidth;
} else {
cols = (int) Math.floor(srcWidth / destWidth) + 1;
}
if (srcHeight % destHeight == 0) {
rows = srcHeight / destHeight;
} else {
rows = (int) Math.floor(srcHeight / destHeight) + 1;
}
// 循环建立切片
// 改进的想法:是否可用多线程加快切割速度
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 四个参数分别为图像起点坐标和宽高
// 即: CropImageFilter(int x,int y,int width,int height)
cropFilter = new CropImageFilter(j * destWidth, i * destHeight, destWidth, destHeight);
img = Toolkit.getDefaultToolkit()
.createImage(new FilteredImageSource(image.getSource(), cropFilter));
BufferedImage tag = new BufferedImage(destWidth, destHeight, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(img, 0, 0, null); // 绘制缩小后的图
g.dispose();
// 输出为文件
ImageIO.write(tag, "JPEG", new File(descDir + "_r" + i + "_c" + j + ".jpg"));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 图像类型转换:GIF->JPG、GIF->PNG、PNG->JPG、PNG->GIF(X)、BMP->PNG
*
* @param srcImageFile
* 源图像地址
* @param formatName
* 包含格式非正式名称的 String:如JPG、JPEG、GIF等
* @param destImageFile
* 目标图像地址
*/
public final static void convert(String srcImageFile, String formatName, String destImageFile) {
try {
File f = new File(srcImageFile);
f.canRead();
f.canWrite();
BufferedImage src = ImageIO.read(f);
ImageIO.write(src, formatName, new File(destImageFile));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 彩色转为黑白
*
* @param srcImageFile
* 源图像地址
* @param destImageFile
* 目标图像地址
*/
public final static void gray(String srcImageFile, String destImageFile) {
try {
BufferedImage src = ImageIO.read(new File(srcImageFile));
ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
ColorConvertOp op = new ColorConvertOp(cs, null);
src = op.filter(src, null);
ImageIO.write(src, "JPEG", new File(destImageFile));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 给图片添加文字水印
*
* @param pressText
* 水印文字
* @param srcImageFile
* 源图像地址
* @param destImageFile
* 目标图像地址
* @param fontName
* 水印的字体名称
* @param fontStyle
* 水印的字体样式
* @param color
* 水印的字体颜色
* @param fontSize
* 水印的字体大小
* @param x
* 修正值
* @param y
* 修正值
* @param alpha
* 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
*/
public final static void pressText(String pressText, String srcImageFile, String destImageFile, String fontName,
int fontStyle, Color color, int fontSize, int x, int y, float alpha) {
try {
File img = new File(srcImageFile);
Image src = ImageIO.read(img);
int width = src.getWidth(null);
int height = src.getHeight(null);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage(src, 0, 0, width, height, null);
g.setColor(color);
g.setFont(new Font(fontName, fontStyle, fontSize));
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 在指定坐标绘制水印文字
g.drawString(pressText, (width - (getLength(pressText) * fontSize)) / 2 + x, (height - fontSize) / 2 + y);
g.dispose();
ImageIO.write((BufferedImage) image, "JPEG", new File(destImageFile));// 输出到文件流
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 给图片添加文字水印
*
* @param pressText
* 水印文字
* @param srcImageFile
* 源图像地址
* @param destImageFile
* 目标图像地址
* @param fontName
* 字体名称
* @param fontStyle
* 字体样式
* @param color
* 字体颜色
* @param fontSize
* 字体大小
* @param x
* 修正值
* @param y
* 修正值
* @param alpha
* 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
*/
public final static void pressText2(String pressText, String srcImageFile, String destImageFile, String fontName,
int fontStyle, Color color, int fontSize, int x, int y, float alpha) {
try {
File img = new File(srcImageFile);
Image src = ImageIO.read(img);
int width = src.getWidth(null);
int height = src.getHeight(null);
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage(src, 0, 0, width, height, null);
g.setColor(color);
g.setFont(new Font(fontName, fontStyle, fontSize));
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 在指定坐标绘制水印文字
g.drawString(pressText, (width - (getLength(pressText) * fontSize)) / 2 + x, (height - fontSize) / 2 + y);
g.dispose();
ImageIO.write((BufferedImage) image, "JPEG", new File(destImageFile));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 给图片添加图片水印
*
* @param pressImg
* 水印图片
* @param srcImageFile
* 源图像地址
* @param destImageFile
* 目标图像地址
* @param x
* 修正值。 默认在中间
* @param y
* 修正值。 默认在中间
* @param alpha
* 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
*/
public final static void pressImage(String pressImg, String srcImageFile, String destImageFile, int x, int y,
float alpha) {
try {
File img = new File(srcImageFile);
Image src = ImageIO.read(img);
int wideth = src.getWidth(null);
int height = src.getHeight(null);
BufferedImage image = new BufferedImage(wideth, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.drawImage(src, 0, 0, wideth, height, null);
// 水印文件
Image src_biao = ImageIO.read(new File(pressImg));
int wideth_biao = src_biao.getWidth(null);
int height_biao = src_biao.getHeight(null);
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
g.drawImage(src_biao, (wideth - wideth_biao) / 2, (height - height_biao) / 2, wideth_biao, height_biao,
null);
// 水印文件结束
g.dispose();
ImageIO.write((BufferedImage) image, "JPEG", new File(destImageFile));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 计算text的长度(一个中文算两个字符)
*
* @param text
* @return
*/
public final static int getLength(String text) {
int length = 0;
for (int i = 0; i < text.length(); i++) {
if (new String(text.charAt(i) + "").getBytes().length > 1) {
length += 2;
} else {
length += 1;
}
}
return length / 2;
}
/**
* 缩放图像(按高度和宽度缩放)
*
* @param srcImageFile
* 源图像文件地址
* @param result
* 缩放后的图像地址
* @param height
* 缩放后的高度
* @param width
* 缩放后的宽度
*/
public static void scale(String srcImageFile, String result, int maxWidth, int maxHeight) {
// 原图片
File in = new File(srcImageFile);
// 目的图片
File out = new File(result);
// 将图像缩略到指定尺寸以内,不足指定尺寸的则不做任何处理
ScaleParameter scaleParam = new ScaleParameter(maxWidth, maxHeight);
FileInputStream inStream = null;
FileOutputStream outStream = null;
WriteRender wr = null;
try {
inStream = new FileInputStream(in);
outStream = new FileOutputStream(out);
ImageRender rr = new ReadRender(inStream);
ImageRender sr = new ScaleRender(rr, scaleParam);
wr = new WriteRender(sr, outStream);
// 执行图像处理
wr.render();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭图片文件输入输出流
IOUtils.closeQuietly(inStream);
IOUtils.closeQuietly(outStream);
if (wr != null) {
try {
// 释放simpleImage的内部资源
wr.dispose();
} catch (SimpleImageException ignore) {
ignore.printStackTrace();
}
}
}
}
/**
* 程序入口:用于测试
*
* @param args
*/
public static void main(String[] args) {
// 缩略图
// ImageUtils.scale("/Users/dewly/Downloads/TB1.9IXIFXXXXadaXXX2jHzFXXX_220x220.jpg",
// "/Users/dewly/Downloads/test00-118x118.jpg", 118, 118);
// ImageUtils.scale("d:/temp/1.png", "d:/temp/1_200x200.png", 200, 200);
// 图片颜色处理(黑白彩色转换)
// ImageUtils.gray("e:/test/test.jpg", "e:/test/test2.jpg");// 测试OK
// 方法一:按比例缩放(放大缩小)
ImageUtils.scale("d:/temp/222.png", "d:/temp/222_111.png", 4, false);// 测试OK
// 方法二:按高度和宽度缩放(放大缩小)
// ImageUtils.scale2("d:/temp/1.png", "d:/temp/1_720x720.png", 720,720,
// true);// 测试OK
// 5-给图片添加文字水印:
// 方法一:
// ImageUtils.pressText("我是水印文字", "e:/test/g.jpg", "e:/test/g2.jpg",
// "宋体", Font.BOLD, Color.white, 80, 0, 0, 0.5f);// 测试OK
// 方法二:
// ImageUtils.pressText2("我也是水印文字", "e:/test/g.jpg", "e:/test/g3.jpg",
// "黑体", 36, Color.white, 80, 0, 0, 0.5f);// 测试OK
}
}