diff --git a/src/main/java/at/favre/tools/dconvert/arg/EScalingAlgorithm.java b/src/main/java/at/favre/tools/dconvert/arg/EScalingAlgorithm.java index 0c0ed85..946352c 100644 --- a/src/main/java/at/favre/tools/dconvert/arg/EScalingAlgorithm.java +++ b/src/main/java/at/favre/tools/dconvert/arg/EScalingAlgorithm.java @@ -2,7 +2,7 @@ import at.favre.tools.dconvert.converters.scaling.NaiveGraphics2dAlgorithm; import at.favre.tools.dconvert.converters.scaling.ProgressiveAlgorithm; -import at.favre.tools.dconvert.converters.scaling.ResambleAlgorithm; +import at.favre.tools.dconvert.converters.scaling.ResampleAlgorithm; import at.favre.tools.dconvert.converters.scaling.ScaleAlgorithm; import com.mortennobel.imagescaling.ResampleFilters; @@ -16,14 +16,14 @@ */ public enum EScalingAlgorithm { - LANCZOS1(new ResambleAlgorithm(new ResambleAlgorithm.LanczosFilter(1)), "lanczos1", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), - LANCZOS2(new ResambleAlgorithm(new ResambleAlgorithm.LanczosFilter(2)), "lanczos2", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), - LANCZOS3(new ResambleAlgorithm(new ResambleAlgorithm.LanczosFilter(3)), "lanczos3", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), - LANCZOS4(new ResambleAlgorithm(new ResambleAlgorithm.LanczosFilter(4)), "lanczos4", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), - LANCZOS5(new ResambleAlgorithm(new ResambleAlgorithm.LanczosFilter(5)), "lanczos5", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), - MITCHELL(new ResambleAlgorithm(ResampleFilters.getMitchellFilter()), "mitchell", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), - BSPLINE(new ResambleAlgorithm(ResampleFilters.getBSplineFilter()), "bspline", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), - HERMITE(new ResambleAlgorithm(ResampleFilters.getHermiteFilter()), "hermite", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), + LANCZOS1(new ResampleAlgorithm(new ResampleAlgorithm.LanczosFilter(1)), "lanczos1", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), + LANCZOS2(new ResampleAlgorithm(new ResampleAlgorithm.LanczosFilter(2)), "lanczos2", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), + LANCZOS3(new ResampleAlgorithm(new ResampleAlgorithm.LanczosFilter(3)), "lanczos3", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), + LANCZOS4(new ResampleAlgorithm(new ResampleAlgorithm.LanczosFilter(4)), "lanczos4", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), + LANCZOS5(new ResampleAlgorithm(new ResampleAlgorithm.LanczosFilter(5)), "lanczos5", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), + MITCHELL(new ResampleAlgorithm(ResampleFilters.getMitchellFilter()), "mitchell", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), + BSPLINE(new ResampleAlgorithm(ResampleFilters.getBSplineFilter()), "bspline", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), + HERMITE(new ResampleAlgorithm(ResampleFilters.getHermiteFilter()), "hermite", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, false), NEAREST_NEIGHBOR(new NaiveGraphics2dAlgorithm(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR), "nearestNeighbor", new Type[]{Type.DOWNSCALING, Type.UPSCALING}, true), BILINEAR_PROGRESSIVE(new ProgressiveAlgorithm(ProgressiveAlgorithm.Type.NOBEL_BILINEAR), "bilinearProgressive", new Type[]{Type.DOWNSCALING}, true), BICUBIC_PROGRESSIVE(new ProgressiveAlgorithm(ProgressiveAlgorithm.Type.NOBEL_BICUBUC), "bicubicProgressive", new Type[]{Type.DOWNSCALING}, true), diff --git a/src/main/java/at/favre/tools/dconvert/converters/APlatformConverter.java b/src/main/java/at/favre/tools/dconvert/converters/APlatformConverter.java index 634f507..8bde2f2 100644 --- a/src/main/java/at/favre/tools/dconvert/converters/APlatformConverter.java +++ b/src/main/java/at/favre/tools/dconvert/converters/APlatformConverter.java @@ -91,6 +91,7 @@ public Result convert(File srcImage, Arguments args) { return new Result(log.toString(), allResultingFiles); } catch (Exception e) { + e.printStackTrace(); return new Result(null, e, Collections.emptyList()); } } diff --git a/src/main/java/at/favre/tools/dconvert/converters/scaling/ProgressiveAlgorithm.java b/src/main/java/at/favre/tools/dconvert/converters/scaling/ProgressiveAlgorithm.java index 8867ee9..855d6c0 100644 --- a/src/main/java/at/favre/tools/dconvert/converters/scaling/ProgressiveAlgorithm.java +++ b/src/main/java/at/favre/tools/dconvert/converters/scaling/ProgressiveAlgorithm.java @@ -70,7 +70,7 @@ private BufferedImage scaleProgressiveLanczos(BufferedImage imageToScale, int ds if (dstWidth < (imageToScale.getWidth() / 2) && dstHeight < (imageToScale.getHeight() / 2)) { return new ThumbnailnatorProgressiveAlgorithm(RenderingHints.VALUE_INTERPOLATION_BILINEAR).scale(imageToScale, dstWidth, dstHeight); } else { - return new ResambleAlgorithm(new ResambleAlgorithm.LanczosFilter(radius)).scale(imageToScale, dstWidth, dstHeight); + return new ResampleAlgorithm(new ResampleAlgorithm.LanczosFilter(radius)).scale(imageToScale, dstWidth, dstHeight); } } diff --git a/src/main/java/at/favre/tools/dconvert/converters/scaling/ResambleAlgorithm.java b/src/main/java/at/favre/tools/dconvert/converters/scaling/ResampleAlgorithm.java similarity index 87% rename from src/main/java/at/favre/tools/dconvert/converters/scaling/ResambleAlgorithm.java rename to src/main/java/at/favre/tools/dconvert/converters/scaling/ResampleAlgorithm.java index 464ecf1..af25181 100644 --- a/src/main/java/at/favre/tools/dconvert/converters/scaling/ResambleAlgorithm.java +++ b/src/main/java/at/favre/tools/dconvert/converters/scaling/ResampleAlgorithm.java @@ -6,12 +6,12 @@ import java.awt.image.BufferedImage; /** - * Wrapper for Resamble Algos from Nobel's Lib + * Wrapper for Resample Algos from Nobel's Lib */ -public class ResambleAlgorithm implements ScaleAlgorithm { +public class ResampleAlgorithm implements ScaleAlgorithm { private ResampleFilter filter; - public ResambleAlgorithm(ResampleFilter filter) { + public ResampleAlgorithm(ResampleFilter filter) { this.filter = filter; } @@ -61,7 +61,7 @@ public String getName() { @Override public String toString() { - return "ResambleAlgorithm[" + filter.getName() + ']'; + return "ResampleAlgorithm[" + filter.getName() + ']'; } @Override @@ -69,7 +69,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - ResambleAlgorithm that = (ResambleAlgorithm) o; + ResampleAlgorithm that = (ResampleAlgorithm) o; return filter != null ? filter.equals(that.filter) : that.filter == null; diff --git a/src/main/java/at/favre/tools/dconvert/util/NinePatchScaler.java b/src/main/java/at/favre/tools/dconvert/util/NinePatchScaler.java index 556019c..614fd46 100644 --- a/src/main/java/at/favre/tools/dconvert/util/NinePatchScaler.java +++ b/src/main/java/at/favre/tools/dconvert/util/NinePatchScaler.java @@ -18,6 +18,7 @@ package at.favre.tools.dconvert.util; import at.favre.tools.dconvert.converters.scaling.ScaleAlgorithm; +import at.favre.tools.dconvert.converters.scaling.ThumbnailnatorProgressiveAlgorithm; import at.favre.tools.dconvert.exceptions.NinePatchException; import java.awt.*; @@ -33,6 +34,7 @@ public class NinePatchScaler { private ScaleAlgorithm algorithm; + private ScaleAlgorithm borderScalerAlgorithm = new ThumbnailnatorProgressiveAlgorithm(RenderingHints.VALUE_INTERPOLATION_BILINEAR); public BufferedImage scale(BufferedImage inputImage, Dimension dimensions, ScaleAlgorithm algorithm) throws NinePatchException { this.algorithm = algorithm; @@ -121,7 +123,7 @@ private BufferedImage generateBordersImage(BufferedImage source, int trimedWidth private BufferedImage resizeBorder(final BufferedImage border, int targetWidth, int targetHeight) { if (targetWidth > border.getWidth() || targetHeight > border.getHeight()) { - BufferedImage endImage = algorithm.scale(border, targetWidth, targetHeight); + BufferedImage endImage = borderScalerAlgorithm.scale(border, targetWidth, targetHeight); this.enforceBorderColors(endImage); return endImage; } diff --git a/src/main/resources/img/ninepatch_account.9.png b/src/main/resources/img/ninepatch_account.9.png new file mode 100644 index 0000000..0f1fdc9 Binary files /dev/null and b/src/main/resources/img/ninepatch_account.9.png differ diff --git a/src/main/resources/img/ninepatch_bubble.9.png b/src/main/resources/img/ninepatch_bubble.9.png new file mode 100644 index 0000000..79dc893 Binary files /dev/null and b/src/main/resources/img/ninepatch_bubble.9.png differ diff --git a/src/test/java/at/favre/tools/dconvert/test/AConverterTest.java b/src/test/java/at/favre/tools/dconvert/test/AConverterTest.java index b83bb65..98a5435 100644 --- a/src/test/java/at/favre/tools/dconvert/test/AConverterTest.java +++ b/src/test/java/at/favre/tools/dconvert/test/AConverterTest.java @@ -41,274 +41,279 @@ * Unit tests for {@link at.favre.tools.dconvert.converters.IPlatformConverter} */ public abstract class AConverterTest { - static final float DEFAULT_SCALE = 3; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - File defaultDst; - File defaultSrc; - IPlatformConverter converter; - ConverterCallback defaultCallback; - - @BeforeClass - public static void oneTimeSetUp() { - - } - - @AfterClass - public static void oneTimeTearDown() { - } - - @Before - public void setUp() throws IOException { - defaultSrc = temporaryFolder.newFolder("converter-test", "src"); - defaultDst = temporaryFolder.newFolder("converter-test", "out"); - converter = getType().getConverter(); - } - - @After - public void tearDown() { - defaultDst = defaultSrc = null; - converter = null; - defaultCallback = null; - } - - protected abstract EPlatform getType(); - - protected abstract void checkOutDir(File dstDir, Arguments arguments, List files, EPlatform type) throws IOException; - - @Test - public void testSinglePng() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); - defaultTest(files); - } - - @Test - public void testSingleJpeg() throws Exception { - List files = copyToTestPath(defaultSrc, "jpg_example_1920.jpg"); - defaultTest(files); - } - - @Test - public void testSingleGif() throws Exception { - List files = copyToTestPath(defaultSrc, "gif_example_640.gif"); - defaultTest(files); - } - - @Test - public void testSingleBmp() throws Exception { - List files = copyToTestPath(defaultSrc, "bmp_example_256.bmp"); - defaultTest(files); - } - - @Test - public void testSingleTiff() throws Exception { - List files = copyToTestPath(defaultSrc, "tiff_example_256.tif"); - defaultTest(files); - } - - @Test - public void testSinglePsd() throws Exception { - List files = copyToTestPath(defaultSrc, "psd_example_827.psd"); - defaultTest(files); - } - - @Test - public void testSingleSvg() throws Exception { - List files = copyToTestPath(defaultSrc, "svg_example_512.svg"); - defaultTest(files); - } - - @Test - public void testRoundMode() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); - test(new Arguments.Builder(defaultSrc, 2.33f).dstFolder(defaultDst).scaleRoundingStragy(RoundingHandler.Strategy.FLOOR).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testScaleWidthInDp() throws Exception { - List files = copyToTestPath(defaultSrc, "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, 24).dstFolder(defaultDst).scaleMode(EScaleMode.DP_WIDTH).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testMultipleScaleWidthInDp() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png", "png_example4_500.png", "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, 48).dstFolder(defaultDst).scaleMode(EScaleMode.DP_WIDTH).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testScaleHeightInDp() throws Exception { - List files = copyToTestPath(defaultSrc, "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, 128).dstFolder(defaultDst).scaleMode(EScaleMode.DP_HEIGHT).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testMultipleScaleHeightInDp() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png", "png_example4_500.png", "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, 48).dstFolder(defaultDst).scaleMode(EScaleMode.DP_HEIGHT).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testMultiplePng() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png", "png_example2_alpha_144.png", "png_example3_alpha_128.png"); - defaultTest(files); - } - - @Test - public void testPngAndJpegKeepCompressions() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "jpg_example_1920.jpg"); - defaultTest(files); - } - - @Test - public void testMixedCompressionsShouldBeMostlyPng() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "psd_example_827.psd", "bmp_example_256.bmp", "jpg_example_1920.jpg"); - defaultTest(files); - } - - @Test - public void testMixedCompressionsShouldKeepCompressions() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "tiff_example_256.tif", "bmp_example_256.bmp", "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.SAME_AS_INPUT_STRICT, 0.5f) - .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testMixedCompressionsShouldCreateJpg() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "psd_example_827.psd", "bmp_example_256.bmp", "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.AS_JPG, 0.0f) - .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testMixedCompressionsShouldCreateJpgAndPng() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.AS_JPG_AND_PNG, 0.0f) - .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testDryRun() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "jpg_example_1920.jpg"); - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.AS_JPG_AND_PNG, 0.0f) - .dstFolder(defaultDst).platform(Collections.singleton(getType())).dryRun(true).build(), files); - } - - protected void defaultTest(List files) throws Exception { - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.SAME_AS_INPUT_PREF_PNG, 0.5f) - .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); - } - - protected void test(Arguments arg, List files) throws Exception { - for (File fileToProcess : arg.filesToProcess) { - Result result = converter.convert(fileToProcess, arg); - assertNull("should be no exception", result.exception); - } - - if (arg.dryRun) { - assertEquals("destination folder should be empty", 0, arg.dst.list().length); - } else { - checkOutDir(arg.dst, arg, files, getType()); - } - } - - public static List copyToTestPath(File defaultSrc, String... resourceNames) throws Exception { - List copiedFiles = new ArrayList<>(); - for (String resourceName : resourceNames) { - File dstFile = new File(defaultSrc, resourceName); - Files.copy(new File(AConverterTest.class.getClassLoader().getResource(resourceName).getFile()).toPath(), dstFile.toPath()); - copiedFiles.add(dstFile); - } - return copiedFiles; - } - - public static void checkMultiPlatformConvert(File dst, Arguments arg, List files) throws IOException { - AndroidConverterTest.checkOutDirAndroid(new File(dst, "android"), arg, files); - IOSConverterTest.checkOutDirIos(new File(dst, "ios"), arg, files); - WindowsConverterTest.checkOutDirWindows(new File(dst, "windows"), arg, files); - WebConverterTest.checkOutDirWeb(new File(dst, "web"), arg, files); - } - - protected static Map createDimensionMap(List files) throws IOException { - Map map = new HashMap<>(); - - for (File file : files) { - map.put(file, ImageUtil.getImageDimension(file)); - } - return map; - } - - protected static Dimension getScaledDimension(File srcFile, Arguments args, Dimension dimension, float scale) throws IOException { - double baseWidth; - double baseHeight; - - if (args.scaleMode == EScaleMode.DP_WIDTH) { - Dimension srcDimension = ImageUtil.getImageDimension(srcFile); - float scaleFactor = args.scale / (float) srcDimension.width; - - baseWidth = (int) args.round(args.scale); - baseHeight = (int) args.round(scaleFactor * (float) srcDimension.height); - } else if (args.scaleMode == EScaleMode.DP_HEIGHT) { - Dimension srcDimension = ImageUtil.getImageDimension(srcFile); - float scaleFactor = args.scale / (float) srcDimension.height; - - baseWidth = (int) args.round(scaleFactor * (float) srcDimension.width); - baseHeight = (int) args.round(args.scale); - } else { - baseWidth = (double) dimension.width / args.scale; - baseHeight = (double) dimension.height / args.scale; - } - - return new Dimension((int) args.round(baseWidth * scale), - (int) args.round(baseHeight * scale)); - } - - - protected static class ImageInfo { - public final File srcFile; - public final String targetFileName; - public final float scale; - public boolean found = false; - - public ImageInfo(File srcFile, String targetFileName, float scale) { - this.srcFile = srcFile; - this.targetFileName = targetFileName; - this.scale = scale; - } - } - - public static void checkOutDirPostfixDescr(File dstRootDir, Arguments arguments, List files, List densityDescriptors) throws IOException { - Map dimensionMap = createDimensionMap(files); - - if (!files.isEmpty()) { - assertTrue("src files and dst folder count should match", dstRootDir.listFiles().length >= files.size()); - - List expectedFiles = new ArrayList<>(); - for (File srcImageFile : files) { - for (PostfixDescriptor descriptor : densityDescriptors) { - expectedFiles.addAll(Arguments.getOutCompressionForType(arguments.outputCompressionMode, Arguments.getImageType(srcImageFile)).stream().map(compression -> new ImageInfo(srcImageFile, MiscUtil.getFileNameWithoutExtension(srcImageFile) + descriptor.postFix + "." + compression.extension, descriptor.scale)).collect(Collectors.toList())); - } - } - - for (File imageFile : dstRootDir.listFiles()) { - for (ImageInfo expectedFile : expectedFiles) { - if (expectedFile.targetFileName.equals(imageFile.getName())) { - expectedFile.found = true; - - Dimension expectedDimension = getScaledDimension(expectedFile.srcFile, arguments, dimensionMap.get(expectedFile.srcFile), expectedFile.scale); - assertEquals("dimensions should match", expectedDimension, ImageUtil.getImageDimension(imageFile)); - } - } - } - - for (ImageInfo expectedFile : expectedFiles) { - assertTrue(expectedFile.targetFileName + " expected in folder " + dstRootDir, expectedFile.found); - } - - System.out.println("found " + expectedFiles.size() + " files in " + dstRootDir); - } else { - assertTrue(dstRootDir.list() == null || dstRootDir.list().length == 0); - } - } + static final float DEFAULT_SCALE = 3; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + File defaultDst; + File defaultSrc; + IPlatformConverter converter; + ConverterCallback defaultCallback; + + @BeforeClass + public static void oneTimeSetUp() { + + } + + @AfterClass + public static void oneTimeTearDown() { + } + + @Before + public void setUp() throws IOException { + defaultSrc = temporaryFolder.newFolder("converter-test", "src"); + defaultDst = temporaryFolder.newFolder("converter-test", "out"); + converter = getType().getConverter(); + } + + @After + public void tearDown() { + defaultDst = defaultSrc = null; + converter = null; + defaultCallback = null; + } + + protected abstract EPlatform getType(); + + protected abstract void checkOutDir(File dstDir, Arguments arguments, List files, EPlatform type) throws IOException; + + @Test + public void testSinglePng() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); + defaultTest(files); + } + + @Test + public void testSingleJpeg() throws Exception { + List files = copyToTestPath(defaultSrc, "jpg_example_1920.jpg"); + defaultTest(files); + } + + @Test + public void testSingleGif() throws Exception { + List files = copyToTestPath(defaultSrc, "gif_example_640.gif"); + defaultTest(files); + } + + @Test + public void testSingleBmp() throws Exception { + List files = copyToTestPath(defaultSrc, "bmp_example_256.bmp"); + defaultTest(files); + } + + @Test + public void testSingleTiff() throws Exception { + List files = copyToTestPath(defaultSrc, "tiff_example_256.tif"); + defaultTest(files); + } + + @Test + public void testSinglePsd() throws Exception { + List files = copyToTestPath(defaultSrc, "psd_example_827.psd"); + defaultTest(files); + } + + @Test + public void testSingleSvg() throws Exception { + List files = copyToTestPath(defaultSrc, "svg_example_512.svg"); + defaultTest(files); + } + + @Test + public void testRoundMode() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); + test(new Arguments.Builder(defaultSrc, 2.33f).dstFolder(defaultDst).scaleRoundingStragy(RoundingHandler.Strategy.FLOOR).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testScaleWidthInDp() throws Exception { + List files = copyToTestPath(defaultSrc, "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, 24).dstFolder(defaultDst).scaleMode(EScaleMode.DP_WIDTH).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testMultipleScaleWidthInDp() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png", "png_example4_500.png", "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, 48).dstFolder(defaultDst).scaleMode(EScaleMode.DP_WIDTH).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testScaleHeightInDp() throws Exception { + List files = copyToTestPath(defaultSrc, "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, 128).dstFolder(defaultDst).scaleMode(EScaleMode.DP_HEIGHT).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testMultipleScaleHeightInDp() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png", "png_example4_500.png", "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, 48).dstFolder(defaultDst).scaleMode(EScaleMode.DP_HEIGHT).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testMultiplePng() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png", "png_example2_alpha_144.png", "png_example3_alpha_128.png"); + defaultTest(files); + } + + @Test + public void testPngAndJpegKeepCompressions() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "jpg_example_1920.jpg"); + defaultTest(files); + } + + @Test + public void testMixedCompressionsShouldBeMostlyPng() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "psd_example_827.psd", "bmp_example_256.bmp", "jpg_example_1920.jpg"); + defaultTest(files); + } + + @Test + public void testMixedCompressionsShouldKeepCompressions() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "tiff_example_256.tif", "bmp_example_256.bmp", "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.SAME_AS_INPUT_STRICT, 0.5f) + .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testMixedCompressionsShouldCreateJpg() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "psd_example_827.psd", "bmp_example_256.bmp", "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.AS_JPG, 0.0f) + .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testMixedCompressionsShouldCreateJpgAndPng() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.AS_JPG_AND_PNG, 0.0f) + .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testDryRun() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example2_alpha_144.png", "gif_example_640.gif", "jpg_example_1920.jpg"); + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.AS_JPG_AND_PNG, 0.0f) + .dstFolder(defaultDst).platform(Collections.singleton(getType())).dryRun(true).build(), files); + } + + protected void defaultTest(List files) throws Exception { + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).compression(EOutputCompressionMode.SAME_AS_INPUT_PREF_PNG, 0.5f) + .dstFolder(defaultDst).platform(Collections.singleton(getType())).build(), files); + } + + protected void test(Arguments arg, List files) throws Exception { + for (File fileToProcess : arg.filesToProcess) { + Result result = converter.convert(fileToProcess, arg); + assertNull("should be no exception: " + result.exception, result.exception); + } + + if (arg.dryRun) { + assertEquals("destination folder should be empty", 0, arg.dst.list().length); + } else { + checkOutDir(arg.dst, arg, files, getType()); + } + } + + public static List copyToTestPath(File defaultSrc, String... resourceNames) throws Exception { + List copiedFiles = new ArrayList<>(); + for (String resourceName : resourceNames) { + File dstFile = new File(defaultSrc, resourceName); + Files.copy(new File(AConverterTest.class.getClassLoader().getResource(resourceName).getFile()).toPath(), dstFile.toPath()); + copiedFiles.add(dstFile); + } + return copiedFiles; + } + + public static void checkMultiPlatformConvert(File dst, Arguments arg, List files) throws IOException { + AndroidConverterTest.checkOutDirAndroid(new File(dst, "android"), arg, files); + IOSConverterTest.checkOutDirIos(new File(dst, "ios"), arg, files); + WindowsConverterTest.checkOutDirWindows(new File(dst, "windows"), arg, files); + WebConverterTest.checkOutDirWeb(new File(dst, "web"), arg, files); + } + + protected static Map createDimensionMap(List files) throws IOException { + Map map = new HashMap<>(); + + for (File file : files) { + map.put(file, ImageUtil.getImageDimension(file)); + } + return map; + } + + protected static Dimension getScaledDimension(File srcFile, Arguments args, Dimension dimension, float scale, boolean isNinePatch) throws IOException { + double baseWidth; + double baseHeight; + + if (args.scaleMode == EScaleMode.DP_WIDTH) { + Dimension srcDimension = ImageUtil.getImageDimension(srcFile); + float scaleFactor = args.scale / (float) srcDimension.width; + + baseWidth = (int) args.round(args.scale); + baseHeight = (int) args.round(scaleFactor * (float) srcDimension.height); + } else if (args.scaleMode == EScaleMode.DP_HEIGHT) { + Dimension srcDimension = ImageUtil.getImageDimension(srcFile); + float scaleFactor = args.scale / (float) srcDimension.height; + + baseWidth = (int) args.round(scaleFactor * (float) srcDimension.width); + baseHeight = (int) args.round(args.scale); + } else { + baseWidth = (double) dimension.width / args.scale; + baseHeight = (double) dimension.height / args.scale; + } + + if (isNinePatch) { + return new Dimension((int) args.round(((baseWidth + 1) * scale) + 2), + (int) args.round(((baseHeight + 1) * scale) + 2)); + } else { + return new Dimension((int) args.round(baseWidth * scale), + (int) args.round(baseHeight * scale)); + } + } + + + protected static class ImageInfo { + public final File srcFile; + public final String targetFileName; + public final float scale; + public boolean found = false; + + public ImageInfo(File srcFile, String targetFileName, float scale) { + this.srcFile = srcFile; + this.targetFileName = targetFileName; + this.scale = scale; + } + } + + public static void checkOutDirPostfixDescr(File dstRootDir, Arguments arguments, List files, List densityDescriptors) throws IOException { + Map dimensionMap = createDimensionMap(files); + + if (!files.isEmpty()) { + assertTrue("src files and dst folder count should match", dstRootDir.listFiles().length >= files.size()); + + List expectedFiles = new ArrayList<>(); + for (File srcImageFile : files) { + for (PostfixDescriptor descriptor : densityDescriptors) { + expectedFiles.addAll(Arguments.getOutCompressionForType(arguments.outputCompressionMode, Arguments.getImageType(srcImageFile)).stream().map(compression -> new ImageInfo(srcImageFile, MiscUtil.getFileNameWithoutExtension(srcImageFile) + descriptor.postFix + "." + compression.extension, descriptor.scale)).collect(Collectors.toList())); + } + } + + for (File imageFile : dstRootDir.listFiles()) { + for (ImageInfo expectedFile : expectedFiles) { + if (expectedFile.targetFileName.equals(imageFile.getName())) { + expectedFile.found = true; + + Dimension expectedDimension = getScaledDimension(expectedFile.srcFile, arguments, dimensionMap.get(expectedFile.srcFile), expectedFile.scale, false); + assertEquals("dimensions should match", expectedDimension, ImageUtil.getImageDimension(imageFile)); + } + } + } + + for (ImageInfo expectedFile : expectedFiles) { + assertTrue(expectedFile.targetFileName + " expected in folder " + dstRootDir, expectedFile.found); + } + + System.out.println("found " + expectedFiles.size() + " files in " + dstRootDir); + } else { + assertTrue(dstRootDir.list() == null || dstRootDir.list().length == 0); + } + } } diff --git a/src/test/java/at/favre/tools/dconvert/test/AndroidConverterTest.java b/src/test/java/at/favre/tools/dconvert/test/AndroidConverterTest.java index 28ff389..52242d3 100644 --- a/src/test/java/at/favre/tools/dconvert/test/AndroidConverterTest.java +++ b/src/test/java/at/favre/tools/dconvert/test/AndroidConverterTest.java @@ -23,7 +23,6 @@ import at.favre.tools.dconvert.converters.AndroidConverter; import at.favre.tools.dconvert.util.ImageUtil; import at.favre.tools.dconvert.util.MiscUtil; -import org.junit.Ignore; import org.junit.Test; import java.awt.*; @@ -42,126 +41,127 @@ */ public class AndroidConverterTest extends AConverterTest { - @Test - public void testMipmapFolder() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).dstFolder(defaultDst).createMipMapInsteadOfDrawableDir(true).includeAndroidLdpiTvdpi(true).platform(Collections.singleton(getType())).build(), files); - } - - @Test - public void testLdpiAndTvdpi() throws Exception { - List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); - test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).dstFolder(defaultDst).includeAndroidLdpiTvdpi(true).platform(Collections.singleton(getType())).build(), files); - } - - @Ignore - @Test - public void testSingleNinePatch() throws Exception { - List files = copyToTestPath(defaultSrc, "ninepatch_bubble.9.png"); - defaultTest(files); - } - - @Override - protected EPlatform getType() { - return EPlatform.ANDROID; - } - - @Override - protected void checkOutDir(File dstDir, Arguments arguments, List files, EPlatform type) throws IOException { - checkOutDirAndroid(dstDir, arguments, files); - } - - public static void checkOutDirAndroid(File dstDir, Arguments arguments, List files) throws IOException { - Map dimensionMap = createDimensionMap(files); - - List expectedDirs = new ArrayList<>(); - - - expectedDirs.addAll(AndroidConverter.getAndroidDensityDescriptors(arguments).stream().map( - androidDensityDescriptor -> new DensityFolder(androidDensityDescriptor.folderName, androidDensityDescriptor.scale)).collect(Collectors.toList())); - - assertFalse("expected dirs should not be empty", expectedDirs.isEmpty()); - if (!files.isEmpty()) { - assertFalse("output dir should not be empty", dstDir.list() == null && dstDir.list().length == 0); - - - System.out.println("Android-convert " + files); - - for (String path : dstDir.list()) { - expectedDirs.stream().filter(expectedDir -> expectedDir.folderName.equals(path)).forEach(expectedDir -> { - try { - expectedDir.found = true; - - List expectedFiles = createExpectedFilesMap(arguments, new File(dstDir, path), files); - - assertTrue("files count should match input", files.isEmpty() == expectedFiles.isEmpty()); - - for (ImageCheck expectedFile : expectedFiles) { - for (File imageFile : new File(dstDir, path).listFiles()) { - if (expectedFile.targetFile.equals(imageFile)) { - expectedFile.found = true; - Dimension expectedDimension = getScaledDimension(expectedFile.srcFile, arguments, dimensionMap.get(expectedFile.srcFile), expectedDir.scaleFactor); - assertEquals("dimensions should match", expectedDimension, ImageUtil.getImageDimension(imageFile)); - } - } - } - - for (ImageCheck expectedFile : expectedFiles) { - assertTrue(expectedFile.targetFile + " file should be generated in path", expectedFile.found); - } - System.out.print("found " + expectedFiles.size() + " files in " + expectedDir.folderName + ", "); - } catch (Exception e) { - fail(); - e.printStackTrace(); - } - }); - - } - - for (DensityFolder expectedDir : expectedDirs) { - assertTrue(expectedDir.folderName + " should be generated in path", expectedDir.found); - } - - System.out.println(); - } else { - assertTrue(dstDir.list() == null || dstDir.list().length == 0); - } - } - - private static List createExpectedFilesMap(Arguments arguments, File file, List files) throws IOException { - List expectedFiles = new ArrayList<>(); - - for (File srcImageFile : files) { - for (ImageType.ECompression compression : Arguments.getOutCompressionForType(arguments.outputCompressionMode, Arguments.getImageType(srcImageFile))) { - expectedFiles.add(new ImageCheck(srcImageFile, new File(file, MiscUtil.getFileNameWithoutExtension(srcImageFile) + "." + compression.extension))); - } - } - - return expectedFiles; - } - - private static class ImageCheck { - public final File srcFile; - public final File targetFile; - public final boolean isNinepatch; - public boolean found; - - public ImageCheck(File srcFile, File targetFile) throws IOException { - this.srcFile = srcFile; - this.targetFile = targetFile; - this.isNinepatch = AndroidConverter.isNinePatch(srcFile); - } - } - - private static class DensityFolder { - public final String folderName; - public final float scaleFactor; - public boolean found; - - public DensityFolder(String folderName, float scaleFactor) { - this.folderName = folderName; - this.scaleFactor = scaleFactor; - } - } + @Test + public void testMipmapFolder() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).dstFolder(defaultDst).createMipMapInsteadOfDrawableDir(true).includeAndroidLdpiTvdpi(true).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testLdpiAndTvdpi() throws Exception { + List files = copyToTestPath(defaultSrc, "png_example1_alpha_144.png"); + test(new Arguments.Builder(defaultSrc, DEFAULT_SCALE).dstFolder(defaultDst).includeAndroidLdpiTvdpi(true).platform(Collections.singleton(getType())).build(), files); + } + + @Test + public void testSingleNinePatch() throws Exception { + List files = copyToTestPath(defaultSrc, "ninepatch_bubble.9.png"); + defaultTest(files); + } + + @Override + protected EPlatform getType() { + return EPlatform.ANDROID; + } + + @Override + protected void checkOutDir(File dstDir, Arguments arguments, List files, EPlatform type) throws IOException { + checkOutDirAndroid(dstDir, arguments, files); + } + + public static void checkOutDirAndroid(File dstDir, Arguments arguments, List files) throws IOException { + Map dimensionMap = createDimensionMap(files); + + List expectedDirs = new ArrayList<>(); + + + expectedDirs.addAll(AndroidConverter.getAndroidDensityDescriptors(arguments).stream().map( + androidDensityDescriptor -> new DensityFolder(androidDensityDescriptor.folderName, androidDensityDescriptor.scale)).collect(Collectors.toList())); + + assertFalse("expected dirs should not be empty", expectedDirs.isEmpty()); + if (!files.isEmpty()) { + assertFalse("output dir should not be empty", dstDir.list() == null && dstDir.list().length == 0); + + + System.out.println("Android-convert " + files); + + for (String path : dstDir.list()) { + expectedDirs.stream().filter(expectedDir -> expectedDir.folderName.equals(path)).forEach(expectedDir -> { + try { + expectedDir.found = true; + + List expectedFiles = createExpectedFilesMap(arguments, new File(dstDir, path), files); + + assertTrue("files count should match input", files.isEmpty() == expectedFiles.isEmpty()); + + for (ImageCheck expectedFile : expectedFiles) { + for (File imageFile : new File(dstDir, path).listFiles()) { + if (expectedFile.targetFile.equals(imageFile)) { + expectedFile.found = true; + Dimension expectedDimension = getScaledDimension(expectedFile.srcFile, arguments, dimensionMap.get(expectedFile.srcFile), expectedDir.scaleFactor, expectedFile.isNinepatch); + Dimension actualDimensions = ImageUtil.getImageDimension(imageFile); + assertEquals("height should match", expectedDimension.getHeight(), actualDimensions.getHeight(), expectedFile.isNinepatch ? 15 : 0.1); + assertEquals("width should match", expectedDimension.getWidth(), actualDimensions.getWidth(), expectedFile.isNinepatch ? 15 : 0.1); + } + } + } + + for (ImageCheck expectedFile : expectedFiles) { + assertTrue(expectedFile.targetFile + " file should be generated in path", expectedFile.found); + } + System.out.print("found " + expectedFiles.size() + " files in " + expectedDir.folderName + ", "); + } catch (Exception e) { + fail(); + e.printStackTrace(); + } + }); + + } + + for (DensityFolder expectedDir : expectedDirs) { + assertTrue(expectedDir.folderName + " should be generated in path", expectedDir.found); + } + + System.out.println(); + } else { + assertTrue(dstDir.list() == null || dstDir.list().length == 0); + } + } + + private static List createExpectedFilesMap(Arguments arguments, File file, List files) throws IOException { + List expectedFiles = new ArrayList<>(); + + for (File srcImageFile : files) { + for (ImageType.ECompression compression : Arguments.getOutCompressionForType(arguments.outputCompressionMode, Arguments.getImageType(srcImageFile))) { + expectedFiles.add(new ImageCheck(srcImageFile, new File(file, MiscUtil.getFileNameWithoutExtension(srcImageFile) + "." + compression.extension))); + } + } + + return expectedFiles; + } + + private static class ImageCheck { + public final File srcFile; + public final File targetFile; + public final boolean isNinepatch; + public boolean found; + + public ImageCheck(File srcFile, File targetFile) throws IOException { + this.srcFile = srcFile; + this.targetFile = targetFile; + this.isNinepatch = AndroidConverter.isNinePatch(srcFile); + } + } + + private static class DensityFolder { + public final String folderName; + public final float scaleFactor; + public boolean found; + + public DensityFolder(String folderName, float scaleFactor) { + this.folderName = folderName; + this.scaleFactor = scaleFactor; + } + } } diff --git a/src/test/java/at/favre/tools/dconvert/test/IOSConverterTest.java b/src/test/java/at/favre/tools/dconvert/test/IOSConverterTest.java index 6abeb64..65d2447 100644 --- a/src/test/java/at/favre/tools/dconvert/test/IOSConverterTest.java +++ b/src/test/java/at/favre/tools/dconvert/test/IOSConverterTest.java @@ -109,7 +109,7 @@ private static void checkWithImagesetFolders(File dstDir, Arguments arguments, L if (dstImageFile.getName().equals(expectedFile.targetFileName)) { expectedFile.found = true; - Dimension expectedDimension = getScaledDimension(expectedFile.srcFile, arguments, dimensionMap.get(expectedFile.srcFile), expectedFile.scale); + Dimension expectedDimension = getScaledDimension(expectedFile.srcFile, arguments, dimensionMap.get(expectedFile.srcFile), expectedFile.scale, false); assertEquals("dimensions should match", expectedDimension, ImageUtil.getImageDimension(dstImageFile)); } }