/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* 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
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.catalog.transformer;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiFunction;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.vividsolutions.jts.io.ParseException;
import ddf.catalog.data.BinaryContent;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.impl.MetacardImpl;
import ddf.catalog.transform.CatalogTransformerException;
public class OverlayMetacardTransformerTest {
private OverlayMetacardTransformer transformer;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before
public void setUp() {
final BiFunction<Metacard, Map<String, Serializable>, Optional<BufferedImage>> supplier =
(metacard, arguments) -> {
try (final InputStream inputStream = getClass().getClassLoader()
.getResourceAsStream("flower.jpg")) {
return Optional.ofNullable(ImageIO.read(inputStream));
} catch (IOException e) {
return Optional.empty();
}
};
transformer = new OverlayMetacardTransformer(supplier);
}
private MetacardImpl getMetacard() {
final MetacardImpl metacard = new MetacardImpl();
metacard.setLocation("POLYGON ((0 0, 1 0, 1 -0.1, 0 -0.1, 0 0))");
return metacard;
}
@Test
public void testOverlaySquishedHeight() throws Exception {
final MetacardImpl metacard = getMetacard();
metacard.setLocation("POLYGON ((0 0, 1 0, 1 -0.1, 0 -0.1, 0 0))");
final BinaryContent content = transform(metacard, null);
final BufferedImage originalImage = getImage(getImageBytes());
final BufferedImage overlayImage = getImage(content.getByteArray());
assertThat(overlayImage.getWidth(), equalTo(originalImage.getWidth()));
assertThat(overlayImage.getHeight(), lessThan(originalImage.getHeight()));
}
@Test
public void testOverlayRotated() throws Exception {
final MetacardImpl metacard = getMetacard();
metacard.setLocation("POLYGON ((0 1, 1 0, 0 -1, -1 0, 0 1))");
final BinaryContent content = transform(metacard, null);
final BufferedImage originalImage = getImage(getImageBytes());
final BufferedImage overlayImage = getImage(content.getByteArray());
// We can only make these assertions because we are rotating a square image
assertThat(overlayImage.getWidth(), greaterThan(originalImage.getHeight()));
assertThat(overlayImage.getHeight(), greaterThan(originalImage.getHeight()));
}
@Test(expected = CatalogTransformerException.class)
public void testNoImageFromSupplier() throws Exception {
final BiFunction<Metacard, Map<String, Serializable>, Optional<BufferedImage>>
imageSupplier = (metacard, arguments) -> Optional.empty();
transformer = new OverlayMetacardTransformer(imageSupplier);
transform(getMetacard(), null);
}
private BufferedImage getImage(byte[] imageBytes) throws IOException {
try (final ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes)) {
final ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream);
return ImageIO.read(imageInputStream);
}
}
private byte[] getImageBytes() throws IOException {
try (final InputStream inputStream = getClass().getClassLoader()
.getResourceAsStream("flower.jpg")) {
return IOUtils.toByteArray(inputStream);
}
}
private BinaryContent transform(Metacard metacard, Map<String, Serializable> arguments)
throws CatalogTransformerException, IOException {
final BinaryContent content = transformer.transform(metacard, arguments);
verifyImageIsPng(content.getByteArray());
return content;
}
private void verifyImageIsPng(byte[] imageBytes) {
// Check the PNG header bytes.
assertThat(imageBytes[0], is((byte) 0x89));
assertThat(imageBytes[1], is((byte) 0x50));
assertThat(imageBytes[2], is((byte) 0x4E));
assertThat(imageBytes[3], is((byte) 0x47));
assertThat(imageBytes[4], is((byte) 0x0D));
assertThat(imageBytes[5], is((byte) 0x0A));
assertThat(imageBytes[6], is((byte) 0x1A));
assertThat(imageBytes[7], is((byte) 0x0A));
}
@Test(expected = CatalogTransformerException.class)
public void testNoLocation() throws Exception {
final MetacardImpl metacard = getMetacard();
metacard.setLocation(null);
transform(metacard, null);
}
@Test
public void testInvalidWkt() throws Exception {
final MetacardImpl metacard = getMetacard();
metacard.setLocation("INVALID WKT");
expectedException.expect(CatalogTransformerException.class);
expectedException.expectCause(isA(ParseException.class));
transform(metacard, null);
}
@Test(expected = CatalogTransformerException.class)
public void testCannotHandleGeometry() throws Exception {
final MetacardImpl metacard = getMetacard();
metacard.setLocation("LINESTRING (30 10, 10 30, 40 40)");
transform(metacard, null);
}
@Test(expected = IllegalArgumentException.class)
public void testNullImageSupplier() {
new OverlayMetacardTransformer(null);
}
}