/* * integration.ImporterTest * *------------------------------------------------------------------------------ * Copyright (C) 2006-2010 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package integration; import static org.testng.AssertJUnit.fail; import java.awt.image.BufferedImage; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.imageio.ImageIO; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; import omero.model.Pixels; import omero.model.StatsInfo; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * Collection of tests to import "big" images and check min/max values. * * @author Colin Blackburn      <a * href="mailto:c.blackburn@dundee.ac.uk">c.blackburn@dundee.ac.uk</a> * * These tests use a simple single plane image. * * These tests depend on PNG being imported using fs-lite and having a * pyramid file created. If that changes then it will be necessary to * change the import. */ public class PyramidMinMaxTest extends AbstractServerTest { /** The format tested here. */ private static final String FORMAT = "png"; /* Total wait time will be WAITS * INTERVAL milliseconds */ /** Maximum number of intervals to wait for pyramid **/ private static final int WAITS = 100; /** Wait time in milliseconds **/ private static final long INTERVAL = 100L; /** The collection of files that have to be deleted. */ private List<File> files; /** * Overridden to initialize the list. * * @see AbstractServerTest#setUp() */ @Override @BeforeClass protected void setUp() throws Exception { super.setUp(); files = new ArrayList<File>(); } /** * Overridden to delete the files. * * @see AbstractServerTest#tearDown() */ @Override @AfterClass public void tearDown() throws Exception { Iterator<File> i = files.iterator(); while (i.hasNext()) { i.next().delete(); } files.clear(); } /** * Import a <code>PNG</code> which generates a pyramid files with all * zeroes. * * @throws Exception * Thrown if an error occurred. */ @Test public void testForMinMaxAllZero() throws Exception { // Create a file, the default is all zeroes BufferedImage bi = new BufferedImage(ModelMockFactory.WIDTH, ModelMockFactory.HEIGHT, BufferedImage.TYPE_INT_RGB); File f = createImageFileWithBufferedImage(bi, FORMAT); files.add(f); Pixels p = importAndWaitForPyramid(f, FORMAT); assertMinMaxOnAllChannels(p, 0.0, 0.0); } /** * Import a <code>PNG</code> which generates a pyramid files with all * FFFFFF. * * @throws Exception * Thrown if an error occurred. */ @Test public void testForMinMaxAll255() throws Exception { // Create a png file, with all RGB values FFFFFF BufferedImage bi = new BufferedImage(ModelMockFactory.WIDTH, ModelMockFactory.HEIGHT, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < ModelMockFactory.WIDTH; x++) { for (int y = 0; y < ModelMockFactory.HEIGHT; y++) { bi.setRGB(x, y, Integer.valueOf("FFFFFF", 16)); } } File f = createImageFileWithBufferedImage(bi, FORMAT); files.add(f); Pixels p = importAndWaitForPyramid(f, FORMAT); assertMinMaxOnAllChannels(p, 255.0, 255.0); } /** * Import a <code>PNG</code> which generates a pyramid files with some 0 and * some FFFFFF. * * @throws Exception * Thrown if an error occurred. */ @Test public void testForMinMaxHalfZeroAndHalf255() throws Exception { // Create a png file, with half RGB values FFFFFF BufferedImage bi = new BufferedImage(ModelMockFactory.WIDTH, ModelMockFactory.HEIGHT, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < ModelMockFactory.WIDTH; x += 2) { for (int y = 0; y < ModelMockFactory.HEIGHT; y++) { bi.setRGB(x, y, Integer.valueOf("FFFFFF", 16)); } } File f = createImageFileWithBufferedImage(bi, FORMAT); files.add(f); Pixels p = importAndWaitForPyramid(f, FORMAT); assertMinMaxOnAllChannels(p, 0.0, 255.0); } /** * Import a <code>PNG</code> which generates a pyramid files with most 0 and * one FFFFFF. * * @throws Exception * Thrown if an error occurred. */ @Test public void testForMinMaxAllZeroWithFirst255() throws Exception { // Create a png file, with first RGB value FFFFFF BufferedImage bi = new BufferedImage(ModelMockFactory.WIDTH, ModelMockFactory.HEIGHT, BufferedImage.TYPE_INT_RGB); bi.setRGB(0, 0, Integer.valueOf("FFFFFF", 16)); File f = createImageFileWithBufferedImage(bi, FORMAT); files.add(f); Pixels p = importAndWaitForPyramid(f, FORMAT); assertMinMaxOnAllChannels(p, 0.0, 255.0); } /** * Import a <code>PNG</code> which generates a pyramid files with most 0 and * one FFFFFF. * * @throws Exception * Thrown if an error occurred. */ @Test public void testForMinMaxAllZeroWithLast255() throws Exception { // Create a png file, with last RGB value FFFFFF BufferedImage bi = new BufferedImage(ModelMockFactory.WIDTH, ModelMockFactory.HEIGHT, BufferedImage.TYPE_INT_RGB); bi.setRGB(ModelMockFactory.WIDTH - 1, ModelMockFactory.HEIGHT - 1, Integer.valueOf("FFFFFF", 16)); File f = createImageFileWithBufferedImage(bi, FORMAT); files.add(f); Pixels p = importAndWaitForPyramid(f, FORMAT); assertMinMaxOnAllChannels(p, 0.0, 255.0); } /** * Check the min and max on all three channels */ private void assertMinMaxOnAllChannels(Pixels p, double min, double max) { for (int c = 0; c < 3; c++) { assert (p.getChannel(c).getStatsInfo().getGlobalMin().getValue() == min); assert (p.getChannel(c).getStatsInfo().getGlobalMax().getValue() == max); } } /** * Create an image file from a BufferedImage of the given format. */ private File createImageFileWithBufferedImage(BufferedImage bi, String format) throws Exception { File f = File.createTempFile("testImage", "." + format); Iterator writers = ImageIO.getImageWritersByFormatName(format); ImageWriter writer = (ImageWriter) writers.next(); ImageOutputStream ios = ImageIO.createImageOutputStream(f); writer.setOutput(ios); writer.write(bi); ios.close(); return f; } /** * Import an image file of the given format then wait for a pyramid file to * be generated by checking if stats exists. */ private Pixels importAndWaitForPyramid(File f, String format) throws Exception { List<Pixels> pixels = null; try { pixels = importFile(f, FORMAT); } catch (Throwable e) { fail("Cannot import image file: " + f.getAbsolutePath() + " Reason: " + e.toString()); } // Wait for a pyramid to be built (stats will be not null) Pixels p = factory.getPixelsService().retrievePixDescription( pixels.get(0).getId().getValue()); StatsInfo stats = p.getChannel(0).getStatsInfo(); int waits = 0; while (stats == null && waits < WAITS) { Thread.sleep(INTERVAL); waits++; p = factory.getPixelsService().retrievePixDescription( pixels.get(0).getId().getValue()); stats = p.getChannel(0).getStatsInfo(); } if (stats == null) { fail("No pyramid after " + WAITS * INTERVAL / 1000.0 + " seconds"); } return p; } }