diff --git a/lib/gif.jar b/lib/gif.jar index ec517a483..a9b48c437 100644 Binary files a/lib/gif.jar and b/lib/gif.jar differ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index 4b70d9108..5dde7f0ae 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -444,7 +444,6 @@ public class FrameExporter { AnimatedGifEncoder encoder = new AnimatedGifEncoder(); encoder.setRepeat(0); // repeat forever - encoder.setTransparent(new Color(0, 0, 0, 0)); encoder.start(file.getAbsolutePath()); encoder.setDelay(1000 / frameRate); while (images.hasNext()) { diff --git a/libsrc/gif/src/net/weiner/kevin/AnimatedGifEncoder.java b/libsrc/gif/src/net/weiner/kevin/AnimatedGifEncoder.java index 820846dd6..bbc08ca56 100644 --- a/libsrc/gif/src/net/weiner/kevin/AnimatedGifEncoder.java +++ b/libsrc/gif/src/net/weiner/kevin/AnimatedGifEncoder.java @@ -3,7 +3,7 @@ package net.weiner.kevin; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; -import java.awt.image.DataBufferByte; +import java.awt.image.DataBufferInt; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -40,7 +40,7 @@ public class AnimatedGifEncoder { protected Color transparent = null; // transparent color if given - protected int transIndex; // transparent index in color table + protected int transIndex = -1; // transparent index in color table protected int repeat = -1; // no repeat @@ -50,10 +50,6 @@ public class AnimatedGifEncoder { protected OutputStream out; - protected BufferedImage image; // current frame - - protected byte[] pixels; // BGR byte array from frame - protected byte[] indexedPixels; // converted frame indexed to palette protected int colorDepth; // number of bit planes @@ -153,9 +149,9 @@ public class AnimatedGifEncoder { // use first frame's size setSize(im.getWidth(), im.getHeight()); } - image = im; - getImagePixels(); // convert to correct format if necessary - analyzePixels(); // build color table & map pixels + + int[] pixels = getImagePixels(im); // convert to correct format if necessary + analyzePixels(pixels); // build color table & map pixels if (firstFrame) { writeLSD(); // logical screen descriptior writePalette(); // global color table @@ -199,10 +195,8 @@ public class AnimatedGifEncoder { } // reset for subsequent use - transIndex = 0; + transIndex = -1; out = null; - image = null; - pixels = null; indexedPixels = null; colorTab = null; closeStream = false; @@ -312,33 +306,62 @@ public class AnimatedGifEncoder { /** * Analyzes image colors and creates color map. */ - protected void analyzePixels() { - int len = pixels.length; - int nPix = len / 3; + protected void analyzePixels(int[] pixels) { + int nPix = pixels.length; + int len = nPix * 3; indexedPixels = new byte[nPix]; NeuQuant nq = new NeuQuant(pixels, len, sample); + // initialize quantizer colorTab = nq.process(); // create reduced palette - // convert map from BGR to RGB - for (int i = 0; i < colorTab.length; i += 3) { - byte temp = colorTab[i]; - colorTab[i] = colorTab[i + 2]; - colorTab[i + 2] = temp; - usedEntry[i / 3] = false; + + for (int i = 0; i < usedEntry.length; i++) { + usedEntry[i] = false; } + // map image pixels to new palette - int k = 0; for (int i = 0; i < nPix; i++) { - int index = nq.map(pixels[k++] & 0xff, pixels[k++] & 0xff, pixels[k++] & 0xff); + int pixel = pixels[i]; + int index = nq.map(pixel & 0xff, (pixel >> 8) & 0xff, (pixel >> 16) & 0xff); usedEntry[index] = true; indexedPixels[i] = (byte) index; } - pixels = null; colorDepth = 8; palSize = 7; + + int unusedIndex = -1; + for (int i = 0; i < usedEntry.length; i++) { + if (!usedEntry[i]) { + unusedIndex = i; + break; + } + } + + int transIdx; + // get closest match to transparent color if specified if (transparent != null) { transIndex = findClosest(transparent); + transIdx = transIndex; + } else { + if (unusedIndex != -1) { + transIdx = (byte) unusedIndex; + } else { + transIdx = findClosest(Color.black); + } + + boolean transp = false; + for (int i = 0; i < nPix; i++) { + int pixel = pixels[i]; + if (((pixel >> 24) & 0xff) < 0x80) { + transp = true; + indexedPixels[i] = (byte) transIdx; + } + } + + if (transp) { + transIndex = transIdx; + } } } @@ -373,19 +396,24 @@ public class AnimatedGifEncoder { /** * Extracts image pixels into byte array "pixels" + * + * @param image current frame + * @return ARGB int array from frame */ - protected void getImagePixels() { + protected int[] getImagePixels(BufferedImage image) { int w = image.getWidth(); int h = image.getHeight(); int type = image.getType(); - if ((w != width) || (h != height) || (type != BufferedImage.TYPE_3BYTE_BGR)) { + if ((w != width) || (h != height) || (type != BufferedImage.TYPE_INT_ARGB)) { // create new image with right size/format - BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); + BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = temp.createGraphics(); g.drawImage(image, 0, 0, null); image = temp; } - pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); + + int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); + return pixels; } /** @@ -396,7 +424,7 @@ public class AnimatedGifEncoder { out.write(0xf9); // GCE label out.write(4); // data block size int transp, disp; - if (transparent == null) { + if (transIndex == -1) { transp = 0; disp = 0; // dispose = no action } else { @@ -415,7 +443,7 @@ public class AnimatedGifEncoder { transp); // 8 transparency flag writeShort(delay); // delay x 1/100 sec - out.write(transIndex); // transparent color index + out.write(transIndex == -1 ? 0 : transIndex); // transparent color index out.write(0); // block terminator } diff --git a/libsrc/gif/src/net/weiner/kevin/NeuQuant.java b/libsrc/gif/src/net/weiner/kevin/NeuQuant.java index 0209b4557..6f69f0cc0 100644 --- a/libsrc/gif/src/net/weiner/kevin/NeuQuant.java +++ b/libsrc/gif/src/net/weiner/kevin/NeuQuant.java @@ -120,7 +120,7 @@ public class NeuQuant { /* * Types and Global Variables -------------------------- */ - protected byte[] thepicture; /* the input image itself */ + protected int[] thepicture; /* the input image itself */ protected int lengthcount; /* lengthcount = H*W*3 */ @@ -130,7 +130,6 @@ public class NeuQuant { // typedef int pixel[4]; /* BGRc */ - protected int[][] network; /* the network itself - [netsize][4] */ @@ -150,7 +149,7 @@ public class NeuQuant { * Initialise network in range (0,0,0) to (255,255,255) and set parameters * ----------------------------------------------------------------------- */ - public NeuQuant(byte[] thepic, int len, int sample) { + public NeuQuant(int[] thepic, int len, int sample) { int i; int[] p; @@ -179,9 +178,11 @@ public class NeuQuant { int k = 0; for (int i = 0; i < netsize; i++) { int j = index[i]; - map[k++] = (byte) (network[j][0]); - map[k++] = (byte) (network[j][1]); + + // convert map from BGR to RGB map[k++] = (byte) (network[j][2]); + map[k++] = (byte) (network[j][1]); + map[k++] = (byte) (network[j][0]); } return map; } @@ -244,6 +245,7 @@ public class NeuQuant { netindex[previouscol] = (startpos + maxnetpos) >> 1; for (j = previouscol + 1; j < 256; j++) { netindex[j] = maxnetpos; /* really 256 */ + } } @@ -254,7 +256,7 @@ public class NeuQuant { int i, j, b, g, r; int radius, rad, alpha, step, delta, samplepixels; - byte[] p; + int[] p; int pix, lim; if (lengthcount < minpicturebytes) { @@ -277,7 +279,7 @@ public class NeuQuant { radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad)); } - // fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad); + // fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad); if (lengthcount < minpicturebytes) { step = 3; } else if ((lengthcount % prime1) != 0) { @@ -296,14 +298,16 @@ public class NeuQuant { i = 0; while (i < samplepixels) { - b = (p[pix + 0] & 0xff) << netbiasshift; - g = (p[pix + 1] & 0xff) << netbiasshift; - r = (p[pix + 2] & 0xff) << netbiasshift; + int pixel = p[pix / 3]; + b = (pixel & 0xff) << netbiasshift; + g = ((pixel >> 8) & 0xff) << netbiasshift; + r = ((pixel >> 16) & 0xff) << netbiasshift; j = contest(b, g, r); altersingle(alpha, j, b, g, r); if (rad != 0) { alterneigh(rad, j, b, g, r); /* alter neighbours */ + } pix += step; @@ -327,7 +331,7 @@ public class NeuQuant { } } } - // fprintf(stderr,"finished 1D learning: final alpha=%f + // fprintf(stderr,"finished 1D learning: final alpha=%f // !\n",((float)alpha)/initalpha); } @@ -356,6 +360,7 @@ public class NeuQuant { if (dist >= bestd) { i = netsize; /* stop iter */ + } else { i++; if (dist < 0) { @@ -385,6 +390,7 @@ public class NeuQuant { if (dist >= bestd) { j = -1; /* stop iter */ + } else { j--; if (dist < 0) { diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 5646ed290..0e788a588 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.flash.tags.base.FontTag; import com.jpexs.decompiler.flash.treeitems.SWFList; +import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.helpers.Cache; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; @@ -92,6 +93,7 @@ import javax.swing.SwingWorker; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.filechooser.FileFilter; +import javax.swing.tree.TreePath; /** * Main executable class @@ -1101,7 +1103,10 @@ public class Main { String pathStr = filesToOpen[filesToOpen.length - 1]; if (pathStr.length() > 0) { String[] path = pathStr.split("\\|"); - View.selectTreeNode(mainFrame.getPanel().tagTree, Arrays.asList(path)); + + MainPanel mainPanel = mainFrame.getPanel(); + TreePath tp = View.getTreePathByPathStrings(mainPanel.tagTree, Arrays.asList(path)); + mainPanel.setTagTreeSelectedNode((TreeItem) tp.getLastPathComponent()); } }); } diff --git a/src/com/jpexs/decompiler/flash/gui/View.java b/src/com/jpexs/decompiler/flash/gui/View.java index f893e2941..e931c2955 100644 --- a/src/com/jpexs/decompiler/flash/gui/View.java +++ b/src/com/jpexs/decompiler/flash/gui/View.java @@ -531,6 +531,12 @@ public class View { } private static TreePath expandTreeNode(JTree tree, List pathAsStringList) { + TreePath tp = getTreePathByPathStrings(tree, pathAsStringList); + tree.expandPath(tp); + return tp; + } + + public static TreePath getTreePathByPathStrings(JTree tree, List pathAsStringList) { TreeModel model = tree.getModel(); Object node = model.getRoot(); @@ -558,17 +564,9 @@ public class View { } TreePath tp = new TreePath(path.toArray(new Object[path.size()])); - tree.expandPath(tp); return tp; } - public static void selectTreeNode(JTree tree, List pathAsStringList) { - TreePath tp = expandTreeNode(tree, pathAsStringList); - if (tp != null) { - tree.setSelectionPath(tp); - } - } - public static void expandTreeNodes(JTree tree, TreePath parent, boolean expand) { expandTreeNodesRecursive(tree, parent, expand); }