How to Scale a Bufferedimage

How to scale a BufferedImage

AffineTransformOp offers the additional flexibility of choosing the interpolation type.

BufferedImage before = getBufferedImage(encoded);
int w = before.getWidth();
int h = before.getHeight();
BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(2.0, 2.0);
AffineTransformOp scaleOp =
new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
after = scaleOp.filter(before, after);

The fragment shown illustrates resampling, not cropping; this related answer addresses the issue; some related examples are examined here.

how do I scale a BufferedImage

Something like this? :

 /**
* Resizes an image using a Graphics2D object backed by a BufferedImage.
* @param srcImg - source image to scale
* @param w - desired width
* @param h - desired height
* @return - the new resized image
*/
private BufferedImage getScaledImage(Image srcImg, int w, int h){
BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
Graphics2D g2 = resizedImg.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(srcImg, 0, 0, w, h, null);
g2.dispose();
return resizedImg;
}

Bufferedimage resize

Updated answer

I cannot recall why my original answer worked but having tested it in a separate environment, I agree, the original accepted answer doesn't work (why I said it did I cannot remember either). This, on the other hand, did work:

public static BufferedImage resize(BufferedImage img, int newW, int newH) { 
Image tmp = img.getScaledInstance(newW, newH, Image.SCALE_SMOOTH);
BufferedImage dimg = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB);

Graphics2D g2d = dimg.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();

return dimg;
}

Is there a way to scale down a BufferedImage

To scale down, use a scale in the range (0.0, 1.0), instead of negatives.

When you apply a scaling Affine Transform with scale (xScale, yScale), the new dimensions are (imgWidth*xScale, imgHeight*yScale).

How to get scaled instance of a bufferedImage

You can create a new image, a BufferedImage with the TookitImage.

Image toolkitImage = img.getScaledInstance(getWidth(), getHeight(), 
Image.SCALE_SMOOTH);
int width = toolkitImage.getWidth(null);
int height = toolkitImage.getHeight(null);

// width and height are of the toolkit image
BufferedImage newImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics g = newImage.getGraphics();
g.drawImage(toolkitImage, 0, 0, null);
g.dispose();

// now use your new BufferedImage

Dynamically resize a bufferedimage in java

You're doing int division which always returns an int, here 0 since your screen dimensions will likely be greater than your image dimensions:

aspectRatioWidth = bufwidth/scrwidth;
aspectRatioHeight = bufheight/scrheight;

Solution: convert the numbers to double and then do double division.

aspectRatioWidth = (double) bufwidth/scrwidth;
aspectRatioHeight = (double) bufheight/scrheight;

Edit

Not sure what you're ultimately trying to do -- post the image of the computer screen in your GUI? If so, perhaps something like...

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.util.List;

import javax.swing.*;

public class ChangeVars extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
private static final int DELAY = 20;
public BufferedImage displayImage;
private MyWorker myWorker;

public ChangeVars() {
try {
myWorker = new MyWorker(DELAY);
myWorker.execute();
} catch (AWTException e) {
e.printStackTrace();
}
}

@Override
// to initialize the panel to something
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (displayImage != null) {
g.drawImage(displayImage, 0, 0, null);
}
}

public void stopWorker() {
if (myWorker != null && !myWorker.isDone()) {
myWorker.setRunning(false);
myWorker.cancel(true);
}
}

private class MyWorker extends SwingWorker<Void, BufferedImage> {

private volatile boolean running = true;
private Robot robot;
private int delay;

public MyWorker(int delay) throws AWTException {
this.delay = delay;
robot = new Robot();
}

@Override
protected Void doInBackground() throws Exception {
while (running) {
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRect = new Rectangle(0, 0, d.width, d.height);
BufferedImage img = robot.createScreenCapture(screenRect);
publish(img);
Thread.sleep(delay);
}
return null;
}

@Override
protected void process(List<BufferedImage> chunks) {
for (BufferedImage image : chunks) {
Dimension sz = getSize();
double scaleX = (double) sz.width / image.getWidth();
double scaleY = (double) sz.height / image.getHeight();
AffineTransform transform = AffineTransform.getScaleInstance(
scaleX, scaleY);
AffineTransformOp transformOp = new AffineTransformOp(transform,
AffineTransformOp.TYPE_BILINEAR);
displayImage = new BufferedImage(sz.width, sz.height,
BufferedImage.TYPE_INT_ARGB);
displayImage = transformOp.filter(image, displayImage);
repaint();
}
}

public void setRunning(boolean running) {
this.running = running;
}

public boolean getRunning() {
return running;
}

}

private static void createAndShowGui() {
final ChangeVars changeVars = new ChangeVars();

JFrame frame = new JFrame("ChangeVars");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {

@Override
public void windowClosing(WindowEvent e) {
if (changeVars != null) {
changeVars.stopWorker();
}
System.exit(0);
}

});
frame.getContentPane().add(changeVars);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Although simpler would be to just let paintComponent do the scaling:

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (displayImage != null) {
int width = getWidth();
int height = getHeight();
g.drawImage(displayImage, 0, 0, width, height, null);
}
}

// ....

@Override
protected void process(List<BufferedImage> chunks) {
for (BufferedImage image : chunks) {
displayImage = image;
repaint();
}
}

BufferedImage black and white after scaling

I'm pretty sure you can not just change the height and width of a Buffered Image and it will scale for you.
Try using getScaledInstance() like in this question.



Related Topics



Leave a reply



Submit