EMMA Coverage Report (generated Sat Oct 08 11:41:37 CEST 2011)
[all classes][net.sf.jomic.jaiunit]

COVERAGE SUMMARY FOR SOURCE FILE [Tools.java]

nameclass, %method, %block, %line, %
Tools.java100% (1/1)71%  (10/14)75%  (693/929)85%  (120.1/142)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Tools100% (1/1)71%  (10/14)75%  (693/929)85%  (120.1/142)
createTestImage (int, int): RenderedImage 0%   (0/1)0%   (0/22)0%   (0/3)
createTestImage (int, int, String): RenderedImage 0%   (0/1)0%   (0/7)0%   (0/1)
createTestImage (int, int, String, String): RenderedImage 0%   (0/1)0%   (0/8)0%   (0/1)
jai (): JAI 0%   (0/1)0%   (0/3)0%   (0/1)
getDeltaImage (RenderedImage, RenderedImage): RenderedImage 100% (1/1)49%  (75/152)68%  (17/25)
imagesAreEqual (RenderedImage, RenderedImage): boolean 100% (1/1)57%  (36/63)82%  (9/11)
showImage (RenderedImage, Class, String): void 100% (1/1)65%  (22/34)75%  (4.5/6)
instance (): Tools 100% (1/1)72%  (13/18)91%  (3.6/4)
createTestImage (int, int, int, String, String): RenderedImage 100% (1/1)85%  (398/470)94%  (59/63)
<static initializer> 100% (1/1)94%  (46/49)98%  (2.9/3)
Tools (): void 100% (1/1)100% (11/11)100% (4/4)
drawCenteredText (Graphics2D, String, int, int, int): void 100% (1/1)100% (51/51)100% (10/10)
drawFilledTriangle (Graphics2D, int, int, int, int, int, int): void 100% (1/1)100% (30/30)100% (7/7)
showDeltaImage (RenderedImage, RenderedImage, Class, String): void 100% (1/1)100% (11/11)100% (3/3)

1// Jomic - a viewer for comic book archives.
2// Copyright (C) 2004-2011 Thomas Aglassinger
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <http://www.gnu.org/licenses/>.
16package net.sf.jomic.jaiunit;
17 
18import java.awt.Color;
19import java.awt.Font;
20import java.awt.FontMetrics;
21import java.awt.GradientPaint;
22import java.awt.Graphics2D;
23import java.awt.RenderingHints;
24import java.awt.geom.GeneralPath;
25import java.awt.geom.Path2D;
26import java.awt.geom.Rectangle2D;
27import java.awt.image.BufferedImage;
28import java.awt.image.RenderedImage;
29import java.awt.image.renderable.ParameterBlock;
30 
31import javax.media.jai.Histogram;
32import javax.media.jai.JAI;
33import javax.media.jai.ParameterBlockJAI;
34 
35import net.sf.jomic.tools.StringTools;
36import org.apache.commons.logging.Log;
37import org.apache.commons.logging.LogFactory;
38 
39/**
40 *  Utility methods to implement JAI-related programmer tests based on the JUnit framework.
41 *
42 * @author    Thomas Aglassinger
43 */
44public final class Tools
45{
46    private static final double LABEL_FONT_SIZE_IN_PERCENT = 0.7;
47    private static final Color[] RAINBOW_COLORS = new Color[]{Color.RED, Color.YELLOW,
48            Color.GREEN, Color.CYAN, Color.BLUE};
49    private static final Color[] WHITE_AND_BLACK = new Color[]{Color.WHITE, Color.BLACK};
50 
51    private static Tools instance;
52    private static Log logger;
53 
54    private JAI jai;
55    private StringTools stringTools;
56 
57    private Tools() {
58        jai = new JAI();
59        stringTools = StringTools.instance();
60    }
61 
62    public RenderedImage getDeltaImage(RenderedImage some, RenderedImage other) {
63        assert some != null;
64        assert other != null;
65        RenderedImage result = null;
66 
67        ParameterBlock pbSubtract = new ParameterBlock();
68 
69        pbSubtract.addSource(some);
70        pbSubtract.addSource(other);
71        result = JAI.create("Subtract", pbSubtract);
72        if (logger.isDebugEnabled()) {
73            logger.debug("subtracted image: " + result);
74        }
75 
76        ParameterBlock pbInvert = new ParameterBlock();
77        RenderingHints hints = new RenderingHints(null);
78 
79        pbInvert.addSource(result);
80        hints.put(JAI.KEY_TRANSFORM_ON_COLORMAP, Boolean.FALSE);
81        result = jai.createNS("Invert", pbInvert, hints);
82 
83        ParameterBlockJAI pbHistogram = new ParameterBlockJAI("Histogram");
84 
85        pbHistogram.addSource(result);
86        result = jai.createNS("Histogram", pbHistogram, null);
87 
88        if (logger.isDebugEnabled()) {
89            Histogram histogram = (Histogram) result.getProperty("histogram");
90            double[] highValues = histogram.getHighValue();
91 
92            logger.debug("histogram = " + histogram);
93            logger.debug("highValues = " + stringTools.arrayToString(highValues));
94            logger.debug("lowValues = " + stringTools.arrayToString(histogram.getLowValue()));
95            logger.debug("standardDeviation = " + stringTools.arrayToString(histogram.getStandardDeviation()));
96        }
97 
98        return result;
99    }
100 
101    public static synchronized Tools instance() {
102        if (instance == null) {
103            logger = LogFactory.getLog(Tools.class);
104            instance = new Tools();
105        }
106        return instance;
107    }
108 
109    public RenderedImage createTestImage(int width, int height) {
110        assert width > 0;
111        assert height > 0;
112        return createTestImage(width, height, null);
113    }
114 
115    public RenderedImage createTestImage(int width, int height, String labelText) {
116        return createTestImage(width, height, labelText, null);
117    }
118 
119    public RenderedImage createTestImage(int width, int height, String labelText, String details) {
120        return createTestImage(width, height, BufferedImage.TYPE_BYTE_GRAY, labelText, details);
121    }
122 
123    public RenderedImage createTestImage(int width, int height, int imageType, String labelText,
124            String details) {
125        // TODO: do something useful about small width or height
126        assert width > 0;
127        assert height > 0;
128        int lastX = width - 1;
129        int lastY = height - 1;
130        int triangleWidth = Math.max(5, Math.min(width, height) / 25);
131        int triangleHeight = (int) (Math.sqrt(0.75) * triangleWidth);
132        int halfWidth = width / 2;
133        int halfHeight = height / 2;
134        BufferedImage result = new BufferedImage(width, height, imageType);
135        Graphics2D g = result.createGraphics();
136        Rectangle2D textBox;
137 
138        g.setColor(Color.WHITE);
139        g.fillRect(0, 0, width, height);
140 
141        if (labelText != null) {
142            int fontHeight = Math.min(10, g.getFontMetrics().getHeight());
143            Font newFont = new Font("Dialog", Font.PLAIN, fontHeight);
144            Font labelFont;
145 
146            do {
147                labelFont = newFont;
148                fontHeight = (int) (1.1 * fontHeight);
149                newFont = newFont.deriveFont((float) fontHeight);
150                textBox = newFont.getStringBounds(labelText, g.getFontRenderContext());
151                // TODO: add support for jomic-logging-test.properties, and
152//                if (logger.isDebugEnabled()) {
153//                     comment this in
154//                                        logger.debug("try font: fontHeight=" +
155//                     labelFont.getSize()
156//                                                + ", boxWidth=" + textBox.getWidth()
157//                                                + ", boxHeight=" + textBox.getHeight());
158//                }
159            } while ((textBox.getWidth() < width * LABEL_FONT_SIZE_IN_PERCENT)
160                    && (textBox.getHeight() < height * LABEL_FONT_SIZE_IN_PERCENT));
161            g.setColor(Color.LIGHT_GRAY);
162            g.setFont(labelFont);
163            textBox = labelFont.getStringBounds(labelText, g.getFontRenderContext());
164 
165            int labelLeftX = (int) (width - textBox.getWidth()) / 2;
166            int labelTopY = (int) (height - textBox.getHeight()) / 2
167                    + g.getFontMetrics().getAscent();
168 
169            if (logger.isDebugEnabled()) {
170                logger.debug("label: font=" + labelFont + ", x=" + labelLeftX + ", y=" + labelTopY);
171            }
172            g.drawString(labelText, labelLeftX, labelTopY);
173        }
174 
175        // draw X
176        g.setColor(Color.BLACK);
177        g.drawLine(0, 0, lastX, lastY);
178        g.drawLine(0, lastY, lastX, 0);
179 
180        // draw triangles
181        drawFilledTriangle(g, halfWidth, 0, halfWidth - triangleHeight, triangleHeight, halfWidth
182                + triangleHeight, triangleHeight);
183        drawFilledTriangle(g, halfWidth, lastY, halfWidth - triangleHeight, lastY - triangleHeight,
184                halfWidth + triangleHeight, lastY - triangleHeight);
185        drawFilledTriangle(g, 0, halfHeight, triangleHeight, halfHeight - triangleHeight,
186                triangleHeight, halfHeight + triangleHeight);
187        drawFilledTriangle(g, lastX, halfHeight, lastX - triangleHeight, halfHeight
188                - triangleHeight, lastX - triangleHeight, halfHeight + triangleHeight);
189 
190        // print image dimension
191        drawCenteredText(g, "" + width + "x" + height, halfWidth, 1 * height / 8, 2 * triangleWidth);
192 
193        // draw rainbow gradient
194        Color[] colors;
195 
196        if ((imageType == BufferedImage.TYPE_BYTE_GRAY)
197                || (imageType == BufferedImage.TYPE_USHORT_GRAY)) {
198            colors = WHITE_AND_BLACK;
199        } else {
200            colors = RAINBOW_COLORS;
201        }
202 
203        int colorCount = colors.length;
204        int rainbowWidth = width / 8;
205        int rainbowHeight = height / 16;
206        int rainbowCenterX = width / 2;
207        int rainbowCenterY = 6 * height / 8;
208        int rainbowStartX = rainbowCenterX - rainbowWidth / 2;
209        int rainbowStartY = rainbowCenterY - rainbowHeight / 2;
210 
211        if ((rainbowWidth >= 2 * colorCount) && (rainbowHeight > 1)) {
212            if (logger.isDebugEnabled()) {
213                logger.debug("draw rainbow from (" + rainbowStartX + ", " + rainbowStartY
214                        + ") with width=" + rainbowWidth + " and height=" + rainbowHeight);
215            }
216            for (int i = 0; i < colorCount - 1; i += 1) {
217                Color startColor = colors[i];
218                Color endColor = colors[i + 1];
219                int startX = (rainbowStartX + i * rainbowWidth / (colorCount - 1));
220                int endX = (rainbowStartX + (i + 1) * rainbowWidth / (colorCount - 1));
221                GradientPaint paint = new GradientPaint(startX, 0, startColor, endX, 0, endColor);
222 
223                g.setPaint(paint);
224                if (logger.isDebugEnabled()) {
225                    logger.debug("draw rainbow element from (" + startX + ", " + rainbowStartY
226                            + ") with width=" + (endX - startX) + " and height=" + rainbowHeight);
227                }
228                g.fill(new Rectangle2D.Double(startX, rainbowStartY, endX - startX, rainbowHeight));
229            }
230        }
231 
232        // print details
233        if (details != null) {
234            g.setColor(Color.BLACK);
235            drawCenteredText(g, details, width / 2, 7 * height / 8, triangleHeight);
236        }
237 
238        return result;
239    }
240 
241    public boolean imagesAreEqual(RenderedImage some, RenderedImage other) {
242        boolean result = true;
243        RenderedImage deltaImage = getDeltaImage(some, other);
244        Histogram histogram = (Histogram) deltaImage.getProperty("histogram");
245        double[] deviations = histogram.getStandardDeviation();
246 
247        if (logger.isDebugEnabled()) {
248            logger.debug("deviations = " + stringTools.arrayToString(deviations));
249            logger.debug("totals = " + stringTools.arrayToString(histogram.getTotals()));
250        }
251        for (int i = 0; i < deviations.length; i += 1) {
252            if (deviations[i] > 0) {
253                result = false;
254            }
255        }
256        return result;
257    }
258 
259    public JAI jai() {
260        return jai;
261    }
262 
263    public void showDeltaImage(RenderedImage some, RenderedImage other, Class clazz, String id) {
264        ImageComparisonViewer frame = new ImageComparisonViewer(some, other, clazz, id);
265 
266        frame.showImages();
267    }
268 
269    /**
270     *  Show image.
271     *
272     * @param  creator  the class that created the image
273     * @param  id       an unique ID (within the creator class) to identify the test image
274     */
275    public void showImage(RenderedImage image, Class creator, String id) {
276        assert image != null;
277        assert creator != null;
278        assert id != null;
279        ImageViewer frame = new ImageViewer(image, creator, id);
280 
281        frame.showImage();
282    }
283 
284    private void drawCenteredText(Graphics2D g, String text, int x, int y, int fontSize) {
285        Font font = new Font("Dialog", Font.BOLD, fontSize);
286 
287        g.setFont(font);
288 
289        FontMetrics metrics = g.getFontMetrics();
290        Rectangle2D textBox = metrics.getStringBounds(text, g);
291        double textWidth = textBox.getWidth();
292        int textX = (int) (x - textWidth / 2);
293        double textHeight = textBox.getHeight();
294        int textY = (int) (y - textHeight / 2 + g.getFontMetrics().getAscent());
295 
296        g.drawString(text, textX, textY);
297 
298    }
299 
300    private void drawFilledTriangle(Graphics2D g, int x1, int y1, int x2, int y2, int x3, int y3) {
301        GeneralPath filledPolygon = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
302 
303        filledPolygon.moveTo(x1, y1);
304        filledPolygon.lineTo(x2, y2);
305        filledPolygon.lineTo(x3, y3);
306        filledPolygon.closePath();
307        g.fill(filledPolygon);
308    }
309}

[all classes][net.sf.jomic.jaiunit]
EMMA 2.0.4217 (C) Vladimir Roubtsov