2009-06-13 241 views
16

我尝试调整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); 

回答

6

按比例放大/缩小图片,您可以看看perils-of-image-getscaledinstance.html这可以解释为什么getScaledInstance(),在一些使用答案,应该避免。

该文章还提供了替代代码。

8

对于初学者 - 看看第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);

+0

耶它的getHeight错误错字 没有任何理由我不能使用getScaledInstance与BufferdImage? – user63898 2009-06-14 03:11:30

+0

这应该没问题,因为BufferedImage扩展Image – Max 2009-06-16 00:05:20

+0

哈,谢谢你的第一个等式。在我困惑的大脑中点击一下! – Cameron 2012-01-03 05:32:57

0

如果要通过保持纵横比将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); 
8

如果源和目标的宽度,高度已知,则使用以下函数确定图像的比例。

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); 
63

加入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图像处理管道将回退到较差的软件管道。

如果听起来像很多令人头疼的事情,那就是......这就是为什么我编写图书馆并开放源代码的原因,所以人们可以调整他们的图像大小并继续他们的生活而不必担心它。

希望有所帮助。

3

我使用这两种方法来缩放图像,其中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; 
} 
相关问题