调整图像大小,同时保持宽高比的Java
我尝试调整bufferdImage内存在Java中,但保持图像 IM有这样的事情的纵横比,但是这是不好的调整图像大小,同时保持宽高比的Java
int w = picture.getWidth();
int h = picture.getWidth();
int neww=w;
int newh=h;
int wfactor = w;
int hfactor = h;
if(w > DEFULT_PICTURE_WIDTH || h > DEFULT_PICTURE_HIGHT)
{
while(neww > DEFULT_PICTURE_WIDTH)
{
neww = wfactor /2;
newh = hfactor /2;
wfactor = neww;
hfactor = newh;
}
}
picture = Utils.resizePicture(picture,neww,newh);
按比例放大/缩小图片,您可以看看perils-of-image-getscaledinstance.html这可以解释为什么getScaledInstance()
,在一些使用答案,应该避免。
该文章还提供了替代代码。
对于初学者 - 看看第2行。不应该是getHeight()
?
你不想为调整大小的while循环,你想找出调整比例,这是一个简单的数学。
(width/height) = (new_width/new_height)
如果你知道“新”尺寸之一,其他的都可以通过乘法发现
new_height * (width/height) = new_width
您还可以使用BufferedImage's
超图像,getScaledInstance()
提供的懒人方法 - 使用-1为宽度或高度将保持高宽比
例如:scaledPic = picture.getScaledInstance(new_width, -1, Image.SCALE_FAST);
如果要通过保持纵横比将w0 x h0的图片调整为w1 x h1,然后计算垂直和水平缩放并选择较小的一个。
double scalex = 1;
double scaley = 1;
if (scalingMode == ScalingMode.WINDOW_SIZE) {
scalex = (double)getWidth()/frontbuffer.getWidth();
scaley = (double)getHeight()/frontbuffer.getHeight();
} else
if (scalingMode == ScalingMode.KEEP_ASPECT) {
double sx = (double)getWidth()/frontbuffer.getWidth();
double sy = (double)getHeight()/frontbuffer.getHeight();
scalex = Math.min(sx, sy);
scaley = scalex;
// center the image
g2.translate((getWidth() - (frontbuffer.getWidth() * scalex))/2,
(getHeight() - (frontbuffer.getHeight() * scaley))/2);
}
g2.scale(scalex, scaley);
if (interpolation != ImageInterpolation.NONE) {
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation.hint);
}
g2.drawImage(frontbuffer, 0, 0, null);
如果源和目标的宽度,高度已知,则使用以下函数确定图像的比例。
private double determineImageScale(int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) {
double scalex = (double) targetWidth/sourceWidth;
double scaley = (double) targetHeight/sourceHeight;
return Math.min(scalex, scaley);
}
然后用这个尺度使用下面的代码
Image scaledImage = sourceBufferedImage.getScaledInstance((int) (width * scale), (int) (height * scale), Image.SCALE_SMOOTH);
加入Erik的关于getScaledInstance的观点,如果您不再使用Java2D中推荐的缩放机制,您可能已经注意到您的图像看起来明显更糟。
其原因是当Java2D的劝阻使用getScaledInstance和AreaAveragingScaleFilter的,他们没有与任何容易 API中使用替换它,而不是我们直接使用的Java2D的API留给我们自己的设备。幸运的是,Chris Campbell(来自J2D团队)跟进了使用增量缩放技术的建议,该技术给了AreaAveragingScaleFilter类似的结果,并且运行速度更快;不幸的是,这些代码的体积很大,并没有解决你原先的比例问题。
约6个月前,我一次又一次地看到所有关于“缩放Java图像”的问题,并最终收集了所有的建议,做了所有的挖掘和研究,并将所有这些都编译成了一个“最好的做法“image scaling library。
由于API只有一个类和一堆静态方法,因此它非常简单。基本使用方法如下:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);
这是simplest call,其中图书馆将成为在质量最好的猜测,孝敬你的图像比例,以及320×320边框内适合的结果。注意,边界框只是使用的最大W/H,因为您的图像比例很高,所得到的图像仍然可以兑现,比如320x200。
如果你想覆盖自动模式并强制它给你最好看的结果,甚至对结果使用非常温和的抗混叠过滤器,所以它看起来更好(尤其适用于缩略图),那个调用看起来像:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
这些都只是例子,API是广泛的,涵盖从超简单的用例到非常专业的一切。你甚至可以通过自己的BufferedImageOps来应用到图像上(并且库自动修复了6年的BufferedImageOp JDK bug!)
还有很多东西在Java中成功缩放图像例如,对于您来说,始终将图像保存为支持最佳的RGB或ARGB图像类型之一。如果用于任何图像操作的图像类型得不到支持,则Java2D图像处理管道将回退到较差的软件管道。
如果听起来像很多令人头疼的事情,那就是......这就是为什么我编写图书馆并开放源代码的原因,所以人们可以调整他们的图像大小并继续他们的生活而不必担心它。
希望有所帮助。
我使用这两种方法来缩放图像,其中max是目标图像的较大尺寸。对于100x100的图像将是100,为200x300的图像将是300
public static BufferedImage scale(InputStream is, int max) {
Image image = null;
try {
image = ImageIO.read(is);
} catch (IOException e) {
e.printStackTrace();
}
int width = image.getWidth(null);
int height = image.getHeight(null);
double dWidth = 0;
double dHeight = 0;
if (width == height) {
dWidth = max;
dHeight = max;
}
else if (width > height) {
dWidth = max;
dHeight = ((double) height/(double) width) * max;
}
else {
dHeight = max;
dWidth = ((double) width/(double) height) * max;
}
image = image.getScaledInstance((int) dWidth, (int) dHeight, Image.SCALE_SMOOTH);
BufferedImage bImage = toBufferedImage(image);
return bImage;
}
public static BufferedImage toBufferedImage(Image img)
{
if (img instanceof BufferedImage)
{
return (BufferedImage) img;
}
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
return bimage;
}
耶它的getHeight错误错字 没有任何理由我不能使用getScaledInstance与BufferdImage? – user63898 2009-06-14 03:11:30
这应该没问题,因为BufferedImage扩展Image – Max 2009-06-16 00:05:20
哈,谢谢你的第一个等式。在我困惑的大脑中点击一下! – Cameron 2012-01-03 05:32:57