I have background templates where java program must write some dynamic texts,
BufferedImage image = ImageIO.read(new File("background.jpg"));
Graphics g = image.createGraphics();
g.setFont(new Font("DejaVu Sans",Font.PLAIN,18));
g.drawString("Hello,World!",10,10);
When writing in such manner, I have some resolution problems around text that Java wrote.
How to write high resolution text on image by Java?
UPDATE: Here example with anti-aliasing.
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
The problem is not the drawing of the text, but the subsequent saving of the file: If you are using JPEG-compression, you will get compression artifacts, specially around sharp corners like your text.
There is no real way around this, apart from not using JPG.
Related
At present I am rendering a DAE using a c++ based graphics engine, and programmatically taking a screenshot to get the PNG image as if the camera is viewing from above (looking directly down). This is quite tedious.
Since I do not need to actually look at the models on screen, is it possible to do the same programmatically without rendering using java ?
At present, it is easy to convert between other 2d formats such as PNG to jpeg using buffered image:
BufferedImage newImage = new BufferedImage( pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB);
newImage.createGraphics().drawImage( pngImage, 0, 0, Color.BLACK, null);
Is there a similar way to load the DAE and take the equivalent of a screenshot by specifying the camera position, angle and distance as input coordinates ?
I am trying to write some programs where I load images to a panel.
Here are my 5 questions:
1> Is there any restriction on what kind(extension) of images can be loaded? I tried to load a .bmp file, it didn't load even after I renamed it with .jpg. However, some other file that were with extensions such as .png or .jpg loaded.
2>Is there a way I can cut an image through java to create a new image. Say, I have a 600x600 pixel image and I want to create a new image by selecting a 200x200 pixel from the middle of the original picture.
3>Is there a way I can resize an image?
4>Can I add an image to a scrollpane?
5> Can I rotate an image by an angle ,say 30 degree?
That's it. A little elaboration with examples will be nice. Thanks in advance.
1> Is there any restriction on what kind(extension) of images can be
loaded? I tried to load a .bmp file, it didn't load even after I
renamed it with .jpg. However, some other file that were with
extensions such as .png or .jpg loaded.
Image I/O has built-in support for GIF, PNG, JPEG, BMP, and WBMP. Image I/O is also extensible so that developers or administrators can "plug-in" support for additional formats. For example, plug-ins for TIFF and JPEG 2000 are separately available.
Check the Reading/Loading an image tutorial page
2>Is there a way I can cut an image through java to create a new
image. Say, I have a 600x600 pixel image and I want to create a new
image by selecting a 200x200 pixel from the middle of the original
picture.
Two ways. Croping the image using Clipping with Graphics. But faster approach is to use BufferedImage.getSubimage(int x, int y, int w, int h) method.
BufferedImage image = ImageIO.read("image file");
image = image.getSubimage(50, 50, 200, 200);
This will crop an image at location(x, y) == (50, 50) and size 200 x 200.
3>Is there a way I can resize an image?
The discussion about the various approach will take a size of a blog. Read through the The Perils of Image.getScaledInstance() article for good insight.
However, a quick approach for example: with cWidth and cHeight
BufferedImage tmpImage = new BufferedImage(cWidth, cHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D)tmpImage.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.drawImage(image, 0, 0, cWidth, cHeight, null);
There is working example done by MadProgrammer. It is also better to use external library such as this which does this works nicely.
4>Can I add an image to a scrollpane?
Direct adding is not suggested. use JLabel instead. Or use a custom component and override the paintComponent(Graphics g) function and draw inside it. There are some working example with these two approach. Generally working with JLabel is easier.
See this question answers. Mine including #MadProgrammer. And The custom painting official tutorial page.
5> Can I rotate an image by an angle ,say 30 degree?
Yes using the Graphics2D.rotate(double theta) function; There are actually much more things you can do with the Graphics2D API. Working examples are shown by MadProgrammer here and here.
I'm building an app which among other things allows the user to insert a text into a PDF, using a layer.
The position of the text in the PDF page can be set using the app, which renders the PDF using ICEPdf inside a JPanel. After selecting the position and the size of the layer, the app renders it to the PDF using iText (v. 5.3.2).
The problem I'm facing is that the font rendering from Swing is sightly different from the final result in the PDF.
Here are some screen-shots, both using the Helvetica plain font inside the same bounding box:
Rendering a text with Swing:
protected void paintComponent(Graphics g){
//for each line...
g.drawString(text, b0, b1);
//b0 and b1 are computed from the selected bounding box for the text
}
I have this:
Rendering a text with iText:
PdfTemplate t; //PdfTemplate is created elsewhere
ColumnText ct = new ColumnText(t);
ct.setRunDirection(PdfWriter.RUN_DIRECTION_NO_BIDI);
ct.setSpaceCharRatio(1);
ct.setSimpleColumn(new Phrase(text, font), b0, b1, b3, b4, font.getSize(), Element.ALIGN_BOTTOM);
//b0, b1, b2 and b3 are the bounding box of the text
ct.go();
I have this:
So the question is: what can be done to make Swing and iText render fonts exactly the same way? I can tweak Swing or iText, so no matter what code is modified, I need a truly WYSIWYG experience for the user.
I tried with other fonts and types, but still there are some differences between them. I think I'm missing some configuration.
Thanks.
Edit:
Font in Java is measured in Pixels, but iText measures in Points, and we know there are 72 points per inch, and for a standard windows machine there are 96 pixels per inch / dpi.
First we need to find the difference between a point and a pixel:
difference = 72 / dpi
0.75 = 72 / 96
Next we can multiply the Java font size with the difference to get the iText font size, if the java font size is 16, then the iText font size should be 12 when used with 96dpi.
iTextFontSize = difference x javaFontSize
12 = 0.75 x 16
On a windows machine 96dpi is often the norm, but remember that is not always the case, you should work it out for each different machine.
Original Post
I believe the difference is caused by rendering hints.
Solution 1:
The best way to do it would be to draw everything on a buffered image. Then the buffered image is drawn to the swing component and the exact same buffered image is drawn to the PDF as well, that way there should be no difference between them.
Alternate Idea:
Another idea that may not work as well, but will work better with your existing code is to draw the contents of the swing component directly to a buffered image then draw the buffered image to the PDF.
The following is a quick example that will draw the contents of a JPanel to a buffered image with a few different rendering hints. (Change the hints to suit your swing component)
public BufferedImage createImage(JPanel panel)
{
BufferedImage swingComponent = new BufferedImage(
panel.getHeight(), panel.getWidth(),
BufferedImage.TYPE_INT_RGB);
Graphics2D g = swingComponent.createGraphics();
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.dispose();
return swingComponent; //print this to your PDF
}
So the question is: what can be done to make Swing and iText render fonts exactly the same way?
Exactly the same? Very little. Presuming that you supply the same font characteristics to both, there may still be differences introduced in rendering.
PDF files (or really, the text phrases) hold font information—family, size, style, etc.—but it is your PDF reader that renders the text to your device. Depending on what program you use, it can use the platform's renderer or it can choose one of its own.
AFAIK, Java Swing uses its own font rendering engine, as distinct from the underlying platform's renderer. This makes it look more consistent across platforms, but also makes it very unlikely that text will be rendered the same way any other program would.
Knowing that, your options are limited:
Use a PDF reader that also uses Swing font rendering. That's a fairly limiting solution.
Use your platform's rendering engine to draw into Swing. That sounds like iffy work, and also like something SWT would have solved. Maybe you could embed an SWT component?
I need to add specific padding around large images and the current method I am using, as seen in the snippet below, is eating up memory. Opening the PNG sucks up ~300mb of memory right off the bat and making a copy of that pushes me past 700mb so I am looking for a way to do this without sucking up all available memory. Any suggestions?
...
BufferedImage img = ImageIO.read(new File("OldWorld.png"));
BufferedImage img2 = new BufferedImage(img.getHeight()+padding,img.getWidth()+padding, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img2.createGraphics();
g2.setPaint(new Color(0,0,0,0);
g2.fillRect(0, 0, img.getHeight()+padding, img.getWidth()+padding);
g2.drawImage(img, img.getHeight(),img.getWidth(), null);
...
There is no direct way to solve this.
Working with large images in Java consumes a lot of memory.
Some alternatives are:
Pre-process your images with the netpbm library
http://netpbm.sourceforge.net/.
To pad an image use a command like:
pngtopnm OldWorld.png | pnmpad -black 48 -left 48 -top 48 | pnmtopng > padded.png
Reduce the number of colors in your image so that you can use image type
BufferedImage.TYPE_INDEXED with only one byte per pixel instead of four.
Use a several tiles instead of a single large image and work
with one tile at a time. Then you avoid having a lot of image
data in memory.
i'm trying to create a program that generates images for use as multi-screen backgrounds, i'm doing this targeted at windows (in my case, 7 so that basically i can get images to change without seeing the same image on two different screens)
in my program, i read multiple image input files and compile them into a single output image that is the total size of the desktop (including black areas not seen on screens)
my question is, what class/methods are good for cropping/resizing/pasting into a new image in java because i'm coming across so many image manipulation classes and they all seem to do one tiny thing.
i will not be modifying any of the images beyond resize or crop and putting it into a certain position in the new (initially blank) image.
code can be made available as i plan to release it at some later point for whoever may like/need it.
thank you in advance, if this question has been answered, my apologies but i DID have a look around.
I do not know if this is the best method, but it is quite easy:
// load an image
Image image = javax.imageio.ImageIO.read(new File("someimage.png");
// resize it
image = image.getScaledInstance(100, 100, Image.SCALE_SMOOTH);
// create a new image to render to
BufferedImage newimg = new BufferedImage(200,100,BufferedImage.TYPE_INT_ARGB);
// get graphics to draw..
Graphics2D graphics =newimg.createGraphics();
//draw the other image on it
graphics.drawImage(image,0,0,null);
graphics.drawImage(image,100,0,null);
graphics.fillOval(20,20,40,40); //making it a bit ugly ;)
//export the new image
ImageIO.write(newimg,"png",new File("output.png"));
//done!
For simplicity I dropped all checks, exception handling, etc.