From 168e4b0c8bead48c68a2557c1a368f07285fb16e Mon Sep 17 00:00:00 2001 From: asiekierka Date: Sat, 30 Jan 2021 16:54:11 +0100 Subject: [PATCH] 0.5.1 --- build.gradle | 5 +- docs/changelog/0.5.1.txt | 13 +++ docs/changelog/versions.txt | 5 +- src/main/java/pl/asie/zima/Version.java | 8 ++ .../zima/image/TrixImageMseCalculator.java | 44 +++++++-- .../zima/image/gui/ZimaConversionProfile.java | 5 +- .../zima/image/gui/ZimaFrontendSwing.java | 36 +++++-- .../zima/image/gui/ZimaProfileSettings.java | 3 + .../util/AspectRatioPreservationMode.java | 37 +++++++ .../java/pl/asie/zima/util/ImageUtils.java | 54 ++++++++--- .../asie/zima/util/gui/ImageFileChooser.java | 5 +- .../zima/util/ImageUtilsAspectRatioTest.java | 96 +++++++++++++++++++ 12 files changed, 276 insertions(+), 35 deletions(-) create mode 100644 docs/changelog/0.5.1.txt create mode 100644 src/main/java/pl/asie/zima/util/AspectRatioPreservationMode.java create mode 100644 src/test/java/pl/asie/zima/util/ImageUtilsAspectRatioTest.java diff --git a/build.gradle b/build.gradle index 55edf24..4eb7186 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { } group 'pl.asie.zima' -version '0.5.0' +version '0.5.1' repositories { mavenCentral() @@ -14,6 +14,9 @@ repositories { dependencies { implementation 'com.google.code.gson:gson:2.8.6' + + testImplementation(platform('org.junit:junit-bom:5.7.0')) + testImplementation('org.junit.jupiter:junit-jupiter') } license { diff --git a/docs/changelog/0.5.1.txt b/docs/changelog/0.5.1.txt new file mode 100644 index 0000000..826cb41 --- /dev/null +++ b/docs/changelog/0.5.1.txt @@ -0,0 +1,13 @@ +Improvements: + +* In order to combat the issue of border halfchars forming around images, new aspect ratio preservation modes have been + added as follows: + * Snap to char (new default) - rounds width/height to the nearest character. + * Snap to center - rounds width/height to the nearest character which allows the image to be centered. +* The aspect ratio preservation mode is now saved as part of the profile. +* The window title now displays the program version. + +Bugs fixed: + +* The window pane showing scroll bars when unnecessary on some platforms has been fixed. +* The correct program version is now displayed (regression in 0.4.2+). \ No newline at end of file diff --git a/docs/changelog/versions.txt b/docs/changelog/versions.txt index 109f518..3ddb90f 100644 --- a/docs/changelog/versions.txt +++ b/docs/changelog/versions.txt @@ -2,4 +2,7 @@ 0.2.0 0.3.0 0.4.0 -0.4.1 \ No newline at end of file +0.4.1 +0.4.2 +0.5.0 +0.5.1 \ No newline at end of file diff --git a/src/main/java/pl/asie/zima/Version.java b/src/main/java/pl/asie/zima/Version.java index 1080307..a5b3634 100644 --- a/src/main/java/pl/asie/zima/Version.java +++ b/src/main/java/pl/asie/zima/Version.java @@ -28,6 +28,14 @@ public final class Version { private static final List versions; + public static String getCurrentWindowName(String appName) { + if (appName.isBlank()) { + return "zima " + getCurrent(); + } else { + return "zima " + getCurrent() + " :: " + appName; + } + } + public static String getCurrent() { return versions != null && !versions.isEmpty() ? versions.get(versions.size() - 1) : "[unknown version]"; } diff --git a/src/main/java/pl/asie/zima/image/TrixImageMseCalculator.java b/src/main/java/pl/asie/zima/image/TrixImageMseCalculator.java index 1decad3..2a670af 100644 --- a/src/main/java/pl/asie/zima/image/TrixImageMseCalculator.java +++ b/src/main/java/pl/asie/zima/image/TrixImageMseCalculator.java @@ -22,7 +22,9 @@ import pl.asie.libzzt.TextVisualData; import java.awt.image.BufferedImage; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -35,6 +37,7 @@ public class TrixImageMseCalculator implements ImageMseCalculator { private final boolean[][] charLut1x1Precalc; private final float[] colDistPrecalc; private final boolean blinkingDisabled; + private final int[][] blendingColorPrecalc; private final Set blendingChars = new HashSet<>(); private static class ImageLutHolder { @@ -139,21 +142,39 @@ public TrixImageMseCalculator(TextVisualData visual, boolean blinkingDisabled, f blendingChars.add(i); } } + + blendingColorPrecalc = new int[256][]; + Map bcpMap = new HashMap<>(); + final int bcpMax = (visual.getCharWidth() * visual.getCharHeight()); + for (int i = 0; i < 256; i++) { + if (blendingChars.contains(i)) { + int count = 0; + for (int j = 0; j < bcpMax; j++) { + count += charLut1x1Precalc[i][j] ? 1 : 0; + } + blendingColorPrecalc[i] = bcpMap.computeIfAbsent(count, c -> { + float factor = c / (float) bcpMax; + int[] data = new int[256]; + for (int k = 0; k < 256; k++) { + data[k] = ColorUtils.mix(visual.getPalette()[k >> 4], visual.getPalette()[k & 15], factor); + } + return data; + }); + } + } } @Override public Applier applyMse(BufferedImage image, int px, int py) { final ImageLutHolder holder = new ImageLutHolder(visual, image, px, py, visual.getCharWidth(), visual.getCharHeight()); float[] mseContrastPrecalc = new float[256]; - float[] macroRatioPrecalc = new float[256]; for (int i = 0; i < 256; i++) { float imgContrast = holder.maxDistance; float chrContrast = colDistPrecalc[i]; float contrastDiff = (imgContrast - chrContrast); mseContrastPrecalc[i] = contrastReduction * contrastDiff * contrastDiff; - - macroRatioPrecalc[i] = blendingChars.contains(i) ? 1.0f : accurateApproximate; } + final int[] palette = visual.getPalette(); final int colorMask = blinkingDisabled ? 0xFF : 0x7F; return (proposed, maxMse) -> { int chr = proposed.getCharacter(); @@ -163,10 +184,21 @@ public Applier applyMse(BufferedImage image, int px, int py) { int[] dataMacro2x2 = holder.dataMacro2x2; float mseContrastReduction = mseContrastPrecalc[col]; - float macroRatio = macroRatioPrecalc[chr]; + float macroRatio = accurateApproximate; mse += dataMacro2x2.length * mseContrastReduction; if (mse <= maxMse) { + int[] blendingRatio = blendingColorPrecalc[chr]; + if (blendingRatio != null) { + for (int i = 0; i < dataMacro2x2.length; i++) { + mse += ColorUtils.distance(blendingRatio[col], dataMacro2x2[i]); + if (mse > maxMse) { + return Float.MAX_VALUE; + } + } + return mse; + } + if (macroRatio < 1.0f) { float invMacroRatio = ((1 - macroRatio) * 0.25f); float[][] dataMacro1x1 = holder.dataMacro1x1; @@ -178,7 +210,7 @@ public Applier applyMse(BufferedImage image, int px, int py) { int charColor = charData[dm1p] ? fg : bg; mse += dataMacro1x1[dm1p][charColor] * invMacroRatio; if (mse > maxMse) { - return mse; + return Float.MAX_VALUE; } } } @@ -192,7 +224,7 @@ public Applier applyMse(BufferedImage image, int px, int py) { float dist2x2 = ColorUtils.distance(char2x2Lut, dataMacro2x2[i]); mse += dist2x2 * macroRatio; if (mse > maxMse) { - return mse; + return Float.MAX_VALUE; } } } diff --git a/src/main/java/pl/asie/zima/image/gui/ZimaConversionProfile.java b/src/main/java/pl/asie/zima/image/gui/ZimaConversionProfile.java index cb2d17e..7b8479c 100644 --- a/src/main/java/pl/asie/zima/image/gui/ZimaConversionProfile.java +++ b/src/main/java/pl/asie/zima/image/gui/ZimaConversionProfile.java @@ -19,7 +19,6 @@ package pl.asie.zima.image.gui; import lombok.Getter; -import pl.asie.libzzt.Board; import pl.asie.libzzt.Platform; import pl.asie.libzzt.TextVisualData; import pl.asie.libzzt.TextVisualRenderer; @@ -54,7 +53,7 @@ public class ZimaConversionProfile { public static final Property BRIGHTNESS = Property.create("image.colorFilter.brightness", 0.0f, FILTERED_IMAGE); public static final Property CONTRAST = Property.create("image.colorFilter.contrast", 0.0f, FILTERED_IMAGE); public static final Property SATURATION = Property.create("image.colorFilter.saturation", 0.0f, FILTERED_IMAGE); - public static final Property PRESERVE_ASPECT_RATIO = Property.create("image.preserveAspectRatio", true, SCALED_IMAGE); + public static final Property ASPECT_RATIO_PRESERVATION_MODE = Property.create("image.preserveAspectRatio", AspectRatioPreservationMode.SNAP_CHAR, SCALED_IMAGE); public static final Property CROP_LEFT = Property.create("image.crop.left", 0, SCALED_IMAGE); public static final Property CROP_RIGHT = Property.create("image.crop.right", 0, SCALED_IMAGE); @@ -167,7 +166,7 @@ public void updateImage(BufferedImage input) { int width = properties.get(VISUAL_DATA).getCharWidth() * properties.get(CHARS_WIDTH); int height = properties.get(VISUAL_DATA).getCharHeight() * properties.get(CHARS_HEIGHT); - this.scaledImage = ImageUtils.scale(img, width, height, properties.get(PRESERVE_ASPECT_RATIO), properties.get(PLATFORM).isDoubleWide(), Color.BLACK); + this.scaledImage = ImageUtils.scale(img, width, height, properties.get(ASPECT_RATIO_PRESERVATION_MODE), properties.get(PLATFORM).isDoubleWide(), Color.BLACK); localHolder.affect(FILTERED_IMAGE); } diff --git a/src/main/java/pl/asie/zima/image/gui/ZimaFrontendSwing.java b/src/main/java/pl/asie/zima/image/gui/ZimaFrontendSwing.java index 1fcb4d0..46dcfaa 100644 --- a/src/main/java/pl/asie/zima/image/gui/ZimaFrontendSwing.java +++ b/src/main/java/pl/asie/zima/image/gui/ZimaFrontendSwing.java @@ -27,11 +27,8 @@ import pl.asie.libzzt.Platform; import pl.asie.libzzt.TextVisualData; import pl.asie.libzzt.ZOutputStream; -import pl.asie.zima.util.FileUtils; -import pl.asie.zima.util.MZMWriter; -import pl.asie.zima.util.Pair; -import pl.asie.zima.util.Property; -import pl.asie.zima.util.PropertyHolder; +import pl.asie.zima.Version; +import pl.asie.zima.util.*; import pl.asie.zima.image.*; import pl.asie.zima.util.gui.ImageFileChooser; import pl.asie.zima.util.gui.SimpleCanvas; @@ -140,7 +137,7 @@ Platform.MEGAZEUX, new ImageConverterRuleset(List.of()) // "Image" tab private JLabel imageDataLabel; private JCheckBox showInputImageEdit; - private JCheckBox preserveAspectRatioEdit; + private JComboBox aspectRatioEdit; private JSlider brightnessEdit; private JButton brightnessReset; private JSlider contrastEdit; @@ -188,7 +185,7 @@ public ZimaFrontendSwing(byte[] defaultCharset, int[] defaultPalette, String zim this.profile.getProperties().set(ZimaConversionProfile.PLATFORM, Platform.ZZT); this.profile.getProperties().set(ZimaConversionProfile.FAST_RULESET, ImageConverterRulesZZT.RULES_BLOCKS); - this.window = new JFrame("zima :: image converter"); + this.window = new JFrame(Version.getCurrentWindowName("image converter")); this.window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.previewCanvas = new SimpleCanvas(); @@ -313,8 +310,8 @@ public ZimaFrontendSwing(byte[] defaultCharset, int[] defaultPalette, String zim appendTabRow(this.optionsImagePanel, gbc, "Image info", this.imageDataLabel = new JLabel("")); - appendTabRow(this.optionsImagePanel, gbc, "Preserve aspect ratio", this.preserveAspectRatioEdit = new JCheckBox()); - bindPropertyBoolean(this.profile.getProperties(), ZimaConversionProfile.PRESERVE_ASPECT_RATIO, this.preserveAspectRatioEdit); + appendTabRow(this.optionsImagePanel, gbc, "Aspect ratio", this.aspectRatioEdit = createEnumComboBox(AspectRatioPreservationMode.class)); + bindPropertyEnum(this.profile.getProperties(), ZimaConversionProfile.ASPECT_RATIO_PRESERVATION_MODE, this.aspectRatioEdit); appendTabRow(this.optionsImagePanel, gbc, "Brightness", this.brightnessEdit = new JSlider(JSlider.HORIZONTAL, -160, 160, 0), @@ -476,6 +473,7 @@ public ZimaFrontendSwing(byte[] defaultCharset, int[] defaultPalette, String zim this.copyItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); this.pasteItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK)); + this.previewCanvasPane.setBorder(null); this.previewCanvas.setMinimumSize(new Dimension(480, 350)); this.previewCanvasPane.setMinimumSize(this.previewCanvas.getMinimumSize()); this.previewCanvas.setPreferredSize(this.previewCanvas.getMinimumSize()); @@ -942,6 +940,8 @@ public ZimaProfileSettings getSettings() { settings.setContrastReduction(this.profile.getProperties().get(ZimaConversionProfile.TRIX_CONTRAST_REDUCTION)); settings.setAccurateApproximate(this.profile.getProperties().get(ZimaConversionProfile.TRIX_ACCURATE_APPROXIMATE)); + settings.setAspectRatioPreservationMode(this.profile.getProperties().get(ZimaConversionProfile.ASPECT_RATIO_PRESERVATION_MODE)); + return settings; } @@ -1018,11 +1018,29 @@ public void setSettings(ZimaProfileSettings settings) { this.profile.getProperties().set(ZimaConversionProfile.TRIX_ACCURATE_APPROXIMATE, settings.getAccurateApproximate()); } + if (settings.getAspectRatioPreservationMode() != null) { + this.profile.getProperties().set(ZimaConversionProfile.ASPECT_RATIO_PRESERVATION_MODE, settings.getAspectRatioPreservationMode()); + } + rerender(); } // Re-render call listeners + public > JComboBox createEnumComboBox(Class enumClass) { + JComboBox comboBox = new JComboBox<>(); + for (T value : enumClass.getEnumConstants()) { + comboBox.addItem(value); + } + return comboBox; + } + + public > void bindPropertyEnum(PropertyHolder holder, Property property, JComboBox comboBox) { + comboBox.setSelectedItem(property.getDefaultValue()); + comboBox.addItemListener((e) -> holder.set(property, (T) comboBox.getSelectedItem())); + holder.addChangeListener(property, (k, v) -> comboBox.setSelectedItem(v)); + } + public void bindPropertyBoolean(PropertyHolder holder, Property property, JCheckBox checkBox) { Boolean defValue = property.getDefaultValue(); checkBox.setSelected(Objects.equals(defValue, Boolean.TRUE)); diff --git a/src/main/java/pl/asie/zima/image/gui/ZimaProfileSettings.java b/src/main/java/pl/asie/zima/image/gui/ZimaProfileSettings.java index 871c851..b9c2f26 100644 --- a/src/main/java/pl/asie/zima/image/gui/ZimaProfileSettings.java +++ b/src/main/java/pl/asie/zima/image/gui/ZimaProfileSettings.java @@ -20,6 +20,7 @@ import lombok.Data; import pl.asie.zima.image.ElementRule; +import pl.asie.zima.util.AspectRatioPreservationMode; import java.util.List; @@ -37,4 +38,6 @@ public class ZimaProfileSettings { private Boolean colorsBlink; private Float contrastReduction; private Float accurateApproximate; + + private AspectRatioPreservationMode aspectRatioPreservationMode; } diff --git a/src/main/java/pl/asie/zima/util/AspectRatioPreservationMode.java b/src/main/java/pl/asie/zima/util/AspectRatioPreservationMode.java new file mode 100644 index 0000000..e3f8359 --- /dev/null +++ b/src/main/java/pl/asie/zima/util/AspectRatioPreservationMode.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2020, 2021 Adrian Siekierka + * + * This file is part of zima. + * + * zima is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * zima 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with zima. If not, see . + */ +package pl.asie.zima.util; + +public enum AspectRatioPreservationMode { + PRESERVE("Preserve"), + SNAP_CHAR("Snap to character"), + SNAP_CENTER("Snap to center"), + IGNORE("Stretch"); + + private final String label; + + AspectRatioPreservationMode(String label) { + this.label = label; + } + + @Override + public String toString() { + return label; + } +} diff --git a/src/main/java/pl/asie/zima/util/ImageUtils.java b/src/main/java/pl/asie/zima/util/ImageUtils.java index 4d57b74..f855c81 100644 --- a/src/main/java/pl/asie/zima/util/ImageUtils.java +++ b/src/main/java/pl/asie/zima/util/ImageUtils.java @@ -32,28 +32,56 @@ public static float calculateScaleFactor(BufferedImage image, int width, int hei return aspectRatioSrc > aspectRatioDst ? ((float) width / image.getWidth()) : ((float) height / image.getHeight()); } - public static void drawScaled(BufferedImage inputImage, int width, int height, Graphics2D scaledGraphics, boolean preserveAspectRatio) { - drawScaled(inputImage, width, height, scaledGraphics, preserveAspectRatio, false); - } - - public static void drawScaled(BufferedImage inputImage, int width, int height, Graphics2D scaledGraphics, boolean preserveAspectRatio, boolean doubleWide) { - if (preserveAspectRatio) { + public static int[] calculateSize(BufferedImage inputImage, int width, int height, AspectRatioPreservationMode preserveAspectRatio, int charWidth, int charHeight, boolean doubleWide) { + if (preserveAspectRatio == AspectRatioPreservationMode.IGNORE) { + return new int[] { width, height }; + } else { float factor = calculateScaleFactor(inputImage, width * (doubleWide ? 2 : 1), height); int drawWidth = Math.round(inputImage.getWidth() * factor); int drawHeight = Math.round(inputImage.getHeight() * factor); - int xOffset = (width - (drawWidth / (doubleWide ? 2 : 1))) / 2; - int yOffset = (height - drawHeight) / 2; - scaledGraphics.drawImage(inputImage, xOffset, yOffset, (drawWidth / (doubleWide ? 2 : 1)) + xOffset, drawHeight + yOffset, 0, 0, inputImage.getWidth(), inputImage.getHeight(), null); - } else { - scaledGraphics.drawImage(inputImage, 0, 0, width, height, 0, 0, inputImage.getWidth(), inputImage.getHeight(), null); + if (preserveAspectRatio == AspectRatioPreservationMode.SNAP_CHAR) { + if (drawWidth != width) { + drawWidth = Math.round(drawWidth / (float) charWidth) * charWidth; + } else if (drawHeight != height) { + drawHeight = Math.round(drawHeight / (float) charHeight) * charHeight; + } + } else if (preserveAspectRatio == AspectRatioPreservationMode.SNAP_CENTER) { + // one of the axes is guaranteed to be snapped + if (drawWidth != width) { + int oddOffset = (width % (charWidth * 2)) >= charWidth ? charWidth : 0; + drawWidth = Math.round((drawWidth - oddOffset) / (float) (charWidth * 2)) * (charWidth * 2) + oddOffset; + } else if (drawHeight != height) { + int oddOffset = (height % (charHeight * 2)) >= charHeight ? charHeight : 0; + drawHeight = Math.round((drawHeight - oddOffset) / (float) (charHeight * 2)) * (charHeight * 2) + oddOffset; + } + } + return new int[] { drawWidth, drawHeight }; + } + } + + public static void drawScaled(BufferedImage inputImage, int width, int height, Graphics2D scaledGraphics, AspectRatioPreservationMode preserveAspectRatio) { + drawScaled(inputImage, width, height, scaledGraphics, preserveAspectRatio, false); + } + + public static void drawScaled(BufferedImage inputImage, int width, int height, Graphics2D scaledGraphics, AspectRatioPreservationMode preserveAspectRatio, boolean doubleWide) { + // TODO: pass char width/height as argument + int charWidth = doubleWide ? 16 : 8; + int charHeight = 14; + int[] drawSize = calculateSize(inputImage, width, height, preserveAspectRatio, charWidth, charHeight, doubleWide); + int xOffset = (width - (drawSize[0] / (doubleWide ? 2 : 1))) / 2; + int yOffset = (height - drawSize[1]) / 2; + if (preserveAspectRatio == AspectRatioPreservationMode.SNAP_CENTER || preserveAspectRatio == AspectRatioPreservationMode.SNAP_CHAR) { + xOffset = Math.round(xOffset / (float) charWidth) * charWidth; + yOffset = Math.round(yOffset / (float) charHeight) * charHeight; } + scaledGraphics.drawImage(inputImage, xOffset, yOffset, (drawSize[0] / (doubleWide ? 2 : 1)) + xOffset, drawSize[1] + yOffset, 0, 0, inputImage.getWidth(), inputImage.getHeight(), null); } - public static BufferedImage scale(BufferedImage inputImage, int width, int height, boolean preserveAspectRatio, Color fillColor) { + public static BufferedImage scale(BufferedImage inputImage, int width, int height, AspectRatioPreservationMode preserveAspectRatio, Color fillColor) { return scale(inputImage, width, height, preserveAspectRatio, false, fillColor); } - public static BufferedImage scale(BufferedImage inputImage, int width, int height, boolean preserveAspectRatio, boolean doubleWide, Color fillColor) { + public static BufferedImage scale(BufferedImage inputImage, int width, int height, AspectRatioPreservationMode preserveAspectRatio, boolean doubleWide, Color fillColor) { if (inputImage.getWidth() == width && inputImage.getHeight() == height) { return inputImage; } diff --git a/src/main/java/pl/asie/zima/util/gui/ImageFileChooser.java b/src/main/java/pl/asie/zima/util/gui/ImageFileChooser.java index 302f55d..7434d99 100644 --- a/src/main/java/pl/asie/zima/util/gui/ImageFileChooser.java +++ b/src/main/java/pl/asie/zima/util/gui/ImageFileChooser.java @@ -25,6 +25,7 @@ import pl.asie.libzzt.TextVisualRenderer; import pl.asie.libzzt.World; import pl.asie.libzzt.ZInputStream; +import pl.asie.zima.util.AspectRatioPreservationMode; import pl.asie.zima.util.ImageUtils; import javax.imageio.ImageIO; @@ -127,7 +128,7 @@ public void paintComponent(Graphics graphics) { g2d.drawImage(image, xPos, yPos, null); } else { g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - ImageUtils.drawScaled(image, (int) size.getWidth(), (int) size.getHeight(), g2d, true); + ImageUtils.drawScaled(image, (int) size.getWidth(), (int) size.getHeight(), g2d, AspectRatioPreservationMode.PRESERVE); } g2d.dispose(); } @@ -151,7 +152,7 @@ public ImageCache(File imageFile) { public void run() { this.image = imageGetterFunction.apply(imageFile); - BufferedImage scaledIconImage = ImageUtils.scale(this.image, 16, 16, true, null); + BufferedImage scaledIconImage = ImageUtils.scale(this.image, 16, 16, AspectRatioPreservationMode.PRESERVE, null); this.icon.setImage(scaledIconImage); ImageFileChooser.this.repaint(); } diff --git a/src/test/java/pl/asie/zima/util/ImageUtilsAspectRatioTest.java b/src/test/java/pl/asie/zima/util/ImageUtilsAspectRatioTest.java new file mode 100644 index 0000000..2fbc3b5 --- /dev/null +++ b/src/test/java/pl/asie/zima/util/ImageUtilsAspectRatioTest.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2020, 2021 Adrian Siekierka + * + * This file is part of zima. + * + * zima is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * zima 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with zima. If not, see . + */ +package pl.asie.zima.util; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.awt.image.BufferedImage; + +public class ImageUtilsAspectRatioTest { + private BufferedImage image(int width, int height) { + return new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); + } + + @Test + public void calculateSizeIgnoreTest() { + Assertions.assertArrayEquals(new int[] { 640, 350 }, + ImageUtils.calculateSize( + image(100, 100), + 640, 350, + AspectRatioPreservationMode.IGNORE, + 8, 14, false + ) + ); + } + + @Test + public void calculateSizePreserveTest() { + Assertions.assertArrayEquals(new int[] { 350, 350 }, + ImageUtils.calculateSize( + image(100, 100), + 640, 350, + AspectRatioPreservationMode.PRESERVE, + 8, 14, false + ) + ); + } + + @Test + public void calculateSizeSnapCharTest() { + Assertions.assertArrayEquals(new int[] { 352, 350 }, + ImageUtils.calculateSize( + image(100, 100), + 640, 350, + AspectRatioPreservationMode.SNAP_CHAR, + 8, 14, false + ) + ); + + Assertions.assertArrayEquals(new int[] { 352, 336 }, + ImageUtils.calculateSize( + image(100, 97), + 352, 630, + AspectRatioPreservationMode.SNAP_CHAR, + 8, 14, false + ) + ); + } + + @Test + public void calculateSizeSnapCenterTest() { + Assertions.assertArrayEquals(new int[] { 344, 350 }, + ImageUtils.calculateSize( + image(100, 100), + 632, 350, + AspectRatioPreservationMode.SNAP_CENTER, + 8, 14, false + ) + ); + + Assertions.assertArrayEquals(new int[] { 352, 350 }, + ImageUtils.calculateSize( + image(100, 97), + 352, 630, + AspectRatioPreservationMode.SNAP_CENTER, + 8, 14, false + ) + ); + } +}