I'm using Barcode4J library to generate barcodes. I am returned a BufferedImage that I can display as an ImageIcon on a JLabel and save to a file but I can't for the life of me print it to a printer, the drawString and drawRect work as expected but the image is blank. I've posted some code below; I don't know how to make it a SSCCE of this but if anyone can point me in any direction I would be most grateful.
snippet:
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;
public class BarcodeBean extends Code128Bean implements Printable{
BufferedImage _bImage;
public void createBarcode2Print(BarcodeBean bean, String barcodeValue) throws FileNotFoundException, IOException {
final int dpi = 150;
BufferedImage image;
BitmapCanvasProvider canvas = null;
if (barcodeValue == null) {
barcodeValue = "0123456789-000-0001";
}
bean.setModuleWidth(UnitConv.in2mm(2.0f / dpi));
bean.doQuietZone(false);
try {
canvas = new BitmapCanvasProvider(
dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
//Generate the barcode
bean.generateBarcode(canvas, barcodeValue);
image = canvas.getBufferedImage();
//Signal end of generation
// canvas.finish();
} finally {
canvas.finish();
}
printImage(image);
int stop = 0;
}
public void printImage(BufferedImage arg_image){
_bImage = arg_image;
createLabel();
}
private void createLabel() {
PrinterJob printJob = PrinterJob.getPrinterJob();
Book book = new Book();
PageFormat format = new PageFormat();
format.setOrientation(PageFormat.PORTRAIT);
java.awt.print.Paper paper = new java.awt.print.Paper();
paper.setSize(612.0, 792.0); //portrait
double hgt = paper.getHeight();
double wdth = paper.getWidth();
paper.setImageableArea(0, 0, wdth, hgt);
format.setPaper(paper);
book.append(this, format);
printJob.setPageable(book);
if (printJob.printDialog()) {
try {
printJob.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D graphics2d = (Graphics2D)graphics;
graphics2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
graphics.setColor(Color.black);
graphics2d.setColor(Color.black);
int imageWidth = _bImage.getWidth(null); // 378
int imageHeight = _bImage.getHeight(null); // 110
int imageableWidth = (int)pageFormat.getImageableWidth(); // 612
int imageableHeight = (int)pageFormat.getImageableHeight(); // 792
graphics2d.drawString("Print barcode between this and...", 10, 30);
graphics2d.drawRect(10, 40, imageWidth, imageHeight);
graphics2d.drawImage(_bImage, 10, 60, imageWidth, imageHeight, null);
graphics2d.drawString("This.............................", 10, 180);
graphics2d.dispose();
return Printable.PAGE_EXISTS;
}
}
I can't say I know why, it's possible that the Barcode4J is using their own implementation of BufferedImage or something, but, if I make a copy of the BufferedImage returned from Barcode4J, I can make it work.
What I mean by that is, if I create a new instance of BufferedImage and draw the instance from Barcode4J onto it and use it, I can make it work...
canvas = new BitmapCanvasProvider(
dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
bean.generateBarcode(canvas, barcodeValue);
BufferedImage bardcode = canvas.getBufferedImage();
image = new BufferedImage(bardcode.getWidth(), bardcode.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(bardcode, 0, 0, null);
g2d.dispose();
graphics2d.dispose(); ← That might be the problem. Never dispose of a Graphics unless you created it.
👆 is really good advice! Unfortunately, in this case it didn't help, but you should listen to it anyway!
Also, this return Printable.PAGE_EXISTS;, could have you running around in circles. You need to tell the caller when there are no more pages to be printed.
Runnable example...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.krysalis.barcode4j.impl.code128.Code128Bean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage barcodeImage;
public TestPane() throws IOException {
setLayout(new GridBagLayout());
barcodeImage = createBarcode2Print(new Code128Bean(), "0123456789-000-0001");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JLabel(new ImageIcon(barcodeImage)), gbc);
JButton print = new JButton("Print");
add(print, gbc);
print.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
printIt();
}
});
}
protected void printIt() {
PrinterJob pj = PrinterJob.getPrinterJob();
if (pj.printDialog()) {
PageFormat pf = pj.defaultPage();
Paper paper = pf.getPaper();
pf.setOrientation(PageFormat.PORTRAIT);
pf.setPaper(paper);
PageFormat validatePage = pj.validatePage(pf);
// System.out.println("Valid- " + dump(validatePage));
pj.setPrintable(new BarCodePrintable(barcodeImage), validatePage);
try {
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
}
public class BarCodePrintable implements Printable {
private BufferedImage barcodeImage;
public BarCodePrintable(BufferedImage barcodeImage) {
this.barcodeImage = barcodeImage;
}
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D graphics2d = (Graphics2D) graphics;
graphics2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
graphics.setColor(Color.black);
graphics2d.setColor(Color.black);
int imageWidth = barcodeImage.getWidth(); // 378
int imageHeight = barcodeImage.getHeight(); // 110
int imageableWidth = (int) pageFormat.getImageableWidth(); // 612
int imageableHeight = (int) pageFormat.getImageableHeight(); // 792
graphics2d.drawString("Print barcode between this and...", 10, 30);
graphics2d.drawRect(10, 40, imageWidth, imageHeight);
graphics2d.drawImage(barcodeImage, 10, 60, null);
graphics2d.drawString("This.............................", 10, 180);
//graphics2d.dispose();
return pageIndex == 0 ? Printable.PAGE_EXISTS : Printable.NO_SUCH_PAGE;
}
}
public BufferedImage createBarcode2Print(Code128Bean bean, String barcodeValue) throws FileNotFoundException, IOException {
final int dpi = 300;
BufferedImage image = null;
BitmapCanvasProvider canvas = null;
if (barcodeValue == null) {
barcodeValue = "0123456789-000-0001";
}
bean.setModuleWidth(UnitConv.in2mm(2.0f / dpi));
bean.doQuietZone(false);
try {
canvas = new BitmapCanvasProvider(
dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
bean.generateBarcode(canvas, barcodeValue);
BufferedImage bardcode = canvas.getBufferedImage();
image = new BufferedImage(bardcode.getWidth(), bardcode.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(bardcode, 0, 0, null);
g2d.dispose();
} finally {
canvas.finish();
}
return image;
}
}
Related
Ok it may simple. But can't figure it out.
I have a JPanel that contains a JTable. JTable contains few rows, Sometime more, because the table model i push into it depends on database.
However, i don't use any JScollpane that enclose my JTable. As a result, when JTable contains more and more row, parent JPanel automatically resized its height. That is working fine.
Problem is i want to print whole JPanel at a time. may be it needs several page, i don't care. I can print JTable directly with a header and footer. But in my case JPanel contains some important component like JLable. So, there is no other way to avoid printing of JPanel.
I search several online link, everywhere i found a suggestion to implements printable interface.
so i implements printable in my class and overload print....
#Override
public int print(Graphics arg0, PageFormat arg1, int arg2) throws PrinterException {
Graphics2D g2d = (Graphics2D) arg0;
g2d.translate((int) arg1.getImageableX(), (int) arg1.getImageableY());
float pageWidth = (float) arg1.getImageableWidth();
float pageHeight = (float) arg1.getImageableHeight();
float imageHeight = (float) paintPanel.getHeight();
float imageWidth = (float) paintPanel.getWidth();
float scaleFactor = Math.min((float) pageWidth / (float) imageWidth, (float) pageHeight / (float) imageHeight);
int scaledWidth = (int) (((float) imageWidth) * scaleFactor);
int scaledHeight = (int) (((float) imageHeight) * scaleFactor);
BufferedImage canvas = new BufferedImage(paintPanel.getWidth(), paintPanel.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D gg = canvas.createGraphics();
paintPanel.paint(gg);
Image img = canvas;
g2d.drawImage(img, 0, 0, scaledWidth, scaledHeight, null);
return Printable.PAGE_EXISTS;
}
Its not working.
Another problem that is my second problem. I want to place a footer JPanel in every page. So how could it possible.
Help me please. Thanks.
So based on this example which demonstrates how to print a component across multiple pages, I modified it to allow for the printing of a footer.
This example draws directly via the Graphics context, but conceptually, the process would be simple enough to paint using a supplied JComponent of some sort.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import static java.awt.print.Printable.NO_SUCH_PAGE;
import static java.awt.print.Printable.PAGE_EXISTS;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.PrinterResolution;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class PrintMe {
public static void main(String[] args) {
new PrintMe();
}
public PrintMe() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane testPane = new TestPane();
JButton btn = new JButton("Print");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(new MultiPagePrintable(testPane));
if (pj.printDialog(aset)) {
try {
pj.print(aset);
testPane.getParent().invalidate();
testPane.getParent().validate();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(testPane));
frame.add(btn, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
private BufferedImage img;
public TestPane() {
try {
img = ImageIO.read(some image source);
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - img.getWidth()) / 2;
int y = (getHeight() - img.getHeight()) / 2;
g2d.drawImage(img, x, y, this);
g2d.dispose();
}
}
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 128;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
#Override
public boolean getScrollableTracksViewportHeight() {
return false;
}
}
public class MultiPagePrintable implements Printable {
private JComponent component;
private int lastPage = 0;
private double yOffset;
private Font footerFont;
public MultiPagePrintable(JComponent component) {
this.component = component;
footerFont = new Font("Arial", Font.BOLD, 24);
}
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
int result = NO_SUCH_PAGE;
String name = "I be mighty!";
String page = Integer.toString(pageIndex);
FontMetrics fm = graphics.getFontMetrics(footerFont);
double footerHeight = fm.getHeight() + 4;
double height = pageFormat.getImageableHeight() - footerHeight;
component.setSize(component.getPreferredSize());
if (lastPage != pageIndex) {
lastPage = pageIndex;
yOffset = height * pageIndex;
if (yOffset > component.getHeight()) {
yOffset = -1;
}
}
if (yOffset >= 0) {
Graphics2D g2d = (Graphics2D) graphics.create();
g2d.translate((int) pageFormat.getImageableX(),
(int) pageFormat.getImageableY());
g2d.translate(0, -yOffset);
component.printAll(g2d);
g2d.translate(0, +yOffset);
Shape footerArea = new Rectangle2D.Double(0, height, pageFormat.getImageableWidth(), footerHeight);
g2d.setColor(Color.WHITE);
g2d.fill(footerArea);
g2d.setColor(Color.RED);
g2d.draw(footerArea);
g2d.setColor(Color.BLACK);
g2d.translate(0, (pageFormat.getImageableHeight() - footerHeight));
float x = 2;
float y = (float)((footerHeight - fm.getHeight()) / 2d);
g2d.drawString(name, x, y + fm.getAscent());
x = (float)(pageFormat.getImageableWidth() - fm.stringWidth(page) - 2);
g2d.drawString(page, x, y + fm.getAscent());
g2d.dispose();
result = PAGE_EXISTS;
}
return result;
}
}
}
I'm trying to display a high-width image in Java Swing (say 2000x100, like a heart rate strip). I need to show only a window of 500 width while it is slightly moving towards left. My current code (a bit complicated, it also has unnecessary animations) does it, but the feature I need to add is: The end of image should be concatenated with the beginning of the image. So it always repeats showing over and over.
In short, I need to join the two ends of image! How can I do that?
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SlidingAnimation {
public static void main(String[] args) {
new SlidingAnimation();
}
public SlidingAnimation() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel j = new JPanel();
j.add(new AnimatedBar(true));
frame.add(j);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
class AnimatedBar extends JPanel {
private BufferedImage img;
private Timer timer;
private long startTime = -1;
private int playTime = 4000;
private int window = 500;
private int moveX=0;
public static boolean keepRunning=true;
private float progress;
public AnimatedBar(boolean x) {
try {
if(x)
img = ImageIO.read(new File("strip2.jpg"));
else
img=null;
} catch (IOException ex) {
ex.printStackTrace();
}
if(x){
timer = new Timer(40, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (startTime == -1) {
startTime = System.currentTimeMillis();
} else {
long currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
if (diff >= playTime) {
diff = 0;
startTime = -1;
}
progress = diff / (float) playTime;
}
repaint();
}
});
timer.start();
}
}
#Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(50, 50) : new Dimension(img.getWidth()/3, img.getHeight());
}
protected BufferedImage generateImage() {
BufferedImage buffer = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = buffer.createGraphics();
g2d.setBackground(new Color(0, 0, 0, 0));
g2d.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
// g2d.drawImage(img, 500, 0, this);
g2d.drawImage(img,0,0,500,100,(moveX++),0,window+moveX,100,this);
float startAt = progress- 0.05f;
float endAt = progress + 0.05f;
if (endAt <= 0.1f) {
startAt = 0;
endAt = Math.max(0.1f, progress);
} else if (endAt >= 1f) {
endAt = 1f;
startAt = progress;
}
LinearGradientPaint lgp = new LinearGradientPaint(
new Point2D.Float(0, 0),
new Point2D.Float(img.getWidth(), 0),
new float[]{startAt, endAt},
new Color[]{new Color(0, 0, 0, 0), Color.RED});
g2d.setPaint(lgp);
g2d.setComposite(AlphaComposite.DstOut.derive(1f));
g2d.fill(new Rectangle(0, 0, img.getWidth(), img.getHeight()));
g2d.dispose();
return buffer;
}
public void setImg(BufferedImage img) {
this.img = img;
}
#Override
protected void paintComponent(Graphics g) {
if(keepRunning==false){
img=null;
}
else{
try {
img = ImageIO.read(new File("strip2.jpg"));
} catch (IOException e) {
}
}
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();
int y = (getHeight() - img.getHeight()) / 2;
int x = (getWidth() - img.getWidth()/3) / 2;
g2d.drawImage(generateImage(), x, y, this);
g2d.dispose();
}
}
}
To join the ends, paint the image twice as seen in this answer. The first paint would be the end of the image. The second paint would be the start of the image, offset by the width the end goes to.
E.G.
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.URL;
import javax.imageio.ImageIO;
public class HeartBeat {
public static void main(String[] args) throws Exception {
URL url = new URL("http://i.stack.imgur.com/i8UJD.jpg");
final BufferedImage bi = ImageIO.read(url);
Runnable r = new Runnable() {
#Override
public void run() {
final BufferedImage canvas = new BufferedImage(
bi.getWidth(), bi.getHeight(),
BufferedImage.TYPE_INT_RGB);
final JLabel animationLabel = new JLabel(new ImageIcon(canvas));
ActionListener animator = new ActionListener() {
int x = 0;
#Override
public void actionPerformed(ActionEvent e) {
Graphics2D g = canvas.createGraphics();
// paint last part of image in left of canvas
g.drawImage(bi, x, 0, null);
// paint first part of image immediately to the right
g.drawImage(bi, x + bi.getWidth(), 0, null);
// reset x to prevent hitting integer overflow
if (x%bi.getWidth()==0) x = 0;
g.dispose();
animationLabel.repaint();
x--;
}
};
Timer timer = new Timer(40, animator);
timer.start();
JOptionPane.showMessageDialog(null, animationLabel);
timer.stop();
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
The end of image should be concatenated with the beginning of the image. So it always repeats showing
Check out the Marquee Panel. You can add a JLabel with an ImageIcon to the MarqueePanel.
The MarqueePanel provides various method to customize the scrolling.
Edit:
The basic code would be:
MarqueePanel panel = new MarqueePanel();
panel.setWrap(true);
panel.setWrapAmount(0);
panel.setPreferredWidth(250);
JLabel label = new JLabel( new ImageIcon( "heartbeat.jpg" ) );
panel.add( label );
frame.add( panel );
If you want the image to fully appear at the left when it is displayed you can change the startScrolling() method and use scrollOffset = 0;.
I got a class with a resizable background. There are paintings over that background(using a paint method and Java2D).
How can i delete everything that was drawn every time that the background gets a resize? (To eventually draw again in the correct places) Is there any sort of transform i can do on the already-drawn objects(like scaling to fit the image again)?
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Background extends JLabel implements ChangeListener {
private ImageIcon background;
private BufferedImage image;
public Background(JPanel parent){
super();
parent.add(this);
try {
image = ImageIO.read(new File("/example/background"));
} catch (IOException e) {
e.printStackTrace();
}
this.background = new ImageIcon(image);
this.setIcon(background);
}
public void stateChanged(ChangeEvent e) {
int value = ((JSlider) e.getSource()).getValue();
double scale = value / 100.0;
BufferedImage scaled = getScaledImage(scale);
this.setIcon(new ImageIcon(scaled));
this.revalidate();
}
private BufferedImage getScaledImage(double scale) {
int w = (int) (scale * image.getWidth());
int h = (int) (scale * image.getHeight());
BufferedImage bi = new BufferedImage(w, h, image.getType());
Graphics2D g2 = bi.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BICUBIC);
AffineTransform at = AffineTransform.getScaleInstance(scale, scale);
g2.drawRenderedImage(image, at);
g2.dispose();
return bi;
}
#Override
public void paint(Graphics g){
super.paint(g);
Graphics2D graphObj = (Graphics2D) g;
RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);rh.put(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
graphObj.setRenderingHints(rh);
graphObj.fillOval(500, 500, 20, 20);
graphObj.finalize();
}
}
Consider:
Drawing in a paintComponent(...) override, not a paint(...) override.
Save a List<Point> where each Point is normalized, say to a 1000 by 1000 size.
Then in the paintComponent method, iterate through each Point in a for loop, scaling it to the current component size, and drawing it.
You'll want to scale any image drawn in the component in a ComponentListener, and then call repaint().
Or perhaps even better, scale the image drawn using the Graphics#drawImage(...) overload that takes width and height parameters.
e.g.,
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MyBackground extends JPanel {
private BufferedImage img;
public MyBackground(BufferedImage img) {
this.img = img;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
}
private static void createAndShowGui() {
String comfyChair = "https://duke.kenai.com/comfyChair/ComfyChairRad.png";
BufferedImage img;
try {
URL url = new URL(comfyChair);
img = ImageIO.read(url);
MyBackground mainPanel = new MyBackground(img);
JFrame frame = new JFrame("MyBackground");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
example 2:
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MyBackground extends JPanel {
public static final double NORM_CONST = 1.0;
private BufferedImage img;
private List<List<Point2D>> normalizedPoints = new ArrayList<List<Point2D>>();
private List<Point2D> pointSubList;
public MyBackground(BufferedImage img) {
this.img = img;
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (List<Point2D> pointList : normalizedPoints) {
if (pointList.size() > 1) {
for (int i = 1; i < pointList.size(); i++) {
Point p1 = deNormalize(pointList.get(i - 1));
Point p2 = deNormalize(pointList.get(i));
g2.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
}
if (pointSubList != null && pointSubList.size() > 1) {
for (int i = 1; i < pointSubList.size(); i++) {
Point p1 = deNormalize(pointSubList.get(i - 1));
Point p2 = deNormalize(pointSubList.get(i));
g2.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
}
private Point deNormalize(Point2D p2d) {
int x = (int) (p2d.getX() * getWidth() / NORM_CONST);
int y = (int) (p2d.getY() * getHeight() / NORM_CONST);
return new Point(x, y);
}
private class MyMouseAdapter extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
Point2D p = normalizePoint(e.getPoint());
pointSubList = new ArrayList<>();
pointSubList.add(p);
}
#Override
public void mouseReleased(MouseEvent e) {
Point2D p = normalizePoint(e.getPoint());
pointSubList.add(p);
normalizedPoints.add(pointSubList);
pointSubList = null;
repaint();
}
#Override
public void mouseDragged(MouseEvent e) {
Point2D p = normalizePoint(e.getPoint());
pointSubList.add(p);
repaint();
}
private Point2D normalizePoint(Point point) {
double x = (NORM_CONST * point.x) / getWidth();
double y = (NORM_CONST * point.y) / getHeight();
Point2D result = new Point2D.Double(x, y);
return result;
}
}
private static void createAndShowGui() {
String comfyChair = "https://duke.kenai.com/comfyChair/ComfyChairRad.png";
BufferedImage img;
try {
URL url = new URL(comfyChair);
img = ImageIO.read(url);
MyBackground mainPanel = new MyBackground(img);
JFrame frame = new JFrame("MyBackground");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I'm trying to get the PageFormat correct when I print. Below is an example program that shows my dilemma: I get a different result when I use printJob.setPrintable(printable) than when I use printJob.setPageable(book) when I create a Book object using the default PageFormat from the Print job.
When I run it, and click "Print", then "Print using Book", I see this console output:
doPrint(false)
printing on 612.000000x792.000000 paper, imageable area=588.960000x768.960000
printing on 612.000000x792.000000 paper, imageable area=588.960000x768.960000
printing on 612.000000x792.000000 paper, imageable area=588.960000x768.960000
doPrint(true)
printing on 612.000000x792.000000 paper, imageable area=468.000000x648.000000
printing on 612.000000x792.000000 paper, imageable area=468.000000x648.000000
What gives? The default page format when using Book sucks and uses 1" margin on each side of the page; the "real" page format only needs about 1/6" margin on each side.
example program here:
package com.example.printing;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.geom.Rectangle2D;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PrintRectangles extends JFrame
{
static final int Nrectangles = 3;
static class RectangleThingy extends JPanel implements Printable
{
#Override public int print(Graphics graphics,
PageFormat pageFormat,
int pageIndex)
throws PrinterException
{
describePageFormat(pageFormat);
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
}
else {
Graphics2D g2d = (Graphics2D)graphics;
g2d.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
double w = pageFormat.getImageableWidth();
double h = pageFormat.getImageableHeight();
final int N = (Nrectangles - 1) / 2;
final double spacing = 7.2; // 1/10 inch
g2d.setStroke(new BasicStroke(0.1f));
for (int i = -N; i <= N; ++i)
{
double dx = i*spacing;
Rectangle2D r = new Rectangle2D.Double(
dx, dx, w-2*dx, h-2*dx
);
g2d.draw(r);
}
Rectangle2D rthick = new Rectangle2D.Double(
0, 0, w, h
);
g2d.setStroke(new BasicStroke(1.0f));
g2d.draw(rthick);
return(PAGE_EXISTS);
}
}
private void describePageFormat(PageFormat pageFormat) {
System.out.println(String.format("printing on %fx%f paper, imageable area=%fx%f",
pageFormat.getWidth(),
pageFormat.getHeight(),
pageFormat.getImageableWidth(),
pageFormat.getImageableHeight()
));
}
}
static private class PrintPreviewPanel extends JPanel
{
final private Printable p;
final private PageFormat pageFormat;
public PrintPreviewPanel(Printable p, PageFormat pf)
{
this.p = p;
this.pageFormat = pf;
}
#Override public Dimension getPreferredSize() {
return new Dimension((int)this.pageFormat.getWidth(),
(int)this.pageFormat.getHeight());
}
#Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
try {
p.print(g, this.pageFormat, 0);
} catch (PrinterException e) {
e.printStackTrace();
}
}
}
public PrintRectangles(String title) {
super(title);
JPanel panel = new JPanel();
setContentPane(panel);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JButton printButton = new JButton("Print");
JButton printUsingBookButton = new JButton("Print using Book");
JButton printPreviewButton = new JButton("Print preview");
panel.add(printButton);
panel.add(printUsingBookButton);
panel.add(printPreviewButton);
printButton.addActionListener(new AbstractAction("print") {
#Override public void actionPerformed(ActionEvent e) {
doPrint(false);
}
});
printUsingBookButton.addActionListener(new AbstractAction("printUsingBook") {
#Override public void actionPerformed(ActionEvent e) {
doPrint(true);
}
});
printPreviewButton.addActionListener(new AbstractAction("printPreview") {
#Override public void actionPerformed(ActionEvent e) {
doPrintPreview();
}
});
}
protected void doPrint(boolean useBook) {
RectangleThingy rectangleThingy = new RectangleThingy();
System.out.println("doPrint("+useBook+")");
try
{
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat pageFormat = printJob.getPageFormat(null);
if (useBook)
{
Book book = new Book();
book.append(rectangleThingy, pageFormat);
printJob.setPageable(book);
}
else
{
printJob.setPrintable(rectangleThingy);
}
if (printJob.printDialog())
printJob.print();
}
catch(PrinterException pe) {
System.out.println("Error printing: " + pe);
}
}
protected void doPrintPreview() {
RectangleThingy rt = new RectangleThingy();
JFrame frame = new JFrame("print preview");
// hack for now -- how do we get this from the printer?
Paper paper = new Paper();
double dotsperinch = 72;
double margin = 0.125*dotsperinch;
double w = 8.5*dotsperinch;
double h = 11*dotsperinch;
paper.setImageableArea(margin, margin, w-2*margin, h-2*margin);
paper.setSize(w, h);
PageFormat pfmt = new PageFormat();
pfmt.setPaper(paper);
frame.setContentPane(new PrintPreviewPanel(rt, pfmt));
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new PrintRectangles("PrintRectangles").start();
}
private void start() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
Hmm. After trying a number of fruitless efforts, it looks like setting a page to zero margin and then calling PrinterJob.validatePage() seems to be the only way I can get a valid minimum-margin PageFormat:
static private PageFormat getMinimumMarginPageFormat(PrinterJob printJob) {
PageFormat pf0 = printJob.defaultPage();
PageFormat pf1 = (PageFormat) pf0.clone();
Paper p = pf0.getPaper();
p.setImageableArea(0, 0,pf0.getWidth(), pf0.getHeight());
pf1.setPaper(p);
PageFormat pf2 = printJob.validatePage(pf1);
return pf2;
}
and then I can change doPrint() to:
protected void doPrint(boolean useBook) {
RectangleThingy rectangleThingy = new RectangleThingy();
System.out.println("doPrint("+useBook+")");
try
{
PrinterJob printJob = PrinterJob.getPrinterJob();
if (useBook)
{
Book book = new Book();
book.append(rectangleThingy, getMinimumMarginPageFormat(printJob));
printJob.setPageable(book);
}
else
{
printJob.setPrintable(rectangleThingy);
}
if (printJob.printDialog())
printJob.print();
}
catch(PrinterException pe) {
System.out.println("Error printing: " + pe);
}
}
I'm trying to capture the screen and then paint the image to a JFrame recursively while scaling the image (to create that effect you get when you look at a mirror in a mirror).
I'm having trouble with my code - it doesn't paint any graphics. What am I doing wrong?
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
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.image.BufferedImage;
import javax.swing.JFrame;
public class ScreenCapture extends JFrame {
BufferedImage screenCapture;
Graphics screenCaptureGraphics;
private static int recurseCount = 0;
private static float $scale = 0.9f;
private static float scale = 1.0f;
private static int height;
private static int width;
ScreenCapture() {
try {
screenCapture = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
height = screenCapture.getHeight();
width = screenCapture.getWidth();
setSize(new Dimension(width, height));
addWindowListener(new LocalWindowListener());
Graphics g = recursiveDraw(screenCapture, getGraphics());
paint(g);
} catch (HeadlessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Graphics recursiveDraw(BufferedImage img, Graphics imgG) {
updateScale(++recurseCount);
float newWidth = scale*width;
float newHeight = scale*height;
int w = (int) newWidth;
int h = (int) newHeight;
System.out.println("W: " + w + "; H: " + h);
if (w >= 10 && h >= 10) {
//scale image
System.out.print("Creating scaled Image...");
Image scaled = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
imgG = resized.createGraphics();
imgG.drawImage(scaled, 0, 0, null);
System.out.println("...Image drawn to graphics");
//return new graphics
return recursiveDraw(resized, imgG);
} else {
//otherwise return old graphics
System.out.println("Completed.");
return imgG;
}
}
private void updateScale(int count) {
for (int i=0; i<count; i++) {
scale *= $scale;
}
System.out.println("Updated scale: " + scale + "; Recurse count: " + recurseCount);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ScreenCapture().setVisible(true);
}
});
}
private class LocalWindowListener extends WindowAdapter {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0); return;
}
}
}
EDIT:
This is what I tried after #andrew-thompson 's answer:
ScreenCapture() {
try {
screenCapture = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
height = screenCapture.getHeight();
width = screenCapture.getWidth();
setSize(new Dimension(width, height));
addWindowListener(new LocalWindowListener());
setLayout(new GridLayout());
add(new PaintPanel());
} catch (HeadlessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class PaintPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
g=recursiveDraw(screenCapture, g);
//what to do with g?
}
}
I still have the same problem where I don't know how to make the BufferedImage paint to the graphics.
would separate out your Swing code from your recursive image creation code. In fact consider creating a static method that creates and returns the BufferedImage and that has no Swing code in it. Then have your GUI call the method when it wishes, and take the image and either write it to disk or display it in a JLabel's ImageIcon.
When I did this (today in fact), I created a recursive method with this signature
private static void recursiveDraw(BufferedImage img, Graphics imgG, double scale) {
and with this method body (in pseudo-code)
start recursiveDraw method
// most important: all recursions must have a good ending condition:
get img height and width. If either <= a min, return
create a BufferedImage, smlImg, for the smaller image using the height,
width and scale factor
Get the Graphics object, smlG, from the small image
Use smlG.drawImage(...) overload to draw the big image in shrunken
form onto the little image
recursively call recursiveDraw passing in smlImg, smlG, and scale.
dispose of smlG
draw smlImg (the small image) onto the bigger one using the bigger's
Graphics object (passed into this method) and a different
overload of the drawImage method.
end recursiveDraw method
This algorithm resulted in images like:
For example:
import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class RecursiveDrawTest {
private static final Color BACKGRND_1 = Color.green;
private static final Color BACKGRND_2 = Color.MAGENTA;
private static final Color FOREGRND_1 = Color.blue;
private static final Color FOREGRND_2 = Color.RED;
private static void createAndShowGui() {
final JPanel mainPanel = new JPanel(new BorderLayout());
final JSlider slider = new JSlider(50, 90, 65);
slider.setMajorTickSpacing(10);
slider.setMinorTickSpacing(5);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
JPanel southPanel = new JPanel();
southPanel.add(new JLabel("Percent Size Reduction:"));
southPanel.add(slider);
southPanel.add(new JButton(new AbstractAction("Create Recursive Image") {
#Override
public void actionPerformed(ActionEvent arg0) {
try {
double scale = slider.getValue() / 100.0;
BufferedImage img = createRecursiveImg(scale);
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
Window win = SwingUtilities.getWindowAncestor(mainPanel);
JDialog dialog = new JDialog(win, "Image", ModalityType.MODELESS);
dialog.getContentPane().add(label);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
} catch (AWTException e) {
e.printStackTrace();
}
}
}));
mainPanel.add(new JScrollPane(new JLabel(new ImageIcon(createLabelImg()))),
BorderLayout.CENTER);
mainPanel.add(southPanel, BorderLayout.PAGE_END);
JFrame frame = new JFrame("RecursiveDrawTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
// create a background image to display in a JLabel so that the GUI
// won't be boring.
private static BufferedImage createLabelImg() {
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int width = (5 * d.width) / 6;
int height = (5 * d.height) / 6;
BufferedImage img = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setPaint(new GradientPaint(0, 0, BACKGRND_1, 40, 40, BACKGRND_2, true));
g2.fillRect(0, 0, width, height);
g2.setPaint(new GradientPaint(0, height, FOREGRND_1, 40, height - 40, FOREGRND_2, true));
g2.fillOval(0, 0, 2 * width, 2 * height);
g2.dispose();
return img;
}
// non-recursive image to get the initial image that will be drawn recursively
public static BufferedImage createRecursiveImg(double scale) throws AWTException {
Robot robot = new Robot();
Dimension screenSz = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRect = new Rectangle(screenSz);
BufferedImage img = robot.createScreenCapture(screenRect);
Graphics g = img.getGraphics();
recursiveDraw(img, g, scale); // call recursive method
g.dispose();
return img;
}
// recursive method to draw image inside of image
private static void recursiveDraw(BufferedImage img, Graphics g, double scale) {
int w = img.getWidth();
int h = img.getHeight();
int smlW = (int)(w * scale);
int smlH = (int)(h * scale);
// criteria to end recursion
if (smlW <= 1 || smlH <= 1) {
return;
}
BufferedImage smlImg = new BufferedImage(smlW, smlH, BufferedImage.TYPE_INT_ARGB);
Graphics smlG = smlImg.getGraphics();
// draw big image in little image, scaled to little image
smlG.drawImage(img, 0, 0, smlW, smlH, null);
// recursive call
recursiveDraw(smlImg, smlG, scale);
smlG.dispose(); // clear resources when done with them
// these guys center the smaller img on the bigger
int smlX = (w - smlW) / 2;
int smlY = (h - smlH) / 2;
// draw small img on big img
g.drawImage(smlImg, smlX, smlY, smlW, smlH, null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Graphics g = recursiveDraw(screenCapture, getGraphics());
Don't call getGraphics(). Override paint(Graphics)1 & use the supplied Graphics instance.
When using Swing, it is actually best to override the paintComponent(Graphics) method of a JComponent or JPanel. Then add that to the top-level container.
Is this what you are hoping for :
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
public class CaptureScreen extends JPanel
{
private BufferedImage screenShot;
private JLabel imageLabel;
private BufferedImage secondScreenShot;
public void createAndDisplayGUI()
{
JFrame frame = new JFrame("CAPTURE SCREEN");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
//imageLabel = new JLabel();
//getImageForLabel();
//add(imageLabel);
frame.getContentPane().add(this);
frame.setSize(600, 600);
frame.setVisible(true);
}
private void getImageForLabel()
{
Robot robot = null;
try
{
robot = new Robot();
}
catch(Exception e)
{
e.printStackTrace();
}
screenShot = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIcon icon = new ImageIcon(screenShot);
imageLabel.setIcon(icon);
}
public void paintComponent(Graphics g)
{
Robot robot = null;
try
{
robot = new Robot();
}
catch(Exception e)
{
e.printStackTrace();
}
screenShot = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
secondScreenShot = getScaledImage((Image) screenShot, 300, 300);
g.drawImage(screenShot, 0, 0, null);
g.drawImage(secondScreenShot, 150, 150, null);
}
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;
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new CaptureScreen().createAndDisplayGUI();
}
});
}
}
Here is the output :
Get rid of the recursion. Create a single buffered image of the correct size and create a Graphics object for it. Just use a loop to draw progressively smaller scaled images down to whatever threshold you choose. Finally use g.drawImage() inside paintComponent() to draw your image to the screen. If you keep the recursion you need to pass the image and continually overlay the scaled down image. You do not need to return anything from the method.