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
Differencebetween & and && in Java
Where Are Static Methods and Static Variables Stored in Java
Way to Get Number of Digits in an Int
Why Do We Use Autoboxing and Unboxing in Java
Eclipse Java Debugging: Source Not Found
Differences in Boolean Operators: & VS && and | VS ||
.Toarray(New Myclass[0]) or .Toarray(New Myclass[Mylist.Size()])
How to Switch to the New Browser Window, Which Opens After Click on the Button
Parse String to Date with Different Format in Java
How to Execute Cmd Commands via Java
How to Fix an Unsatisfiedlinkerror (Can't Find Dependent Libraries) in a Jni Project
How to Kill a Thread? Without Using Stop();
Re-Paint on Translucent Frame/Panel/Component
How to Derive Module Descriptor for Auto Generated Module Names in Java 9
Get Selected Rows in Jtable Using Abstracttablemodel
How to Convert Comma-Separated String to List
Convert Java.Util.Date to Java.Time.Localdate
How to Resolve the "Java.Net.Bindexception: Address Already in Use: Jvm_Bind" Error