Java实现图片的裁剪

时间:2022-08-20 09:00:34

需求:

有一张位置大小的图片,现在需要根据这张原图得到指定尺寸的图片,且得到的图片要符合原先图片的比例,就是在原图的基础上等比例缩放得到图片后,在进行剪裁,这样保证得到的图片是原图的一部分,而不是将原图拉伸或着是压缩到指定的尺寸,这样的图片就会严重的失真,且不协调。

例如:

一张原图为600×400的图片,现在需求如下:

  1. 一张500×300的图片
  2. 一张700×400的图片
  3. 一张400×500的图片
注意:得到的图片不能是原图中的人物、景象有拉伸或压缩的感觉。

思路:

500×300的图片:可以看出宽度和高度都在原图的尺寸之内,但是为了多的得到原图的信息,可先将原图按照一定的比率压缩,压缩的比率min(500/600,300/400),为什么要选择这样的压缩比率呢?因为假如按照宽度比进行压缩,虽然得到的图片的宽度和要求的一致,但是那高度呢?有可能高度压缩之前确实是符合的,也就是大于目标图片的高度,但是枷锁之后,可能出现高度比需求的高度小,导致无法安装、要求截取图片,所以需要比较之后进行压缩,这样不会超出范围。

同理,不管要求的图片大小是否超出原图的大小,或是在原图的大小范围之内,都要先比较,然后再压缩,这样就可以保证得到的图片是放大或缩小到最合适并且包含最多的原图信息,不会变形。

计算压缩比例的核心算法:

/*
* 核心算法,计算图片的压缩比
*/
int w= buffer.getWidth();
int h=buffer.getHeight();
double ratiox = 1.0d;
double ratioy = 1.0d;

ratiox= w * ratiox / width;
ratioy= h * ratioy / height;

if( ratiox >= 1){
if(ratioy < 1){
ratiox = height * 1.0 / h;
}else{
if(ratiox > ratioy){
ratiox = height * 1.0 / h;
}else{
ratiox = width * 1.0 / w;
}
}
}else{
if(ratioy < 1){
if(ratiox > ratioy){
ratiox = height * 1.0 / h;
}else{
ratiox = width * 1.0 / w;
}
}else{
ratiox = width * 1.0 / w;
}
}
/*
* 对于图片的放大或缩小倍数计算完成,ratiox大于1,则表示放大,否则表示缩小
*/

这样,计算完的ratiox就是要压缩的比率。w、h是原图的width和height,而程序中的width和height是要得到图片的width和height。

在生成图片和其他的地方的程序是参考别人的,具体地址给忘了,再次谢过作者,以下是源代码:

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;
public class UploadImg {
String fromFileStr;
String saveToFileStr;
String sysimgfile;
int width;
int height;
String suffix;
/**
* @param fromFileStr
* 原始图片完整路径
* @param saveToFileStr
* 缩略图片保存路径
* @param sysimgfilenNow
* 处理后的图片文件名前缀
*
*/
public UploadImg(String fromFileStr, String saveToFileStr, String sysimgfile,String suffix,int width,int height) {
this.fromFileStr = fromFileStr;
this.saveToFileStr = saveToFileStr;
this.sysimgfile = sysimgfile;
this.width=width;
this.height=height;
this.suffix=suffix;
}
public boolean createThumbnail() throws Exception {
// fileExtNmae是图片的格式 gif JPG 或png
// String fileExtNmae="";
File F = new File(fromFileStr);
if (!F.isFile())
throw new Exception(F
+ " is not image file error in CreateThumbnail!");
File ThF = new File(saveToFileStr, sysimgfile +"."+suffix);
BufferedImage buffer = ImageIO.read(F);
/*
* 核心算法,计算图片的压缩比
*/
int w= buffer.getWidth();
int h=buffer.getHeight();
double ratiox = 1.0d;
double ratioy = 1.0d;

ratiox= w * ratiox / width;
ratioy= h * ratioy / height;

if( ratiox >= 1){
if(ratioy < 1){
ratiox = height * 1.0 / h;
}else{
if(ratiox > ratioy){
ratiox = height * 1.0 / h;
}else{
ratiox = width * 1.0 / w;
}
}
}else{
if(ratioy < 1){
if(ratiox > ratioy){
ratiox = height * 1.0 / h;
}else{
ratiox = width * 1.0 / w;
}
}else{
ratiox = width * 1.0 / w;
}
}
/*
* 对于图片的放大或缩小倍数计算完成,ratiox大于1,则表示放大,否则表示缩小
*/
AffineTransformOp op = new AffineTransformOp(AffineTransform
.getScaleInstance(ratiox, ratiox), null);
buffer = op.filter(buffer, null);
//从放大的图像中心截图
buffer = buffer.getSubimage((buffer.getWidth()-width)/2, (buffer.getHeight() - height) / 2, width, height);
try {
ImageIO.write(buffer, suffix, ThF);
} catch (Exception ex) {
throw new Exception(" ImageIo.write error in CreatThum.: "
+ ex.getMessage());
}
return (true);
}
public static void main(String[] args) {
UploadImg UI;
boolean ss = false;
try {
UI = new UploadImg("C:\\Users\\Administrator\\Pictures\\111.jpg", "C:\\Users\\Administrator\\Pictures\\", "ps_low2","png",280,280);
ss = UI.createThumbnail();
if (ss) {
System.out.println("Success");
} else {
System.out.println("Error");
}
} catch (Exception e) {
System.out.print(e.toString());
}
}
}

接下来测试几个例子:

原图1024*520:

Java实现图片的裁剪

要求得到尺寸:1000*500

UI = new UploadImg("F:\\2.jpg", "F:\\", "ps","jpg",1000,500);


Java实现图片的裁剪

目标尺寸1000*700:

UI = new UploadImg("F:\\2.jpg", "F:\\", "ps","jpg",1000,700);

Java实现图片的裁剪

目标尺寸:1100*600:

UI = new UploadImg("F:\\2.jpg", "F:\\", "ps","jpg",1100,600);

Java实现图片的裁剪

目标尺寸600*500:

UI = new UploadImg("F:\\2.jpg", "F:\\", "ps","jpg",600,500);

Java实现图片的裁剪

以上就是效果,如有错误,请指正!