EMMA Coverage Report (generated Sun Apr 20 22:38:01 CEST 2008)
[all classes][net.sf.jomic.jaiunit]

COVERAGE SUMMARY FOR SOURCE FILE [Tools.java]

nameclass, %method, %block, %line, %
Tools.java100% (1/1)71%  (10/14)92%  (853/929)93%  (132.1/142)

COVERAGE BREAKDOWN BY CLASS AND METHOD

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

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