Using JAI to rotate a grayscale image increases contrast
I am trying to use JAI to do a rotation task on an image. I can get this to work with no problem. However, there is a serious loss of midtones in the image. The image can be rotated in Photoshop without this lack of contrast.
Please see the following 3 images side by side to see what I mean:
The top image is the original, the middle is rotated in Photoshop to prove it can be done, and the bottom is from my code.
To see actual images see here:
Before the turn: http://imgur.com/eiAOO.jpg After the turn: http://imgur.com/TTUKS.jpg
You can see the problem most clearly if you load images in two different tabs and move between them.
In terms of code, I am loading an image like this:
public void testIt() throws Exception {
File source = new File("c:\\STRIP.jpg");
FileInputStream fis = new FileInputStream(source);
BufferedImage sourceImage = ImageIO.read(fis);
fis.close();
BufferedImage rotatedImage = doRotate(sourceImage, 15);
FileOutputStream output = new FileOutputStream("c:\\STRIP_ROTATED.jpg");
ImageIO.write(rotatedImage, "JPEG", output);
}
and then the rotation function;
public BufferedImage doRotate(BufferedImage input, int angle) {
int width = input.getWidth();
int height = input.getHeight();
double radians = Math.toRadians(angle / 10.0);
// Rotate about the input image centre
AffineTransform rotate = AffineTransform.getRotateInstance(radians, width / 2.0, height / 2.0);
Shape rect = new Rectangle(width, height);
// Work out how big the rotated image would be..
Rectangle bounds = rotate.createTransformedShape(rect).getBounds();
// Shift the rotated image into the centre of the new bounds
rotate.preConcatenate(
AffineTransform.getTranslateInstance((bounds.width - width) / 2.0, (bounds.height - height) / 2.0));
BufferedImage output = new BufferedImage(bounds.width, bounds.height, input.getType());
Graphics2D g2d = (Graphics2D) output.getGraphics();
// Fill the background with white
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle(width, height));
RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
hints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHints(hints);
g2d.drawImage(input, rotate, null);
return output;
}
a source to share
This appears to be a bug in JAI that has been around for a while:
The earliest mention that I was able to find this issue appears here . This original article points out an old jai-core issue here . After reading this resolution, it seems like there is a root bug that is still open and described here .
Whether or not all of these detective actions apply to your application, it is possible to create a color space that is more bearable than the default that JAI uses for your test code.
In the absolute worst case, you can write the pixel traversal yourself to create a rotated image. This is not the optimal solution, but I mention it for completeness if you absolutely need a solution to this problem today.
a source to share