mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-08 18:46:12 +00:00
faster imageToShape
This commit is contained in:
@@ -149,6 +149,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -861,12 +862,12 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
}
|
||||
}
|
||||
|
||||
/*preload shape tags*/
|
||||
for (Tag tag : tags) {
|
||||
if (tag instanceof ShapeTag) {
|
||||
((ShapeTag) tag).getShapes();
|
||||
}
|
||||
}
|
||||
/*preload shape tags
|
||||
for (Tag tag : tags) {
|
||||
if (tag instanceof ShapeTag) {
|
||||
((ShapeTag) tag).getShapes();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2810,9 +2811,32 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
return modified;
|
||||
}
|
||||
|
||||
public void removeTag(Tag t, boolean removeDependencies) {
|
||||
Timelined timelined = t.getTimelined();
|
||||
if (t instanceof ShowFrameTag || ShowFrameTag.isNestedTagType(t.getId())) {
|
||||
public void removeTags(Collection<Tag> tags, boolean removeDependencies) {
|
||||
Set<Timelined> timelineds = new HashSet<>();
|
||||
for (Tag tag : tags) {
|
||||
Timelined timelined = tag.getTimelined();
|
||||
timelineds.add(timelined);
|
||||
removeTagInternal(timelined, tag, removeDependencies);
|
||||
}
|
||||
|
||||
for (Timelined timelined : timelineds) {
|
||||
resetTimelines(timelined);
|
||||
}
|
||||
|
||||
updateCharacters();
|
||||
clearImageCache();
|
||||
}
|
||||
|
||||
public void removeTag(Tag tag, boolean removeDependencies) {
|
||||
Timelined timelined = tag.getTimelined();
|
||||
removeTagInternal(timelined, tag, removeDependencies);
|
||||
resetTimelines(timelined);
|
||||
updateCharacters();
|
||||
clearImageCache();
|
||||
}
|
||||
|
||||
private void removeTagInternal(Timelined timelined, Tag tag, boolean removeDependencies) {
|
||||
if (tag instanceof ShowFrameTag || ShowFrameTag.isNestedTagType(tag.getId())) {
|
||||
List<Tag> tags;
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
@@ -2820,7 +2844,7 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
} else {
|
||||
tags = this.tags;
|
||||
}
|
||||
tags.remove(t);
|
||||
tags.remove(tag);
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
sprite.setModified(true);
|
||||
@@ -2829,18 +2853,15 @@ public final class SWF implements SWFContainerItem, Timelined {
|
||||
} else {
|
||||
// timeline should be always the swf here
|
||||
if (removeDependencies) {
|
||||
removeTagWithDependenciesFromTimeline(t, timelined.getTimeline());
|
||||
removeTagWithDependenciesFromTimeline(tag, timelined.getTimeline());
|
||||
if (timelined instanceof DefineSpriteTag) {
|
||||
DefineSpriteTag sprite = (DefineSpriteTag) timelined;
|
||||
sprite.setModified(true);
|
||||
}
|
||||
} else {
|
||||
removeTagFromTimeline(t, timeline);
|
||||
removeTagFromTimeline(tag, timeline);
|
||||
}
|
||||
}
|
||||
resetTimelines(timelined);
|
||||
updateCharacters();
|
||||
clearImageCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import java.awt.Component;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Area;
|
||||
@@ -65,7 +66,7 @@ public class Helper {
|
||||
public static String newLine = System.getProperty("line.separator");
|
||||
|
||||
public static String decompilationErrorAdd = null;
|
||||
|
||||
|
||||
private static final Map<String, Area> shapeCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -898,7 +899,7 @@ public class Helper {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static Shape imageToShape(BufferedImage image) {
|
||||
public static Shape imageToShapeOld(BufferedImage image) {
|
||||
Area area = new Area();
|
||||
Rectangle rectangle = new Rectangle();
|
||||
int y1, y2;
|
||||
@@ -909,12 +910,12 @@ public class Helper {
|
||||
int type = image.getType();
|
||||
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
|
||||
imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
} else{
|
||||
} else {
|
||||
imgData = image.getRGB(0, 0, width, height, null, 0, width);
|
||||
}
|
||||
|
||||
|
||||
BitSet bs = new BitSet(width * height);
|
||||
bs.set(type);
|
||||
bs.set(type);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int idx = width * y + x;
|
||||
@@ -923,12 +924,12 @@ public class Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String key = byteArrayToBase64String(bs.toByteArray());
|
||||
if (shapeCache.containsKey(key)) {
|
||||
return shapeCache.get(key);
|
||||
}
|
||||
|
||||
|
||||
for (int x = 0; x < width; x++) {
|
||||
y1 = Integer.MAX_VALUE;
|
||||
y2 = -1;
|
||||
@@ -957,7 +958,159 @@ public class Helper {
|
||||
shapeCache.put(key, area);
|
||||
return area;
|
||||
}
|
||||
|
||||
|
||||
public static Shape imageToShape(BufferedImage image) {
|
||||
Area area = new Area();
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
|
||||
int[] imgData;
|
||||
int type = image.getType();
|
||||
if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB) {
|
||||
imgData = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
|
||||
} else {
|
||||
imgData = image.getRGB(0, 0, width, height, null, 0, width);
|
||||
}
|
||||
|
||||
BitSet bs = new BitSet(width * height);
|
||||
bs.set(type);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
int idx = width * y + x;
|
||||
if ((imgData[idx] >>> 24) > 0) {
|
||||
bs.set(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String key = byteArrayToBase64String(bs.toByteArray());
|
||||
if (shapeCache.containsKey(key)) {
|
||||
return shapeCache.get(key);
|
||||
}
|
||||
|
||||
BitSet bsArea = new BitSet(width * height);
|
||||
boolean modified = true;
|
||||
|
||||
List<Integer> leftCoordsX = new ArrayList<>();
|
||||
List<Integer> leftCoordsY = new ArrayList<>();
|
||||
List<Integer> rightCoordsX = new ArrayList<>();
|
||||
List<Integer> rightCoordsY = new ArrayList<>();
|
||||
while (modified) {
|
||||
modified = false;
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
int idx = width * y + x;
|
||||
if ((imgData[idx] >>> 24) > 0 && !bsArea.get(idx)) {
|
||||
leftCoordsX.clear();
|
||||
leftCoordsY.clear();
|
||||
rightCoordsX.clear();
|
||||
rightCoordsY.clear();
|
||||
int leftX = x;
|
||||
int rightX = findRight(imgData, x, y, width);
|
||||
leftCoordsX.add(leftX);
|
||||
leftCoordsY.add(y);
|
||||
rightCoordsX.add(rightX);
|
||||
rightCoordsY.add(y);
|
||||
setBitSet(bsArea, leftX, rightX, y, width);
|
||||
int y2 = y + 1;
|
||||
while (y2 < height) {
|
||||
leftCoordsX.add(leftX);
|
||||
leftCoordsY.add(y2);
|
||||
rightCoordsX.add(rightX);
|
||||
rightCoordsY.add(y2);
|
||||
|
||||
int leftX2 = findFirst(imgData, leftX, rightX, y2, width);
|
||||
if (leftX2 == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int rightX2 = findRight(imgData, leftX2, y2, width);
|
||||
|
||||
if (leftX2 != leftX) {
|
||||
leftCoordsX.add(leftX2);
|
||||
leftCoordsY.add(y2);
|
||||
}
|
||||
|
||||
if (rightX2 != rightX) {
|
||||
rightCoordsX.add(rightX2);
|
||||
rightCoordsY.add(y2);
|
||||
}
|
||||
|
||||
leftX = leftX2;
|
||||
rightX = rightX2;
|
||||
|
||||
setBitSet(bsArea, leftX, rightX, y2, width);
|
||||
y2++;
|
||||
}
|
||||
|
||||
int cnt = leftCoordsX.size() + rightCoordsX.size();
|
||||
int[] xCoords = new int[cnt];
|
||||
int[] yCoords = new int[cnt];
|
||||
for (int i = 0; i < rightCoordsX.size(); i++) {
|
||||
xCoords[i] = rightCoordsX.get(i);
|
||||
yCoords[i] = rightCoordsY.get(i);
|
||||
}
|
||||
|
||||
int offset = rightCoordsX.size();
|
||||
for (int i = 0; i < leftCoordsX.size(); i++) {
|
||||
int idx2 = leftCoordsX.size() - i - 1;
|
||||
xCoords[i + offset] = leftCoordsX.get(idx2);
|
||||
yCoords[i + offset] = leftCoordsY.get(idx2);
|
||||
}
|
||||
|
||||
Area area2 = new Area(new Polygon(xCoords, yCoords, xCoords.length));
|
||||
area.add(area2);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shapeCache.put(key, area);
|
||||
return area;
|
||||
}
|
||||
|
||||
private static void setBitSet(BitSet bitSet, int x1, int x2, int y, int width) {
|
||||
int idx = width * y + x1;
|
||||
int idx2 = width * y + x2;
|
||||
for (; idx < idx2; idx++) {
|
||||
bitSet.set(idx);
|
||||
}
|
||||
}
|
||||
|
||||
private static int findFirst(int[] imgData, int x1, int x2, int y, int width) {
|
||||
int idx = width * y + x1;
|
||||
if ((imgData[idx] >>> 24) > 0) {
|
||||
while (x1 > 0 && (imgData[idx - 1] >>> 24) > 0) {
|
||||
x1--;
|
||||
idx--;
|
||||
}
|
||||
return x1;
|
||||
}
|
||||
|
||||
int idx2 = width * y + x2;
|
||||
for (; idx < idx2; idx++) {
|
||||
if ((imgData[idx] >>> 24) > 0) {
|
||||
return x1;
|
||||
}
|
||||
|
||||
x1++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static int findRight(int[] imgData, int x, int y, int width) {
|
||||
int result = x;
|
||||
int idx = width * y + x;
|
||||
while ((imgData[idx] >>> 24) > 0 && result < width) {
|
||||
result++;
|
||||
idx++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void clearShapeCache() {
|
||||
shapeCache.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user