我正在尝试实现一个简单的类,允许用户裁剪图像以用于他们的个人资料图片。这是一个java Web应用程序。
我做了一些搜索,发现java.awt有一个BufferedImage类,这看起来(乍一看)是我需要的完美。但是,似乎有一个错误(或者也许是java,正如我所见),这意味着裁剪并不总能正常工作。
以下是我用来尝试裁剪图片的代码:
BufferedImage profileImage = getProfileImage(form, modelMap);
if (profileImage != null) {
BufferedImage croppedImage = profileImage
.getSubimage(form.getStartX(), form.getStartY(), form.getWidth(), form.getHeight());
System.err.println(form.getStartX());
System.err.println(form.getStartY());
File finalProfileImage = new File(form.getProfileImage());
try {
String imageType = getImageType(form.getProfileImage());
ImageIO.write(croppedImage, imageType, finalProfileImage);
}
catch (Exception e) {
logger.error("Unable to write cropped image", e);
}
}
return modelAndView;
}
protected BufferedImage getProfileImage(CropImageForm form, Map<String, Object> modelMap) {
String profileImageFileName = form.getProfileImage();
if (validImage(profileImageFileName) && imageExists(profileImageFileName)) {
BufferedImage image = null;
try {
image = getCroppableImage(form, ImageIO.read(new File(profileImageFileName)), modelMap);
}
catch (IOException e) {
logger.error("Unable to crop image, could not read profile image: [" + profileImageFileName + "]");
modelMap.put("errorMessage", "Unable to crop image. Please try again");
return null;
}
return image;
}
modelMap.put("errorMessage", "Unable to crop image. Please try again.");
return null;
}
private boolean imageExists(String profileImageFileName) {
return new File(profileImageFileName).exists();
}
private BufferedImage getCroppableImage(CropImageForm form, BufferedImage image, Map<String, Object> modelMap) {
int cropHeight = form.getHeight();
int cropWidth = form.getWidth();
if (cropHeight <= image.getHeight() && cropWidth <= image.getWidth()) {
return image;
}
modelMap.put("errorMessage", "Unable to crop image. Crop size larger than image.");
return null;
}
private boolean validImage(String profileImageFileName) {
String extension = getImageType(profileImageFileName);
return (extension.equals("jpg") || extension.equals("gif") || extension.equals("png"));
}
private String getImageType(String profileImageFileName) {
int indexOfSeparator = profileImageFileName.lastIndexOf(".");
return profileImageFileName.substring(indexOfSeparator + 1);
}
此代码段中引用的表单是一个简单的POJO,它包含左上角的整数值以开始裁剪(startX和startY)以及用于制作新图像的宽度和高度。
然而,我最终得到的是一个裁剪图像,始终从0,0开始,而不是startX和startY位置。我已经检查了代码,以确保将正确的值传递给getSubimage方法,它们似乎是。
使用BufferedImage裁剪图像是否有简单的替代方法。我简要介绍了JAI。我想在我的应用程序中添加一个jar,而不是更新所有生产盒上安装的jdk,以及任何开发/测试服务器和本地工作站。
我选择替代方案的标准是: 1)简单地用于裁剪图像,因为这是我将要使用它的全部内容 2)如果没有内置到java或spring中,jar应该很小并且可以在web-app中轻松部署
有什么建议吗?
注意:上面的评论表明bufferedImage或Java存在问题,这是我在帖子中看到的:Guidance on the BufferedImage.getSubimage(int x, int y, int w, int h) method?
答案 0 :(得分:2)
之前我曾多次使用过getSubimage()而没有任何问题。您是否在该调用之前添加了System.out.println(form.getStartX()+“”+ form.getStartY())以确保它们不是0?
另外,你至少得到的形式是form.getWidth()x form.getHeight()吗?
请确保您没有以任何方式修改/处理profileImage,因为返回的BufferedImage与父级共享相同的数据数组。
如果您想要一个全新且独立的BufferedImage,最好的方法就是简单地绘制它:
BufferedImage croppedImage = new BufferedImage(form.getWidth(),form.getHeight(),BufferedImage.TYPE_INT_ARGB);
Graphics g = croppedImage.getGraphics();
g.drawImage(profileImage,0,0,form.getWidth(),form.getHeight(),form.getStartX(),form.getStartY(),form.getWidth(),form.getHeight(),null);
g.dispose();
答案 1 :(得分:1)
您也可以这样做(代码不是100%经过测试,例如我从现有应用程序中采用的):
import javax.imageio.*;
import java.awt.image.*;
import java.awt.geom.*;
...
BufferedImage img = ImageIO.read(imageStream);
...
/*
* w = image width, h = image height, l = crop left, t = crop top
*/
ColorModel dstCM = img.getColorModel();
BufferedImage dst = new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(w, h), dstCM.isAlphaPremultiplied(), null);
Graphics2D g = dst.createGraphics();
g.drawRenderedImage(img, AffineTransform.getTranslateInstance(-l,-t));
g.dispose();
java.io.File outputfile = new java.io.File(sessionScope.get('absolutePath') + java.io.File.separator + sessionScope.get('lastUpload'));
ImageIO.write(dst, 'png', outputfile);
答案 2 :(得分:0)
感谢所有回复的人。事实证明,问题根本不在裁剪代码中。
当我显示要裁剪的图像时,我将其调整大小以适应我的布局,然后使用javascript裁剪工具找出要裁剪的坐标。
由于我调整了图像大小,但在确定裁剪坐标时没有考虑调整大小,我最终得到的坐标似乎与左上角重合。
我已将显示更改为不再调整图像大小,现在裁剪效果非常好。