/* * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package boofcv.struct.image; import boofcv.core.image.FactoryGImageGray; import boofcv.core.image.GImageGray; import boofcv.core.image.GeneralizedImageOps; import org.junit.Test; import java.io.*; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Random; import static org.junit.Assert.*; /** * Standard tests for children of {@link ImageGray}. Ensures that they contain * all the expected functions and that they have the expected behavior. This is done * through extensive use of reflections. * * @author Peter Abeles */ public abstract class StandardSingleBandTests<T extends ImageGray> { public Random rand = new Random(234); public abstract T createImage(int width, int height); public abstract T createImage(); public abstract Number randomNumber(); /** * Sets each element in the image to a random value. */ public void setRandom(T img) { Object data = img._getData(); int N = Array.getLength(data); for (int i = 0; i < N; i++) { Array.set(data, i, randomNumber()); } } /** * Check for a positive case of get() and set() */ @Test public void get_set() { T img = createImage(10, 20); setRandom(img); Number expected = randomNumber(); Number orig = (Number) call(img, "get", 0, null, 1, 1); // make sure the two are not equal assertFalse(expected.equals(orig)); // set the expected to the point in the image call(img, "set", 1, expected, 1, 1); Number found = (Number) call(img, "get", 0, null, 1, 1); if (!img.getDataType().isInteger()) assertEquals(expected.doubleValue(), found.doubleValue(), 1e-4); else { if( img.getDataType().isSigned() ) assertTrue(expected.intValue() == found.intValue()); else assertTrue((expected.intValue() & 0xFFFF) == found.intValue()); } } /** * Check for a positive case of get() and set() */ @Test public void unsafe_get_set() { T img = createImage(10, 20); setRandom(img); Number expected = randomNumber(); Number orig = (Number) call(img, "unsafe_get", 0, null, 1, 1); // make sure the two are not equal assertFalse(expected.equals(orig)); // set the expected to the point in the image call(img, "unsafe_set", 1, expected, 1, 1); Number found = (Number) call(img, "unsafe_get", 0, null, 1, 1); if (!img.getDataType().isInteger()) assertEquals(expected.doubleValue(), found.doubleValue(), 1e-4); else { if( img.getDataType().isSigned() ) assertTrue(expected.intValue() == found.intValue()); else assertTrue((expected.intValue() & 0xFFFF) == found.intValue()); } } /** * Makes sure all the accessors do proper bounds checking */ @Test public void accessorBounds() { ImageGray img = createImage(10, 20); checkBound(img, "get", 0, null); checkBound(img, "set", 1, randomNumber()); } private void checkBound(ImageGray img, String method, int type, Object typeData) { checkException(img, method, type, typeData, -1, 0); checkException(img, method, type, typeData, 0, -1); checkException(img, method, type, typeData, img.getWidth(), 0); checkException(img, method, type, typeData, 0, img.getHeight()); } private void checkException(ImageGray img, String method, int type, Object typeData, int... where) { boolean found = false; try { call(img, method, type, typeData, where); } catch (ImageAccessException e) { found = true; } assertTrue("No exception was thrown", found); } private Object call(ImageGray img, String method, int type, Object typeData, int... where) { try { Class<?>[] paramTypes = type == 0 ? new Class<?>[where.length] : new Class<?>[where.length + 1]; Object[] args = new Object[paramTypes.length]; int index; for (index = 0; index < where.length; index++) { paramTypes[index] = int.class; args[index] = where[index]; } if (type == 1) { paramTypes[index] = img.getDataType().getSumType(); args[index] = typeData; } else if (type == 2) { String name = "[" + img.getDataType().getDataType().getName().toUpperCase().charAt(0); paramTypes[index] = Class.forName(name); args[index] = typeData; } Method m = img.getClass().getMethod(method, paramTypes); return m.invoke(img, args); } catch (ClassNotFoundException | IllegalAccessException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { fail("The method " + method + " needs to be implemented"); } catch (InvocationTargetException e) { throw (RuntimeException) e.getCause(); } throw new RuntimeException("Shouldn't be here"); } @Test public void subimage() { T img = createImage(10, 20); setRandom(img); T sub = (T)img.subimage(2,3,3,5, null); assertTrue(img.getImageType() == sub.getImageType()); assertEquals(1, sub.getWidth()); assertEquals(2, sub.getHeight()); GImageGray a = FactoryGImageGray.wrap(img); GImageGray b = FactoryGImageGray.wrap(sub); assertEquals(a.get(2, 3), b.get(0, 0)); assertEquals(a.get(2, 4), b.get(0, 1)); } @Test public void reshape() { ImageGray img = createImage(10, 20); // reshape to something smaller img.reshape(5,4); assertEquals(5, img.getWidth()); assertEquals(4, img.getHeight()); // reshape to something larger img.reshape(15,21); assertEquals(15, img.getWidth()); assertEquals(21, img.getHeight()); } @Test public void serialize() throws IOException, ClassNotFoundException { // randomly fill the image ImageGray imgA = createImage(10, 20); GImageGray a = FactoryGImageGray.wrap(imgA); for (int i = 0; i < imgA.getHeight(); i++) { for (int j = 0; j < imgA.getWidth(); j++) { a.set(j,i,rand.nextDouble()*200); } } // make a copy of the original ImageGray imgB = (ImageGray)imgA.clone(); ByteArrayOutputStream streamOut = new ByteArrayOutputStream(1000); ObjectOutputStream out = new ObjectOutputStream(streamOut); out.writeObject(imgA); out.close(); ByteArrayInputStream streamIn = new ByteArrayInputStream(streamOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(streamIn); ImageGray found = (ImageGray)in.readObject(); // see if everything is equals checkEquals(imgA, imgB); checkEquals(imgA, found); } private void checkEquals(ImageGray imgA, ImageGray imgB) { for (int i = 0; i < imgA.getHeight(); i++) { for (int j = 0; j < imgA.getWidth(); j++) { double valA = GeneralizedImageOps.get(imgA, j, i); double valB = GeneralizedImageOps.get(imgB, j, i); assertEquals(valA, valB, 1e-8); } } } @Test public void checkNoArgumentConstructor() { ImageGray a = createImage(); assertTrue(a._getData() == null); assertTrue(a.getImageType() != null); } }