Filters strictly increasing 0f-1f values for Java gradient.

This commit is contained in:
Jindra Petřík
2025-05-15 22:39:27 +02:00
parent 03da8d6fde
commit 960f705071
3 changed files with 60 additions and 33 deletions
@@ -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;
}
}
@@ -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<Color> colors = new ArrayList<>();
List<Float> 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;
@@ -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<Color> colors = new ArrayList<>();
List<Float> 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