From 960f70507162807f468144a74a07d2388b13a3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Thu, 15 May 2025 22:39:27 +0200 Subject: [PATCH] Filters strictly increasing 0f-1f values for Java gradient. --- .../flash/types/filters/FILTER.java | 54 ++++++++++++++++++- .../types/filters/GRADIENTBEVELFILTER.java | 19 ++----- .../types/filters/GRADIENTGLOWFILTER.java | 20 ++----- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/FILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/FILTER.java index 348592be5..011fd653c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/FILTER.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/FILTER.java @@ -44,11 +44,12 @@ public abstract class FILTER implements Serializable { public int id; /** - * FILTER is enabled. Used internally by Simple editor GUI. Not a real SWF field. + * FILTER is enabled. Used internally by Simple editor GUI. Not a real SWF + * field. */ @Internal public boolean enabled = true; - + /** * Constructor * @@ -60,6 +61,7 @@ public abstract class FILTER implements Serializable { /** * Applies filter to image. + * * @param src Image to apply filter to * @param zoom Zoom level * @param srcX X coordinate of the source rectangle @@ -72,18 +74,21 @@ public abstract class FILTER implements Serializable { /** * Gets delta X + * * @return Delta X */ public abstract double getDeltaX(); /** * Gets delta Y + * * @return Delta Y */ public abstract double getDeltaY(); /** * Converts filter to SVG. + * * @param document Document * @param filtersElement Filters element * @param exporter SVG exporter @@ -94,6 +99,7 @@ public abstract class FILTER implements Serializable { /** * Converts drop shadow to SVG. + * * @param distance Distance * @param angle Angle * @param dropShadowColor Drop shadow color @@ -254,6 +260,7 @@ public abstract class FILTER implements Serializable { /** * Converts blur to SVG. + * * @param blurX Blur X * @param blurY Blur Y * @param iterations Iterations @@ -307,4 +314,47 @@ public abstract class FILTER implements Serializable { return blurSvg(blurX, blurY, iterations - 1, document, filtersElement, exporter, result); } + + /** + * Converts gradient ratios to Java format float ratios. + * @param input 0-255 values + * @return 0f - 1f values, strictly increasing + */ + public static float[] convertRatiosToJavaGradient(int[] input) { + int n = input.length; + float[] output = new float[n]; + final float max = 1.0f; + final float epsilon = 0.000001f; + + for (int i = 0; i < n; i++) { + output[i] = input[i] / 255f; + } + + for (int i = 1; i < n; i++) { + if (output[i] <= output[i - 1]) { + float proposed = output[i - 1] + epsilon; + + if (proposed > max) { + int j = i - 1; + while (j >= 0 && output[j] >= (max - (i - j) * epsilon)) { + j--; + } + + if (j < 0) { + for (int k = i - (i); k <= i; k++) { + output[k] = max - (i - k) * epsilon; + } + } else { + for (int k = j + 1; k <= i; k++) { + output[k] = output[k - 1] + epsilon; + } + } + } else { + output[i] = proposed; + } + } + } + + return output; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java index 4a9cdfd5e..eb242d510 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTBEVELFILTER.java @@ -117,25 +117,12 @@ public class GRADIENTBEVELFILTER extends FILTER { @Override public SerializableImage apply(SerializableImage src, double zoom, int srcX, int srcY, int srcW, int srcH) { - List colors = new ArrayList<>(); - List ratios = new ArrayList<>(); - float lastRatioF = 0f; + Color[] colorsArr = new Color[gradientColors.length]; for (int i = 0; i < gradientColors.length; i++) { - float ratioF = gradientRatio[i] / 255f; - if ((i > 0) && (gradientRatio[i - 1] == gradientRatio[i])) { - ratioF = lastRatioF + 0.000001f; - } - colors.add(gradientColors[i].toColor()); - ratios.add(ratioF); - lastRatioF = ratioF; + colorsArr[i] = gradientColors[i].toColor(); } + float[] ratiosArr = convertRatiosToJavaGradient(gradientRatio); - float[] ratiosArr = new float[ratios.size()]; - for (int i = 0; i < ratios.size(); i++) { - ratiosArr[i] = ratios.get(i); - } - - Color[] colorsArr = colors.toArray(new Color[colors.size()]); int type = Filtering.INNER; if (onTop && !innerShadow) { type = Filtering.FULL; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java index 0e94cc089..2cd814530 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/GRADIENTGLOWFILTER.java @@ -119,18 +119,12 @@ public class GRADIENTGLOWFILTER extends FILTER { @Override public SerializableImage apply(SerializableImage src, double zoom, int srcX, int srcY, int srcW, int srcH) { - List colors = new ArrayList<>(); - List ratios = new ArrayList<>(); - float lastRatioF = 0f; + Color[] colorsArr = new Color[gradientColors.length]; for (int i = 0; i < gradientColors.length; i++) { - float ratioF = gradientRatio[i] / 255f; - if ((i > 0) && (gradientRatio[i - 1] == gradientRatio[i])) { - ratioF = lastRatioF + 0.000001f; - } - colors.add(gradientColors[i].toColor()); - ratios.add(ratioF); - lastRatioF = ratioF; + colorsArr[i] = gradientColors[i].toColor(); } + float[] ratiosArr = convertRatiosToJavaGradient(gradientRatio); + int type = Filtering.INNER; if (onTop && !innerShadow) { type = Filtering.FULL; @@ -138,11 +132,7 @@ public class GRADIENTGLOWFILTER extends FILTER { type = Filtering.OUTER; } - float[] ratiosAr = new float[ratios.size()]; - for (int i = 0; i < ratios.size(); i++) { - ratiosAr[i] = ratios.get(i); - } - return Filtering.gradientGlow(src, (int) Math.round(blurX * zoom), (int) Math.round(blurY * zoom), (int) (angle * 180 / Math.PI), distance * zoom, colors.toArray(new Color[colors.size()]), ratiosAr, type, passes, strength, knockout, compositeSource); + return Filtering.gradientGlow(src, (int) Math.round(blurX * zoom), (int) Math.round(blurY * zoom), (int) (angle * 180 / Math.PI), distance * zoom, colorsArr, ratiosArr, type, passes, strength, knockout, compositeSource); } @Override