Graphics and Grayscale Images - Maximum luninance is 252 ?
Hi everybody,
I am working with 8 bit Grayscale
images and am in the process of implementing a rendering interface for
an imaging program I work on.
The interface of the "renderer" is quite simple:
import java.awt.image.BufferedImage;
/**
* A <i>renderer</i> is responsible for successfully rendering images to a
* given <i>destination</i>.
*
*/
public interface IImageRenderer {
/**
* Render an image.
*
* @param sourceImage
* the image to render
* <p>
* If
a <code>null</code> image is passed, no rendering will be
* performed.
* </p>
* @param horizontalOffset
* the horizontal offset to apply
* @param verticalOffset
* the vertical offset to apply
*/
public void renderFrame(BufferedImage sourceImage, int horizontalOffset,
int verticalOffset);
}
I came up with the following implementation:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.SwingUtilities;
import IImageRenderer;
/**
* Render images to a given <code>Graphics2D</code>.
* <p>
* The areas of the graphics not covered by the image will be filled with a
* custom background color.
* </p>
*
* @see GraphicsImageRendererTest
*/
public final class GraphicsImageRenderer implements IImageRenderer, Runnable {
/**
* Build a renderer for a specified <code>Graphics</code>.
*
* @param targetGraphics
* the
graphics where the images are to be rendered
* @param backgroundColor
* the background color to use
* <p>
* If
<code>null</code>, <code>Color.BLACK</code>
will be
* used.
* </p>
*/
public GraphicsImageRenderer(Graphics2D targetGraphics,
Color backgroundColor) {
if (backgroundColor != null) {
this.currentBackgroundColor = backgroundColor;
} else {
this.currentBackgroundColor = Color.BLACK;
}
if (targetGraphics != null) {
this.destinationGraphics = targetGraphics;
this.destinationGraphics.setBackground(backgroundColor);
} else {
this.destinationGraphics = null;
}
}
/*
* (non-Javadoc)
*
* @see IImageRenderer#renderFrame(java.awt.image.BufferedImage, int, int)
*/
public final void renderFrame(BufferedImage sourceImage,
int horizontalOffset, int verticalOffset) {
this.currentSourceImage = sourceImage;
this.currentHorizontalOffset = horizontalOffset;
this.currentVerticalOffset = verticalOffset;
if (!SwingUtilities.isEventDispatchThread()) {
try {
SwingUtilities.invokeAndWait(this);
} catch (Exception exception) {
// Oops..
}
} else {
run();
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Runnable#run()
*/
public final void run() {
if (SwingUtilities.isEventDispatchThread()
&& this.destinationGraphics != null
&& this.currentSourceImage != null) {
this.destinationGraphics.clearRect(0, 0, Integer.MAX_VALUE,
Integer.MAX_VALUE);
this.destinationGraphics.drawImage(this.currentSourceImage,
this.currentHorizontalOffset,
this.currentVerticalOffset,
this.currentBackgroundColor, null);
}
}
private BufferedImage currentSourceImage = null;
private int currentHorizontalOffset = 0;
private int currentVerticalOffset = 0;
private final Graphics2D destinationGraphics;
private final Color currentBackgroundColor;
}
My first questions are:
1/ Is my handling of the call to drawImage() appropriate or are the
"Swing related" precautions irrelevant (i.e. I should not care about
the EDT at this point) ?
2/ How can I retrieve the dimensions of my Graphics2D in order to avoid
having to call clearRect() on the largest possible values (no laughing
please ;-) ), should I pass them to my constructor (since I will
probably have access to the dimensions when retrieving/creating the
graphics) ?
Now for the weird part (at least from my point of view).
I have writtent the following JUnit TestCase to see how the background was handled:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import junit.framework.TestCase;
import GraphicsImageRenderer;
public class GraphicsImageRendererTest extends TestCase {
public static void main(String[] args) {
junit.swingui.TestRunner
.main(new String[] { "GraphicsImageRendererTest" });
}
public GraphicsImageRendererTest(String name) {
super(name);
}
public void testBackgroundColor_colorImagesCustomColor() {
try {
BufferedImage testDestinationImage = new BufferedImage(10, 10,
BufferedImage.TYPE_3BYTE_BGR);
Graphics2D testDestinationGraphics = testDestinationImage
.createGraphics();
BufferedImage testSourceImage = new BufferedImage(1, 1,
BufferedImage.TYPE_3BYTE_BGR);
Color customColor = new Color(10, 20, 30);
GraphicsImageRenderer testCustomColorRenderer = new
GraphicsImageRenderer(
testDestinationGraphics, customColor);
testCustomColorRenderer.renderFrame(testSourceImage, 0, 0);
assertEquals(customColor.getRed(), testDestinationImage.getData()
.getSample(9, 9, 0));
assertEquals(customColor.getGreen(), testDestinationImage.getData()
.getSample(9, 9, 1));
assertEquals(customColor.getBlue(), testDestinationImage.getData()
.getSample(9, 9, 2));
} catch (Exception exception) {
fail("Exception: " + exception);
}
}
public void testBackgroundColor_grayScaleImagesMinimumLuminance() {
try {
BufferedImage testDestinationImage = new BufferedImage(10, 10,
BufferedImage.TYPE_BYTE_GRAY);
Graphics2D testDestinationGraphics = testDestinationImage
.createGraphics();
BufferedImage testSourceImage = new BufferedImage(1, 1,
BufferedImage.TYPE_BYTE_GRAY);
ColorSpace grayColorSpace = ColorSpace
.getInstance(ColorSpace.CS_GRAY);
Color black = new Color(grayColorSpace,
new float[] { grayColorSpace.getMinValue(0) },
1f);
GraphicsImageRenderer testCustomBlackRenderer = new
GraphicsImageRenderer(
testDestinationGraphics, black);
testCustomBlackRenderer.renderFrame(testSourceImage, 0, 0);
assertEquals(0, testDestinationImage.getData().getSample(9, 9, 0));
} catch (Exception exception) {
fail("Exception: " + exception);
}
}
public void testBackgroundColor_grayScaleImagesMaximumLuminance() {
try {
BufferedImage testDestinationImage = new BufferedImage(10, 10,
BufferedImage.TYPE_BYTE_GRAY);
Graphics2D testDestinationGraphics = testDestinationImage
.createGraphics();
BufferedImage testSourceImage = new BufferedImage(1, 1,
BufferedImage.TYPE_BYTE_GRAY);
ColorSpace grayColorSpace = ColorSpace
.getInstance(ColorSpace.CS_GRAY);
Color white = new Color(grayColorSpace,
new float[] { grayColorSpace.getMaxValue(0) },
1f);
GraphicsImageRenderer testCustomWhiteRenderer = new
GraphicsImageRenderer(
testDestinationGraphics, white);
testCustomWhiteRenderer.renderFrame(testSourceImage, 0, 0);
assertEquals(255, testDestinationImage.getData().getSample(9, 9, 0));
} catch (Exception exception) {
fail("Exception: " + exception);
}
}
}
The first two tests pass smoothly but for the last one I get a failure on the "white color" test:
junit.framework.AssertionFailedError: expected:<255> but was:<252>
Why are the luminance values only covering the [0..252] range ?
Any extra comment on what I am doing wrong (Java2D, Code conventions, OO, design...) is more that welcome.
Yours,
D.
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".
- [JAVA2D] Graphics and Grayscale Images - Maximum luninance ... Java Questions
- [JAVA2D] Graphics and Grayscale Images - Maximum lunin... Java Questions
- Re: [JAVA2D] Graphics and Grayscale Images - Maxim... Jerry Evans
- Re: [JAVA2D] Graphics and Grayscale Images - M... Java Questions
