Files
2026-06-17 14:00:51 +02:00

325 lines
11 KiB
Java

package jmri.jmrit.catalog;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.PixelGrabber;
import javax.swing.JLabel;
import jmri.util.JUnitAppender;
import jmri.util.JUnitUtil;
import org.junit.jupiter.api.*;
import org.junit.Assert;
/**
*
* @author Paul Bender Copyright (C) 2017
* @author Joe Comuzzi Copyright (C) 2018
*/
public class NamedIconTest {
/**
* Test constructor for NamedIcon
*/
@Test
public void testCTor() {
NamedIcon t = new NamedIcon("program:resources/logo.gif","logo");
Assert.assertNotNull("exists",t);
}
/**
* Test bad prefix on file name
*/
@Test
public void testBadPrefix() {
NamedIcon t = new NamedIcon("foof:biff.gif","logo");
JUnitAppender.assertErrorMessageStartsWith("Did not find \"foof:biff.gif\" for NamedIcon");
JUnitAppender.assertWarnMessage("Could not load image from foof:biff.gif (file does not exist)");
JUnitAppender.assertWarnMessage("NamedIcon can't scan foof:biff.gif for animated status");
Assert.assertNotNull("exists",t);
}
/**
* Test no file at prefixed URL
*/
@Test
public void testNoFileBehindPrefix() {
NamedIcon t = new NamedIcon("program:resources/foo/foo/foo/foo.gif","logo");
JUnitAppender.assertErrorMessageStartsWith("Did not find \"program:resources/foo/foo/foo/foo.gif\" for NamedIcon");
JUnitAppender.assertWarnMessage("Could not load image from program:resources/foo/foo/foo/foo.gif (file does not exist)");
JUnitAppender.assertWarnMessage("NamedIcon can't scan program:resources/foo/foo/foo/foo.gif for animated status");
Assert.assertNotNull("exists",t);
}
/**
* Test no file at relative URL
*/
@Test
public void testNoFileRelative() {
NamedIcon t = new NamedIcon("resources/foo/foo/foo/foo.gif","logo");
JUnitAppender.assertErrorMessageStartsWith("Did not find \"resources/foo/foo/foo/foo.gif\" for NamedIcon");
JUnitAppender.assertWarnMessage("Could not load image from resources/foo/foo/foo/foo.gif (file does not exist)");
JUnitAppender.assertWarnMessage("NamedIcon can't scan resources/foo/foo/foo/foo.gif for animated status");
Assert.assertNotNull("exists",t);
}
/**
* Test transformImage. Confirm that resize Affine Transform doesn't affects size.
* The size comes from the width and height parameters
*/
@Test
public void testTransformImage() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
AffineTransform t = AffineTransform.getScaleInstance(0.5, 0.5);
ni.transformImage(w/2, h, t, null);
Assert.assertEquals(w/2, ni.getIconWidth());
Assert.assertEquals(h, ni.getIconHeight());
}
/**
* Test rotate method with no scaling, 45 deg rotation. The size
* should change.
*/
@Test
public void testRotateNoScaling() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
ni.rotate(45, new JLabel());
int rectSize = (int) Math.ceil((h + w)/Math.sqrt(2.));
Assert.assertEquals(rectSize, ni.getIconHeight());
Assert.assertEquals(rectSize, ni.getIconWidth());
}
/**
* Test scaling, no rotation
*/
@Test
public void testScaling() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
double scale = 1.2;
ni.scale(scale, new JLabel());
Assert.assertEquals((int) (h * scale), ni.getIconHeight());
Assert.assertEquals((int) (w * scale), ni.getIconWidth());
}
/**
* Test rotate method with scaling, 270 degrees
* should just swap height and width and we'll scale by 2.0
*/
@Test
public void testRotate270() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
JLabel comp = new JLabel();
double scale = 2.0;
ni.scale(scale, comp);
ni.rotate(270, comp);
// The +1 in the below is a bit of a crock, but it's because the argument of
// Math.ceil(Math.abs(w*Math.cos(rad))) is slightly more than zero, so it
// rounds up!
Assert.assertEquals((int) Math.ceil(w * scale) + 1, ni.getIconHeight());
Assert.assertEquals((int) Math.ceil(h * scale) + 1, ni.getIconWidth());
}
/**
* Test setLoad and scale. 30 degrees is also simple geometry.
* Also test getDegrees and getScale while we're here
*/
@Test
public void testSetLoad()
{
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
JLabel comp = new JLabel();
double scale = 0.333;
int degrees = 30;
ni.setLoad(degrees, scale, comp);
Assert.assertEquals(ni.getDegrees(), degrees);
Assert.assertEquals(ni.getScale(), scale, .001);
// Be wary of numerical instability in these tests. e.g. because of rounding in NamedIcon, sometimes
// cos(30) is not exactly 0.5 and the ceil operation gives different answers!
double sqrt3 = Math.sqrt(3);
int expectedHeight = (int) (Math.ceil(h * sqrt3 * scale / 2.0 + w * scale / 2.0));
Assert.assertEquals(expectedHeight, ni.getIconHeight());
int expectedWidth = (int) (Math.ceil(h * scale / 2.0 + w * sqrt3 * scale / 2.0));
Assert.assertEquals(expectedWidth, ni.getIconWidth());
}
/**
* Test reduceTo method.
*
*/
@Test
public void testReduceTo() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
// Test that limit of one won't let you reduce the size.
ni.reduceTo(10, 10, 1.0);
Assert.assertEquals(h, ni.getIconHeight());
Assert.assertEquals(w, ni.getIconWidth());
// Test that we can reduce the size
ni.reduceTo(w / 3, h / 2, 0.1);
Assert.assertEquals(w / 3, ni.getIconWidth());
Assert.assertEquals(h / 3, ni.getIconHeight());
}
/**
* Test flip method
*/
@Test
public void testFlip() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
JLabel comp = new JLabel();
ni.flip(NamedIcon.NOFLIP, comp);
Assert.assertEquals(w, ni.getIconWidth());
Assert.assertEquals(h, ni.getIconHeight());
int [] noflipPixels = getPixels(ni.getImage());
ni.flip(NamedIcon.VERTICALFLIP, comp);
Assert.assertEquals(w, ni.getIconWidth());
Assert.assertEquals(h, ni.getIconHeight());
int [] flipPixels = getPixels(ni.getImage());
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
Assert.assertEquals(noflipPixels[j * w + i], flipPixels[(h - 1 - j) * w + i]);
}
}
}
/**
* Test createRotatedImage. N.B, createRotatedImage forces the color
* model, so we can't easily compare to the original image. Instead,
* we compare the image rotated by 90 deg to the image rotated by 180 deg,
*/
@Test
public void testCreateRotatedImage() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
JLabel comp = new JLabel();
Image img = ni.getImage();
Image rot1Image = ni.createRotatedImage(img, comp, 1);
Assert.assertEquals(w, rot1Image.getHeight(null));
Assert.assertEquals(h, rot1Image.getWidth(null));
int [] rot1Pixels = getPixels(rot1Image);
Image rot2Image = ni.createRotatedImage(img, comp, 2);
Assert.assertEquals(h, rot2Image.getHeight(null));
Assert.assertEquals(w, rot2Image.getWidth(null));
int [] rot2Pixels = getPixels(rot2Image);
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
Assert.assertEquals(rot1Pixels[j * h + i], rot2Pixels[(h - 1 - i) * w + j]);
}
}
}
/**
* Test setRotation and getRotation. Since this calls createRotatedImage, we compare
* the image rotated by 90 deg to the image rotated by 270 deg.
*/
@Test
public void testSetRotation() {
NamedIcon ni = new NamedIcon("program:resources/logo.gif","logo");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
JLabel comp = new JLabel();
Assert.assertEquals(0, ni.getRotation());
ni.setRotation(1, comp);
Assert.assertEquals(h, ni.getIconWidth());
Assert.assertEquals(w, ni.getIconHeight());
Assert.assertEquals(1, ni.getRotation());
int [] rot1Pixels = getPixels(ni.getImage());
ni.setRotation(3, comp);
Assert.assertEquals(h, ni.getIconWidth());
Assert.assertEquals(w, ni.getIconHeight());
Assert.assertEquals(3, ni.getRotation());
int [] rot3Pixels = getPixels(ni.getImage());
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
Assert.assertEquals(rot1Pixels[j * w + i], rot3Pixels[(h - j) * w - 1 - i]);
}
}
}
/**
* Test rotate and scale with blinking GIF. This will use the animated GIF codepath.
*/
@Test
public void testAnimatedGif() {
NamedIcon ni = new NamedIcon("program:resources/icons/largeschematics/aspects/CSD-1962/003_o40_p.gif", "blink");
int h = ni.getIconHeight();
int w = ni.getIconWidth();
JLabel comp = new JLabel();
double scale = 2.0;
ni.scale(scale, comp);
ni.rotate(270, comp);
// The +1 in the below is a bit of a crock, but it's because the argument of
// Math.ceil(Math.abs(w*Math.cos(rad))) is slightly more than zero, so it
// rounds up!
Assert.assertEquals((int) Math.ceil(w * scale) + 1, ni.getIconHeight());
Assert.assertEquals((int) Math.ceil(h * scale), ni.getIconWidth());
}
/**
* Helper routine to grab the pixels from an Image
* @param img Image to get pixels from
* @return array of ints, one for each pixel
*/
private int [] getPixels(Image img) {
int w = img.getWidth(null);
int h = img.getHeight(null);
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pixels, 0, w);
try {
pg.grabPixels();
} catch (InterruptedException ie) {
}
return pixels;
}
@BeforeEach
public void setUp() {
JUnitUtil.setUp();
}
@AfterEach
public void tearDown() {
JUnitUtil.tearDown();
}
// private static final Logger log = LoggerFactory.getLogger(NamedIconTest.class);
}