/** * Copyright (C) 2011 JTalks.org Team * This library 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 2.1 of the License, or (at your option) any later version. * This library 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. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jtalks.jcommune.service.nontransactional; import net.sf.image4j.codec.ico.ICODecoder; import net.sf.image4j.codec.ico.ICOEncoder; import org.apache.commons.codec.binary.Base64; import org.jtalks.jcommune.service.exceptions.ImageProcessException; import org.springframework.mock.web.MockMultipartFile; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import static org.mockito.MockitoAnnotations.initMocks; import static org.testng.Assert.assertEquals; /** * @author Eugeny Batov * @author Alexandre Teterin */ public class ImageConverterTest { private static final int DEFAULT_MAX_WIDTH = 100; private static final int DEFAULT_MAX_HEIGHT = 100; private static final int ICON_MAX_WIDTH = 32; private static final int ICON_MAX_HEIGHT = 32; private ImageConverter imageConverter; private byte[] byteArray = new byte[]{1, 2, 3}; @BeforeClass public void init() throws IOException { initMocks(this); imageConverter = new ImageConverter("jpeg", BufferedImage.TYPE_INT_RGB, DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT); } @Test(expectedExceptions = {IllegalArgumentException.class}) public void convertImageToByteArrayShouldNotWorkWithPassedNull() throws ImageProcessException { imageConverter.convertImageToByteArray(null); } @Test(dataProvider = "parameterResizeImage") public void testResizeImage(int maxWidth, int maxHeight, int imageType, String format) throws IOException { int expectedWidth = 4; int expectedHeight = 4; imageConverter = new ImageConverter(format, imageType, maxWidth, maxHeight); BufferedImage originalImage = ImageIO.read(new MockMultipartFile("test_image", "test_image", "image/png", originalImageByteArray).getInputStream()); Image modifiedImage = imageConverter.resizeImage(originalImage, imageType); assertEquals(modifiedImage.getWidth(null), expectedWidth); assertEquals(modifiedImage.getHeight(null), expectedHeight); } @DataProvider(name = "parameterResizeImage") public Object[][] parameterResizeImage() { int widthWithAspectRatioOne = 4; int heightWithAspectRatioOne = 4; int widthWithAspectRationMoreThatOne = 5; int heightWithAspectRatioMoreThatOne = 4; return new Object[][]{ {widthWithAspectRatioOne, heightWithAspectRatioOne, BufferedImage.TYPE_INT_RGB, "jpeg"}, {widthWithAspectRationMoreThatOne, heightWithAspectRatioMoreThatOne, BufferedImage.TYPE_INT_ARGB, "png"} }; } @Test public void testPrepareHtmlImgSrc() { String source = "QUFBQUJBQ0FB"; Base64Wrapper base64Wrapper = new Base64Wrapper(); byte[] sourceBytes = base64Wrapper.decodeB64Bytes(source); String actual = imageConverter.prepareHtmlImgSrc(sourceBytes); assertEquals(actual, source); } private byte[] originalImageByteArray = new byte[]{-119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 5, 0, 0, 0, 5, 8, 2, 0, 0, 0, 2, 13, -79, -78, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 1, -118, 0, 0, 1, -118, 1, 51, -105, 48, 88, 0, 0, 0, 32, 99, 72, 82, 77, 0, 0, 122, 37, 0, 0, -128, -125, 0, 0, -7, -1, 0, 0, -128, -23, 0, 0, 117, 48, 0, 0, -22, 96, 0, 0, 58, -104, 0, 0, 23, 111, -110, 95, -59, 70, 0, 0, 0, 54, 73, 68, 65, 84, 120, -38, 76, -55, -79, 21, -128, 32, 0, -60, -48, 28, 14, 32, -52, -30, -2, -93, 121, -79, -112, -126, 116, -1, 37, 42, 71, 3, -72, -41, 4, -110, -88, -88, 42, 79, -37, 110, 3, 109, -81, 12, -33, -26, -1, 73, -88, 36, -33, 0, -62, -31, 36, 71, 49, 115, -89, 85, 0, 0, 0, 0, 73, 69, 78, 68, -82, 66, 96, -126 }; private byte[] originalIcoImageByteArray = new byte[]{0, 0, 1, 0, 1, 0, 16, 16, 0, 0, 1, 0, 24, 0, 7, 2, 0, 0, 22, 0, 0, 0, -119, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 16, 0, 0, 0, 16, 8, 6, 0, 0, 0, 31, -13, -1, 97, 0, 0, 1, -50, 73, 68, 65, 84, 56, -115, -51, -45, -49, 107, -46, 113, 28, -57, 113, -1, -111, 32, -94, 83, 116, 28, -44, 45, -126, 46, 117, -88, 91, 37, -76, -37, 26, -12, 99, 95, 38, -83, -62, 90, -10, 99, 101, 12, -14, -101, 63, -74, 125, -105, -72, -51, -104, -50, -111, -75, 37, 11, -61, -48, 73, 36, -77, -48, -24, -69, 10, 15, -126, 30, 12, -119, 82, -28, -21, -14, -117, 124, -31, -5, -3, 60, 59, -122, 124, 111, -115, -96, 55, -68, 46, -17, -61, -29, -14, 122, -65, 29, 14, -121, -125, 93, -58, -63, -33, -50, -65, 7, 76, -45, -28, -90, -5, 26, -7, 124, 30, 33, 4, -106, 101, 81, -87, 84, -16, -36, -102, -92, -33, -17, -37, 1, -45, 52, -23, 118, -69, -24, -70, 14, -128, 97, 24, 68, 67, 87, 9, 122, 47, 18, 85, -90, 80, 30, 79, -78, 24, 112, 49, -1, 72, 66, -41, -11, 65, 64, -45, 52, -54, -27, 50, -86, -86, -30, 116, 58, -119, -59, 98, 0, -92, 87, -68, -4, 42, -113, -16, -11, -75, -60, -113, -83, 75, -4, 44, -116, -78, -7, -52, 109, 7, 84, 85, -91, -45, -23, 0, -96, -21, 58, -75, 90, -115, -51, 108, -122, -128, 119, -116, 86, -15, 50, -71, -43, 113, -78, 9, 23, -75, -84, -60, -13, -89, -45, 8, 33, 6, -127, -19, -19, 109, 44, -53, 66, 8, 65, 46, -109, -58, 51, 49, -54, -46, -44, 41, 22, 30, -100, -90, -72, 126, -123, -4, -22, 56, 27, 81, -119, 111, 111, 37, 22, -97, -124, -20, 64, -67, 94, -89, 90, -83, 18, 14, -34, -26, -107, 124, -100, -110, 50, 68, 73, 25, -30, -115, -1, 40, -55, -64, 48, -33, -117, 46, 118, 74, -25, 73, 68, -18, -47, 104, 52, -20, 64, -81, -41, -29, -6, -40, 57, -118, -54, 97, 82, -14, 9, -34, -51, 29, 65, 13, 31, -32, -45, -36, 30, -34, -49, 30, 34, 19, 25, 38, 58, -21, -90, -35, 110, -37, 107, 20, 66, 16, 14, 121, 89, 8, 120, -16, -36, -104, 96, -1, -66, -67, -92, -110, -53, -84, 45, 7, 89, 9, 74, -28, 66, -57, 40, 43, 7, -119, 79, -97, -91, -72, 85, -80, 3, 27, 47, -30, -52, -36, -65, 0, -128, 16, 2, 89, -106, -111, 101, 25, 77, -45, 48, 12, -125, 47, -97, 85, 18, 75, 126, 94, -6, -49, -80, -26, 59, -55, -57, 15, 5, 76, -45, -4, 3, -52, -8, -18, -112, 78, 37, 7, -114, -88, -43, 106, 97, 24, -58, -64, -82, -39, 108, -78, 30, -97, 39, -14, 112, -124, -112, -17, -18, -1, -12, 11, -69, -55, 111, -87, -80, -30, 120, 52, 83, -116, 64, 0, 0, 0, 0, 73, 69, 78, 68, -82, 66, 96, -126}; @DataProvider private Object[][] rangeStringByteData() throws IOException { String inputData = Base64.encodeBase64String(byteArray); byte[] outputData = Base64.decodeBase64(inputData); return new Object[][]{ {inputData, outputData}, {null, null} }; } @Test(dataProvider = "validDataForConvertByteArrayToImageTest") public void testConvertByteArrayToImageForValidData(byte[] bytes, BufferedImage expected) throws ImageProcessException { BufferedImage actual = imageConverter.convertByteArrayToImage(bytes); byte[] actualResult = imageConverter.convertImageToByteArray(actual); byte[] expectedResult = imageConverter.convertImageToByteArray(expected); assertEquals(actualResult, expectedResult); } @DataProvider private Object[][] validDataForConvertByteArrayToImageTest() throws IOException { BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(originalImageByteArray)); BufferedImage result = ImageIO.read(bis); BufferedInputStream bisIco = new BufferedInputStream(new ByteArrayInputStream(originalIcoImageByteArray)); BufferedImage resultIco = ICODecoder.read(bisIco).get(0); return new Object[][]{ {originalImageByteArray, result}, {originalIcoImageByteArray, resultIco} }; } @Test(dataProvider = "validDataForImageToByteArrayTest") public void testConvertImageToByteArrayForValidData(BufferedImage image, byte[] expected, String format) throws ImageProcessException { imageConverter = ImageConverter.createConverter(format, DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT); byte[] actual = imageConverter.convertImageToByteArray(image); assertEquals(actual, expected); } @DataProvider private Object[][] validDataForImageToByteArrayTest() throws IOException { BufferedImage image = new BufferedImage(DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT, BufferedImage.TYPE_INT_RGB); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] result = null; try { ImageIO.write(image, "jpeg", baos); baos.flush(); result = baos.toByteArray(); } finally { baos.close(); } BufferedImage imagePng = new BufferedImage(DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT, BufferedImage.TYPE_INT_ARGB); baos = new ByteArrayOutputStream(); byte[] resultPng = null; try { ImageIO.write(imagePng, "png", baos); baos.flush(); resultPng = baos.toByteArray(); } finally { baos.close(); } BufferedImage imageIco = new BufferedImage(ICON_MAX_WIDTH, ICON_MAX_HEIGHT, BufferedImage.TYPE_INT_ARGB); baos = new ByteArrayOutputStream(); byte[] resultIco = null; try { ICOEncoder.write(imageIco, 32, baos); baos.flush(); resultIco = baos.toByteArray(); } finally { baos.close(); } return new Object[][]{ {image, result, "jpeg"}, {imagePng, resultPng, "png"}, {imageIco, resultIco, "ico"} }; } @Test(dataProvider = "imageFormats") public void createConverterMethodShouldReturnConverterWithSpecifiedType(String imageFormat, String imgPrefix) { ImageConverter converter = ImageConverter.createConverter(imageFormat, DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT); assertEquals(converter.getFormat(), imageFormat); assertEquals(converter.getHtmlSrcImagePrefix(), imgPrefix); } @DataProvider(name = "imageFormats") private Object[][] imageFormats() { return new Object[][]{ {"jpeg", "data:image/jpeg;base64,"}, {"png", "data:image/png;base64,"}, {"ico", "data:image/ico;base64,"} }; } @Test public void resizeIconWithWidthLessThenMinimumShouldCreateIconWidthMinimumWidth() { ImageConverter converter = ImageConverter.createConverter("ico", DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT); BufferedImage image = new BufferedImage(ImageConverter.MINIMUM_ICO_WIDTH / 4, 5, BufferedImage.TYPE_INT_ARGB); image = converter.resizeImage(image, BufferedImage.TYPE_INT_ARGB); assertEquals(image.getHeight(), 5 * 4); assertEquals(image.getWidth(), ImageConverter.MINIMUM_ICO_WIDTH); } @Test public void resizeIconWithWidthLessThenMinimumShouldCreateIconWidthMinimumWidthAndNotGreateThenMinimumHeight() { int maxSize = 16; ImageConverter converter = ImageConverter.createConverter("ico", maxSize, maxSize); BufferedImage image = new BufferedImage(ImageConverter.MINIMUM_ICO_WIDTH / 4, 5, BufferedImage.TYPE_INT_ARGB); image = converter.resizeImage(image, BufferedImage.TYPE_INT_ARGB); assertEquals(image.getHeight(), maxSize); assertEquals(image.getWidth(), ImageConverter.MINIMUM_ICO_WIDTH); } }