Printing jpanel data where page width is greater than height - java

In my desktop application i need to print jPanel data on dot matrix printer where paper size should be 10x6. In java we have a restriction that width should not greater than height. But how can i accomplish my task by crossing this limit. If i set the page format with height is smaller than width it is treating it as A4 paper and feed the bottom of the paper.
If I didn't specify the page format it is printing fine but giving lot of margin(top,bottom,left,right). I am unable to change the margins. If set only the margins it is treating page as A4 and giving feed at bottom.
I need to print the data on pre printed page with alignment. Is there any other way to do this. Can I use Landscape, If so how to control the text flow (from bottom to top - X axis).
This is my code
PrinterJob job = PrinterJob.getPrinterJob();
PageFormat pageFormat = job.defaultPage();
pageFormat.setOrientation(PageFormat.LANDSCAPE);
job.setPrintable(this,pageFormat);
try {
job.print();
} catch (PrinterException ex) {
System.out.println(ex);
}
paint method
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
if (page > 0) {
return NO_SUCH_PAGE;
}
g.setFont(new java.awt.Font("Sans Serif", java.awt.Font.PLAIN, 10));
Graphics2D g2d = (Graphics2D)g;
AffineTransform old = g2d.getTransform();
if (pf.getOrientation() == PageFormat.LANDSCAPE) {
g2d.rotate( -Math.PI / 2, 0, 0);
g2d.translate( -pf.getImageableWidth(), 0);
}
else {
g2d.rotate(Math.PI / 2, 0, 0);
g2d.translate(0, -pf.getImageableHeight());
}
jPanel1.printAll(g2d);
g2d.setTransform(old);
//g2d.translate(70, 30);
return PAGE_EXISTS;
}
Thanks in advance.

Set PageFormat's orientation to landscape and rotate the content. In the print() method rotate and translate the content.
Graphics2D g2d = (Graphics2D) g;
AffineTransform old = g2d.getTransform();
if (contentOrientation == ORIENTATION_DOWN_UP) {
g2d.rotate( -Math.PI / 2, 0, 0);
g2d.translate( -w, 0);
}
else {
g2d.rotate(Math.PI / 2, 0, 0);
g2d.translate(0, -h);
}
//paint all your content here
g2d.setTransform(old);

Related

Fill rectangle with image in Java

How can I fill the following rectangle using an image? Can anyone help me please?
public void paintComponent(Graphics g) {
setOpaque(false);
//Paint a filled rectangle at user's chosen point.
if (point != null) {
g.drawRect(0, 0,
rectWidth - 1, rectHeight - 1);
g.setColor(Color.yellow);
g.fillRect(1, 1,
rectWidth - 2, rectHeight - 2);
}}
I tried this code but I couldn't find a way to make it work:
File imageFile = new File("duck.jpg");
BufferedImage img;
Graphics2D graph = img.createGraphics();
graph.setColor(Color.BLACK);
graph.fill(new Rectangle(1, 2, rectWidth, rectHeight));
graph.dispose();
ImageIO.write(img, "jpg", new File("duck.jpg"));
You have to load an image into an Image object (like BufferedImage) and then call
graphics.drawImage()
on that image, giving the coordinates and other info.
Look in the tutorial for more info

Inner-Transparent Selection Window in Java using GlassPane

I am trying to achieve the following
http://www.qksnap.com/i/3hunq/4ld0v/screenshot.png
I am currently able to draw rectangles successfully on a semi-transparent glasspane background using the following code:
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g.setColor(Color.black); // black background
g.fillRect(0, 0, frame.getWidth(), frame.getHeight());
g2.setColor(Color.GREEN.darker());
if (getRect() != null && isDrawing()) {
g2.draw(getRect()); // draw our rectangle (simple Rectangle class)
}
g2.dispose();
}
Which works great, however, I would love to have the area within the rectangle be completely transparent while the outside was still darken much like the screenshot above.
Any ideas?
..have the area within the rectangle be completely transparent while the outside was still darken much like the screenshot above.
Create a Rectangle (componentRect) that is the size of the component being painted.
Create an Area (componentArea) of that shape (new Area(componentRect)).
Create an Area (selectionArea) of the selectionRectangle.
Call componentArea.subtract(selectionArea) to remove the selected part.
Call Graphics.setClip(componentArea)
Paint the semi-transparent color.
(Clear the clipping area if more paint operations are required).
As Andrew has suggested (just beat me while I was finishing off my example)
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
g.setColor(Color.black); // black background
Area area = new Area();
// This is the area that will filled...
area.add(new Area(new Rectangle2D.Float(0, 0, getWidth(), getHeight())));
g2.setColor(Color.GREEN.darker());
int width = getWidth() - 1;
int height = getHeight() - 1;
int openWidth = 200;
int openHeight = 200;
int x = (width - openWidth) / 2;
int y = (height - openHeight) / 2;
// This is the area that will be uneffected
area.subtract(new Area(new Rectangle2D.Float(x, y, openWidth, openHeight)));
// Set up a AlphaComposite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2.fill(area);
g2.dispose();
}

Java, using AffineTransform not rotating exactly centered

I'm trying to rotate an image, but it's getting slightly messed up when I'm rotating it, and it looks like it's not rotating it on center. So if I go around it looks like it's being truncated. Is there a better method to get the "center" of the image?
public void RotateImageLeft() {
try {
BufferedImage newImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), originalImage.getType());
AffineTransform tx = new AffineTransform();
tx.rotate(Math.toRadians(-90.0), originalImage.getWidth() / 2, originalImage.getHeight() / 2);
Graphics2D g2 = newImage.createGraphics();
g2.drawImage(originalImage, tx, null);
originalImage = newImage;
this.repaint();
g2.dispose();
} catch (Exception ex) {
ex.toString();
}
//g2d.drawImage(getResImage(), rescale, x, y);
}
For full code disclosure, here's more code. Here's my painComponent overridden method:
public void paintComponent(Graphics g) {
super.paintComponent(g);
resizeImage();
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(getResImage(), rescale, x, y);
}
Here's the resizeImage() method that gets called:
public void resizeImage() {
Graphics g = getResImage().getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, getResImage().getWidth(), getResImage().getHeight());
int scaledWidth = (int) ((getOriginalImage().getWidth() * getHeight()
/ getOriginalImage().getHeight()));
if (scaledWidth < getWidth()) {
int leftOffset = getWidth() / 2 - scaledWidth / 2;
int rightOffset = getWidth() / 2 + scaledWidth / 2;
g.drawImage(getOriginalImage(),
leftOffset, 0, rightOffset, getHeight(),
0, 0, getOriginalImage().getWidth(), getOriginalImage().getHeight(),
null);
} else {
int scaledHeight = (getOriginalImage().getHeight() * getWidth())
/ getOriginalImage().getWidth();
int topOffset = getHeight() / 2 - scaledHeight / 2;
int bottomOffset = getHeight() / 2 + scaledHeight / 2;
g.drawImage(getOriginalImage(),
0, topOffset, getWidth(), bottomOffset,
0, 0, getOriginalImage().getWidth(), getOriginalImage().getHeight(),
null);
}
}
I'm using the ResizeImage method since I want any image to fit correctly on my 720/432 panel.
Here's some example pictures.
Pre-rotated
Post-rotated:
New code: (new image is the correct height/width of rotated image, still getting black bars. Screens below.
public void RotateImageLeft() {
try {
BufferedImage newImage = new BufferedImage( originalImage.getHeight(),originalImage.getWidth(), originalImage.getType());
AffineTransform tx = new AffineTransform();
tx.rotate(Math.toRadians(-90.0), newImage.getWidth() / 2, (newImage.getHeight() / 2));
Graphics2D g2 = newImage.createGraphics();
g2.drawImage(originalImage, tx, null);
originalImage = newImage;
this.repaint();
g2.dispose();
} catch (Exception ex) {
ex.toString();
}
}
Post rotate:
From my answer to another similar question
If you're rotating then this will work for 90 degrees.
move image so centered "around" the origin
plain rotate() call with no extra parameters
Move image back into the center remembering that now width = old height and height = old width.
Also remember the affine transform steps work in reverse order.
AffineTransform tx = new AffineTransform();
// last, width = height and height = width
tx.translate(originalImage.getHeight() / 2,originalImage.getWidth() / 2);
tx.rotate(Math.PI / 2);
// first - center image at the origin so rotate works OK
tx.translate(-originalImage.getWidth() / 2,-originalImage.getHeight() / 2);
If you want to rotate an image without cropping you need to add black bars around it first, since a rotated rectangle will always have a bigger bounding box than an axis-aligned one (exception: rotating a square by multiples of 90 degrees).
So what you want to do is do some trigonometric calculations beforehand to decide the maximum Width/Height of the rotated image, and combine that with the original Width/Height. Resize your image (centering it) using those dimensions, rotate it, and then crop it back to the Width/Height of the rotated image.

printing bufferedimage to a printer

i have an application from which i want to print an image. The image is loaded as a BufferedImage object. The problem is, when i print the image (to the postscript or to the pdf file), the quality is really poor.
When i'm using some other tools (basically any picture viewer application which can print the image) the result is significantly better.
I know there can be some problems with the DPI vs resolution but i'm not exactly sure how to compute the correct values for printing.
I tried to google and tried some methods, but nothing seems to work as i expected.
Basicaly i just want to print an image (in resolution let's say 3000x2000) to a printer (with DPI for example 600x600).
This is how i create the print job:
PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
printAttributes.add(PrintQuality.HIGH);
printAttributes.add(new PrinterResolution(600, 600 PrinterResolution.DPI));
printAttributes.add(new Destination(URI.create("file:/tmp/test.ps")));
PageFormat pf = printerJob.defaultPage();
Paper paper = pf.getPaper();
double xMargin = 0.0;
double yMargin = 0.0;
paper.setImageableArea(xMargin, yMargin, paper.getWidth() - 2 * xMargin, paper.getHeight() - 2 * yMargin);
pf.setPaper(paper);
// create new Printable for the specified image
printerJob.setPrintable(PrintableImage.get(image), pf)
if (printerJob.printDialog(printAttributes)) {
printerJob.print(printAttributes);
}
Where image is BufferedImage and PrintableImage.get returns new instance which implements Printable
Then the actual print is doing this way (i let the commented code which i tried but didn't work for me)
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (image == null)
throw new PrinterException("no image specified to be printed");
// We have only one page, and 'page' is zero-based
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
// tranlate the coordinates (according to the orientations, margins, etc)
Graphics2D printerGraphics = (Graphics2D) graphics;
//g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
//g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
printerGraphics.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
// THIS IS A TEST - javax.printing api uses 72 DPI, but we have 600DPI set for the printer
//AffineTransform at = printerGraphics.getTransform();
//printerGraphics.scale((double)72 / (double)600, (double)72 / (double)600);
//printerGraphics.drawRenderedImage(image, null);
//printerGraphics.setTransform(at);
//if(printerGraphics != null)
//return PAGE_EXISTS;
double scale = 72.0 / 600.0;
Dimension pictureSize = new Dimension((int)Math.round(image.getWidth() / scale), (int) Math.round(image.getHeight() / scale));
// center the image horizontaly and verticaly on the page
int xMargin = (int) ((pageFormat.getImageableWidth() - image.getWidth()) / 2);
int yMargin = (int) ((pageFormat.getImageableHeight() - image.getHeight()) / 2);
xMargin = yMargin = 0;
System.out.println(String.format("page size [%.2f x %.2f], picture size [%.2f x %.2f], margins [%d x %d]", pageFormat.getImageableWidth(), pageFormat.getImageableHeight(), pictureSize.getWidth(), pictureSize.getHeight(), xMargin, yMargin));
printerGraphics.drawImage(image, xMargin, yMargin, (int)pageFormat.getWidth(), (int)pageFormat.getHeight(), null);
//printerGraphics.drawImage(image, 0, 0, null);
//printerGraphics.drawImage(image, xMargin, yMargin, pictureSize.width, pictureSize.height, null);
//printerGraphics.drawImage(image, xMargin, yMargin, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableHeight(), 0, 0, pictureSize.width, pictureSize.height, null);
//printerGraphics.drawImage(image, 0, 0, (int) pageFormat.getWidth() - xMargin, (int) pageFormat.getHeight() - yMargin, 0, 0, pictureSize.width, pictureSize.height, null);
return PAGE_EXISTS;
}
Does anybody solves the same problem?
Any help would be appreciated.
Thanks
Matej
This is how I did it. It works smoothly. Note that this code snippet doesn't center the image.
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return (NO_SUCH_PAGE);
} else {
double pageHeight = pageFormat.getImageableHeight(), pageWidth = pageFormat.getImageableWidth();
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if (pageHeight < image.getHeight() || pageWidth < image.getWidth()) {
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(image, 0, 0, (int) pageWidth, (int) pageHeight - textSize, null);
} else {
g2d.drawImage(image, 0, 0, null);
}
g2d.dispose();
return (PAGE_EXISTS);
}
}
#Viktor Fonic
Thank you for this, I was searching a lot to do this!
You're solution works perfectly, but has a small error,
textSize was not declared, so:
int textSize = (int) (pageHeight - image.getHeight()*pageWidth/image.getWidth());

Rotating BufferedImage instances

I am having trouble getting a rotated BufferedImage to display. I think the rotation is working just fine, but I can't actually draw it to the screen. My code:
Class extends JPanel {
BufferedImage img;
int rotation = 0;
public void paintComponent(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
img2d = img.createGraphics();
img2d.rotate(Math.toRadians(rotation), img.getWidth() / 2, img.getHeight() / 2);
g.drawImage(img, imgx, imgy, null);
this.repaint();
}
}
This is not working for me. I could not find any way to draw the rotated img2d onto g.
EDIT: I have multiple objects that are being drawn onto g, so I can't rotate that. I need to be able to rotate things individually.
Maybe you should try using AffineTransform like this:
AffineTransform transform = new AffineTransform();
transform.rotate(radians, bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
bufferedImage = op.filter(bufferedImage, null);
Hope this helps.
I would use Graphics2D.drawImage(image, affinetranform, imageobserver).
The code example below rotates and translates an image to the center of the component. This is a screenshot of the result:
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("Test");
frame.add(new JComponent() {
BufferedImage image = ImageIO.read(
new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png"));
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// create the transform, note that the transformations happen
// in reversed order (so check them backwards)
AffineTransform at = new AffineTransform();
// 4. translate it to the center of the component
at.translate(getWidth() / 2, getHeight() / 2);
// 3. do the actual rotation
at.rotate(Math.PI / 4);
// 2. just a scale because this image is big
at.scale(0.5, 0.5);
// 1. translate the object so that you rotate it around the
// center (easier :))
at.translate(-image.getWidth() / 2, -image.getHeight() / 2);
// draw the image
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, at, null);
// continue drawing other stuff (non-transformed)
//...
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
You are rotating the graphics for drawing into your image, not the image. Thats why you see no effect. Apply the rotation to the graphics you are painting on and it will draw the image rotated:
public void paintComponent(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
g.rotate(Math.toRadians(rotation), img.getWidth() / 2, img.getHeight() / 2);
g.drawImage(img, imgx, imgy, null);
this.repaint();
}
This will probably not draw entirely what you expect, the rotation will revolve around the coordinate origin. For the image to be rotate around its center you need to apply a coordinate translation before the rotation, for example:
g.translate(imgx >> 1, imgy >> 1);
The Graphics2D Tutorial has some more examples.
I know this question is old but I came up with a solution that has some advantages:
creates image of correct size.
correct offset.
does not unnecessarily rotate by 0° or 360°.
works for negative angles (e.g. -90°).
works when input is BufferedImage.TYPE_CUSTOM.
As it is, it is assumed that the angle is a multiple of 90°. The only improvement that one might need is to use an Enum for angle instead of just int.
Here's my code:
public static BufferedImage rotateBufferedImage(BufferedImage img, int angle) {
if (angle < 0) {
angle = 360 + (angle % 360);
}
angle %= 360;
if (angle == 0) {
return img;
}
final boolean r180 = angle == 180;
if (angle != 90 && !r180 && angle != 270)
throw new IllegalArgumentException("Invalid angle.");
final int w = r180 ? img.getWidth() : img.getHeight();
final int h = r180 ? img.getHeight() : img.getWidth();
final int type = img.getType() == BufferedImage.TYPE_CUSTOM ? BufferedImage.TYPE_INT_ARGB : img.getType();
final BufferedImage rotated = new BufferedImage(w, h, type);
final Graphics2D graphic = rotated.createGraphics();
graphic.rotate(Math.toRadians(angle), w / 2d, h / 2d);
final int offset = r180 ? 0 : (w - h) / 2;
graphic.drawImage(img, null, offset, -offset);
graphic.dispose();
return rotated;
}
public static BufferedImage rotateBufferedImage(String img, int angle) throws IOException {
return rotateBufferedImage(Paths.get(img), angle);
}
public static BufferedImage rotateBufferedImage(Path img, int angle) throws IOException {
return rotateBufferedImage(ImageIO.read(img.toFile()), angle);
}

Categories