Resizing photos without text .. is RenderingHints necessary? - java

I am writing a quick little java class that resizes an image into various smaller sizes (thumbnail large/small/etc). I have seen examples that have RenderingHints in it. The output file is significantly larger than without.
My question is: Is it necessary to use RenderingHints if the images that are being resized have no text?
int IMG_WIDTH = 100;
int IMG_HEIGHT = 100;
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
g.setComposite(AlphaComposite.Src);
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
I started with a 45kb image, and the output difference is a 3kb file (without RenderingHints) versus a 24kb file (with RenderingHints)

I suppose, after reading the following stackoverflow.com question/answer:
Java Text on Image
I am inclined to think that RenderingHints will provide no benefit for me when the photos contain no text ... In which case, no text = no RenderingHints = smaller resized image

Related

How do I write a jpeg2000 with a transparent background in Java?

I'm using Java Advanced Imaging to read and write JPEG2000 images in java. When debugging in Intellij, I can view the BufferedImage and see that it's transparent. So I can stack layers on top of each other. But when I write it to a file, the background is always black. Is it something I'm doing wrong? Or is it the writer that's the problem? Do I need to be doing something specific with the J2KImageWriteParam regarding encoding etc? Unfortunately I'm fairly new to handling images programmatically, and there is little to no information or support for jpeg2000 that I can find.
BufferedImage image = ImageIO.read(new File("image.jp2"));
BufferedImage tmpImage = new BufferedImage(
image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR_PRE
);
Graphics2D g = (Graphics2D) tmpImage.getGraphics();
g.setComposite(AlphaComposite.Clear);
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.setComposite(AlphaComposite.Src);
g.drawImage(image, 0, 0, null);
ImageIO.write(tmpImage, "jpeg2000", new File("outputImage.jp2"));
g.dispose();

How to render small utf fonts in a high quality bufferedImage

I want to render a string using java in a a bufferedImage. the problem is when i use a small font (for example: 8pt) i have bad quality images and the image resolution is 72dpi.
i want to have the best quality for images and if possible change the images resolution to 360dpi.
Noted that i want to generate a database of a language words with differents fonts, font sizes and font styles. and i used the standard java API (Graphics2D, Font, RenderingHints, FontMetrics,...) to generate images.
here is my code:
public static void main(String[] args) {
String text = "ⴰⴱⴱⵓⵥⵥⵍ";
String [] polices=polices();
for(int i=0;i<polices.length;i++){
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g2d = img.createGraphics();
Font font = new Font(polices[i], Font.PLAIN, 8);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int width = fm.stringWidth(text);
int height = fm.getHeight();
g2d.dispose();
img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setFont(font);
g2d.setBackground(Color.WHITE);
g2d.clearRect(0, 0, width, height);
fm = g2d.getFontMetrics();
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
ImageIO.write(img, "png", new File("Text "+i+".png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
I searched a lot for a solution vainly, if someone can help me i will be thankfull.
A solution that uses any externe libraries is welcome too.
An 8pt font at 72dpi is 8/72*360 = size 40 font at 360dpi - so set the font size to 40.
As to how to set the DPI for an image, see the question How to set DPI information in an image?

Java blurrying background with Graphics2D

I'm using Java to create an image with text. I set the color of the background and fill it up. Then I place the text using LineBreakMeasurer. The problem is (As you can see in the attached image) the image background around the text is blurry (if you zoom on). This is a problem for me. Is it possible to fix that?
final BufferedImage image = new BufferedImage(600, 400, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setColor(new Color(255,0,0));
g2d.fillRect (0, 0, image.getWidth(), image.getHeight());
...
AttributedString attributedString = getAttributedString(text, fontSize, new Color(1.0f,1.0f,1.0f,0.9f));
AttributedCharacterIterator characterIterator = attributedString
.getIterator();
FontRenderContext fontRenderContext = g2d.getFontRenderContext();
LineBreakMeasurer measurer = new LineBreakMeasurer(characterIterator,
fontRenderContext);
while (measurer.getPosition() < characterIterator.getEndIndex()) {
TextLayout textLayout = measurer.nextLayout(width);
int currentX = x + (int)(width - textLayout.getVisibleAdvance()) / 2;
y += textLayout.getAscent();
textLayout.draw(g2d, currentX, y);
}
If you're referring to the artifacts around the letters, the problem isn't with your painting code. It's the result of saving the image as a JPEG. Save it using a non-lossy format, like PNG. You could also try reducing the compression of the JPEG, but saving as a PNG is probably easier.

Java rescaling an image creating half white half grey image

I am having a problem with the Grapics2D API, I am trying to re-size an image but instead of getting the smaller image its showing a half white and half grey area. what am I doing wrong? I tried with and without render hints and it didn't work, or is there another approach that will give me a new Buffered Image object at the specified size?
//height = 400, width = 600, capture_rect = screen size
BufferedImage img = robot.createScreenCapture(CAPTURE_RECT);
BufferedImage resized = new BufferedImage(WIDTH, HEIGHT, img.getType());
Graphics2D g = resized.createGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, 0, 0, img.getWidth(), img.getHeight(), null);
g.dispose();
setImage(resized);
See the article on Perils of Image.getScaledImage. It has some recommendations.
Here is some code it recommends:
private float xScaleFactor, yScaleFactor = ...;
private BufferedImage originalImage = ...;
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
int newW = (int)(originalImage.getWidth() * xScaleFactor);
int newH = (int)(originalImage.getHeight() * yScaleFactor);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(originalImage, 0, 0, newW, newH, null);
}
It looks like you just need to specify the new width/height and it will do the scaling for you automatically.
Or maybe the problem is with the img.getType() method. You should be able to just using:
BufferedImage.TYPE_INT_RGB // (or ARGB)
See which works the best.

How to get rid of White rectangle from an image using java

I had tired the following code to generate the thumb nail but when I place it on another image, the thumbnail has a white rectangle. How can I remove it using java graphics 2D?
Image image = javax.imageio.ImageIO.read(new File(originalFile));
BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setBackground(Color.WHITE);
graphics2D.setPaint(Color.WHITE);
graphics2D.fillRect(0, 0, thumbWidth, thumbHeight);
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
File file = new File(thumbnailFile);
if(javax.imageio.ImageIO.write(thumbImage, "png", file))
return file;
}
Even if i remove these three lines I am getting black rectangle.
graphics2D.setBackground(Color.WHITE);
graphics2D.setPaint(Color.WHITE);
graphics2D.fillRect(0, 0, thumbWidth, thumbHeight);
How to get this image as transparent? Please some one help me out.
Color transparent = new Color(0,0,0,0)
by setting Composite . here : AlphaComposite
// Create an image that supports arbitrary levels of transparency
Graphics2D g2d = (Graphics2D) image.getGraphics();
BufferedImage thumbImage = g2d.getDeviceConfiguration().createCompatibleImage(
thumbWidth, thumbHeight, Transparency.TRANSLUCENT);
..BufferedImage.TYPE_INT_RGB
That should be:
..BufferedImage.TYPE_INT_ARGB

Categories