mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-27 09:40:44 +00:00
Fixed: #2596 Scaling images in relation to antialias conflation
This commit is contained in:
@@ -177,6 +177,7 @@ import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.Cache;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.ImageResizer;
|
||||
import com.jpexs.helpers.ImmediateFuture;
|
||||
import com.jpexs.helpers.NulStream;
|
||||
import com.jpexs.helpers.ProgressListener;
|
||||
@@ -189,6 +190,7 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -5025,12 +5027,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
viewRect.yMax *= aaScale;
|
||||
|
||||
timeline.toImage(frame, time, renderContext, image, image, false, m, new Matrix(), m, colorTransform, zoom * aaScale, true, viewRect, viewRect, m, true, Timeline.DRAW_MODE_ALL, 0, canUseSmoothing, new ArrayList<>(), aaScale);
|
||||
|
||||
SerializableImage img2 = new SerializableImage(image.getWidth() / aaScale, image.getHeight() / aaScale, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||
img2.fillTransparent();
|
||||
Graphics2D g2 = (Graphics2D) img2.getGraphics();
|
||||
g2.drawImage(image.getBufferedImage().getScaledInstance(image.getWidth() / aaScale, image.getHeight() / aaScale, Image.SCALE_SMOOTH), 0, 0, null);
|
||||
image = img2;
|
||||
|
||||
if (aaScale > 1) {
|
||||
image = new SerializableImage(ImageResizer.resizeImage(image.getBufferedImage(), image.getWidth() / aaScale, image.getHeight() / aaScale, RenderingHints.VALUE_INTERPOLATION_BICUBIC, true));
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.ImageResizer;
|
||||
import com.jpexs.helpers.Path;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
@@ -52,6 +53,7 @@ import dev.matrixlab.webp4j.WebPCodec;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -188,12 +190,8 @@ public class MorphShapeExporter {
|
||||
BufferedImage bim = img.getBufferedImage();
|
||||
|
||||
if (realAaScale > 1) {
|
||||
SerializableImage img2 = new SerializableImage(((newWidth - 1) / realAaScale) + 1,
|
||||
((newHeight - 1) / realAaScale) + 1, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
img2.fillTransparent();
|
||||
Graphics g2 = img2.getGraphics();
|
||||
g2.drawImage(img.getBufferedImage().getScaledInstance(img2.getWidth(), img2.getHeight(), Image.SCALE_SMOOTH), 0, 0, null);
|
||||
bim = img2.getBufferedImage();
|
||||
bim = ImageResizer.resizeImage(bim, ((newWidth - 1) / realAaScale) + 1,
|
||||
((newHeight - 1) / realAaScale) + 1, RenderingHints.VALUE_INTERPOLATION_BICUBIC, true);
|
||||
}
|
||||
|
||||
if (settings.mode == MorphShapeExportMode.PNG_START_END) {
|
||||
@@ -229,12 +227,8 @@ public class MorphShapeExporter {
|
||||
bim = img.getBufferedImage();
|
||||
|
||||
if (realAaScale > 1) {
|
||||
SerializableImage img2 = new SerializableImage(((newWidth - 1) / realAaScale) + 1,
|
||||
((newHeight - 1) / realAaScale) + 1, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
img2.fillTransparent();
|
||||
Graphics g2 = img2.getGraphics();
|
||||
g2.drawImage(img.getBufferedImage().getScaledInstance(img2.getWidth(), img2.getHeight(), Image.SCALE_SMOOTH), 0, 0, null);
|
||||
bim = img2.getBufferedImage();
|
||||
bim = ImageResizer.resizeImage(bim, ((newWidth - 1) / realAaScale) + 1,
|
||||
((newHeight - 1) / realAaScale) + 1, RenderingHints.VALUE_INTERPOLATION_BICUBIC, true);
|
||||
}
|
||||
|
||||
if (settings.mode == MorphShapeExportMode.PNG_START_END) {
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.ImageResizer;
|
||||
import com.jpexs.helpers.Path;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
@@ -50,6 +51,10 @@ import dev.matrixlab.webp4j.WebPCodec;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.AffineTransformOp;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -72,8 +77,8 @@ import java.util.logging.Logger;
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ShapeExporter {
|
||||
|
||||
public class ShapeExporter {
|
||||
|
||||
public List<File> exportShapes(AbortRetryIgnoreHandler handler, final String outdir, final SWF swf, ReadOnlyTagList tags, final ShapeExportSettings settings, EventListener evl, double unzoom, int aaScale) throws IOException, InterruptedException {
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (CancellableWorker.isInterrupted()) {
|
||||
@@ -147,12 +152,8 @@ public class ShapeExporter {
|
||||
|
||||
BufferedImage bim = img.getBufferedImage();
|
||||
if (realAaScale > 1) {
|
||||
SerializableImage img2 = new SerializableImage(((newWidth - 1) / realAaScale) + 1,
|
||||
((newHeight - 1) / realAaScale) + 1, SerializableImage.TYPE_INT_ARGB_PRE);
|
||||
img2.fillTransparent();
|
||||
Graphics g2 = img2.getGraphics();
|
||||
g2.drawImage(img.getBufferedImage().getScaledInstance(img2.getWidth(), img2.getHeight(), Image.SCALE_SMOOTH), 0, 0, null);
|
||||
bim = img2.getBufferedImage();
|
||||
bim = ImageResizer.resizeImage(bim, ((newWidth - 1) / realAaScale) + 1,
|
||||
((newHeight - 1) / realAaScale) + 1, RenderingHints.VALUE_INTERPOLATION_BICUBIC, true);
|
||||
}
|
||||
|
||||
if (settings.mode == ShapeExportMode.PNG) {
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.jpexs.helpers;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* Image resizer. Correct downscaling of images.
|
||||
*
|
||||
* @author JPEXS
|
||||
*
|
||||
* Based on
|
||||
* https://web.archive.org/web/20150504200847/https://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html
|
||||
*/
|
||||
public class ImageResizer {
|
||||
|
||||
/**
|
||||
* Returns a scaled instance of the provided {@code BufferedImage}.
|
||||
*
|
||||
*
|
||||
* @param img the original image to be scaled
|
||||
* @param targetWidth the desired width of the scaled instance, in pixels
|
||||
* @param targetHeight the desired height of the scaled instance, in pixels
|
||||
* @param hint one of the rendering hints that corresponds to
|
||||
* {@code RenderingHints.KEY_INTERPOLATION} (e.g.
|
||||
* {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
|
||||
* {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
|
||||
* {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
|
||||
* @param higherQuality if true, this method will use a multi-step scaling
|
||||
* technique that provides higher quality than the usual one-step technique
|
||||
* (only useful in downscaling cases, where {@code targetWidth} or
|
||||
* {@code targetHeight} is smaller than the original dimensions, and
|
||||
* generally only when the {@code BILINEAR} hint is specified)
|
||||
* @return a scaled version of the original {@code BufferedImage}
|
||||
*/
|
||||
public static BufferedImage resizeImage(BufferedImage img,
|
||||
int targetWidth,
|
||||
int targetHeight,
|
||||
Object hint,
|
||||
boolean higherQuality) {
|
||||
int type = img.getType();
|
||||
BufferedImage ret = (BufferedImage) img;
|
||||
int w;
|
||||
int h;
|
||||
if (higherQuality) {
|
||||
// Use multi-step technique: start with original size, then
|
||||
// scale down in multiple passes with drawImage()
|
||||
// until the target size is reached
|
||||
w = img.getWidth();
|
||||
h = img.getHeight();
|
||||
} else {
|
||||
// Use one-step technique: scale directly from original
|
||||
// size to target size with a single drawImage() call
|
||||
w = targetWidth;
|
||||
h = targetHeight;
|
||||
}
|
||||
|
||||
do {
|
||||
if (higherQuality && w > targetWidth) {
|
||||
w /= 2;
|
||||
if (w < targetWidth) {
|
||||
w = targetWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (higherQuality && h > targetHeight) {
|
||||
h /= 2;
|
||||
if (h < targetHeight) {
|
||||
h = targetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage tmp = new BufferedImage(w, h, type);
|
||||
Graphics2D g2 = tmp.createGraphics();
|
||||
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
|
||||
g2.drawImage(ret, 0, 0, w, h, null);
|
||||
g2.dispose();
|
||||
|
||||
ret = tmp;
|
||||
} while (w != targetWidth || h != targetHeight);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user