Added #1909 Export/import DefineBitsJPEG3/4s alpha channel to/from separate file

("PNG/GIF/JPEG+alpha" option in GUI, "-format image:png_gif_jpeg_alpha" for commandline)
Fixed Exporting DefineJPEG3/4 with alpha channel to PNG produced JPEG instead

Refactored bulkImport shapes and images to single file.
This commit is contained in:
Jindra Petřík
2022-12-21 21:59:01 +01:00
parent 9b708491d9
commit c72215df42
12 changed files with 339 additions and 259 deletions

View File

@@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file.
- [#1231] Button transforming
- [#1690] Deobfuscation tool dialog for script level (not just current method / all classes)
- [#1460] Commandline import of text, images, shapes, symbol-class
- [#1909] Export/import DefineBitsJPEG3/4s alpha channel to/from separate file
("PNG/GIF/JPEG+alpha" option in GUI, "-format image:png_gif_jpeg_alpha" for commandline)
### Fixed
- [#1904] NullPointerException when renaming invalid identifiers in AS1/2 files caused by missing charset
@@ -25,6 +27,7 @@ All notable changes to this project will be documented in this file.
- Speaker image when sound selected not in the center
- [#1908] Slow commandline opening SWF
- [#1908] Shape/image import must accept also filenames in the form "CHARID_xxx.ext" instead of just "CHARID.ext"
- Exporting DefineJPEG3/4 with alpha channel to PNG produced JPEG instead
### Changed
- Warning before switching deobfuscation is now optional
@@ -2772,6 +2775,7 @@ All notable changes to this project will be documented in this file.
[#1231]: https://www.free-decompiler.com/flash/issues/1231
[#1690]: https://www.free-decompiler.com/flash/issues/1690
[#1460]: https://www.free-decompiler.com/flash/issues/1460
[#1909]: https://www.free-decompiler.com/flash/issues/1909
[#1904]: https://www.free-decompiler.com/flash/issues/1904
[#595]: https://www.free-decompiler.com/flash/issues/595
[#1908]: https://www.free-decompiler.com/flash/issues/1908

View File

@@ -25,10 +25,14 @@ import com.jpexs.decompiler.flash.exporters.settings.ImageExportSettings;
import com.jpexs.decompiler.flash.helpers.BMPFile;
import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -36,6 +40,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
/**
*
@@ -48,7 +53,7 @@ public class ImageExporter {
if (Thread.currentThread().isInterrupted()) {
return ret;
}
if (tags.isEmpty()) {
return ret;
}
@@ -76,7 +81,7 @@ public class ImageExporter {
final ImageTag imageTag = (ImageTag) t;
ImageFormat fileFormat = imageTag.getImageFormat();
ImageFormat fileFormat = imageTag.getOriginalImageFormat();
ImageFormat originalFormat = fileFormat;
if (settings.mode == ImageExportMode.PNG) {
fileFormat = ImageFormat.PNG;
@@ -92,6 +97,7 @@ public class ImageExporter {
{
final File file = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + "." + ImageHelper.getImageFormatString(fileFormat)));
final ImageFormat ffileFormat = fileFormat;
new RetryTask(() -> {
@@ -105,9 +111,37 @@ public class ImageExporter {
ImageHelper.write(imageTag.getImageCached().getBufferedImage(), ffileFormat, file);
}
}, handler).run();
final File alphaBinFile = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + ".alpha.bin"));
final File alphaPngFile = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + ".alpha.png"));
if ((imageTag instanceof HasSeparateAlphaChannel)
&& (settings.mode == ImageExportMode.PNG_GIF_JPEG_ALPHA)) {
HasSeparateAlphaChannel hsac = (HasSeparateAlphaChannel) imageTag;
if (hsac.hasAlphaChannel()) {
new RetryTask(() -> {
byte[] alphaChannel = hsac.getImageAlpha();
Dimension dim = imageTag.getImageDimension();
BufferedImage img = new BufferedImage(dim.width, dim.height, BufferedImage.TYPE_INT_ARGB);
int[] pixels = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
for (int i = 0; i < pixels.length; i++) {
int a = alphaChannel[i] & 0xff;
int v = 0;
int r = v;
int g = v;
int b = v;
pixels[i] = (a << 24) | (b << 16) | (g << 8) | r;
}
ImageIO.write(img, "PNG", alphaPngFile);
}, handler).run();
}
}
ret.add(file);
}
if (Thread.currentThread().isInterrupted()) {
break;
}

View File

@@ -22,5 +22,9 @@ package com.jpexs.decompiler.flash.exporters.modes;
*/
public enum ImageExportMode {
PNG_GIF_JPEG, PNG, JPEG, BMP
PNG_GIF_JPEG,
PNG,
JPEG,
BMP,
PNG_GIF_JPEG_ALPHA
}

View File

@@ -25,13 +25,25 @@ import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag;
import com.jpexs.decompiler.flash.tags.DefineBitsTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.Helper;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
/**
*
@@ -159,4 +171,124 @@ public class ImageImporter extends TagImporter {
return res;
}
public int bulkImport(File imagesDir, SWF swf, boolean printOut) {
int count = 0;
Map<Integer, CharacterTag> characters = swf.getCharacters();
List<String> extensions = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp");
List<String> alphaExtensions = Arrays.asList("png");
File allFiles[] = imagesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
if (nameLower.endsWith(".alpha.png")) {
return false;
}
for (String ext : extensions) {
if (nameLower.endsWith("." + ext)) {
return true;
}
}
return false;
}
});
File alphaFiles[] = imagesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
for (String ext : alphaExtensions) {
if (nameLower.endsWith(".alpha." + ext)) {
return true;
}
}
return false;
}
});
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ImageTag) {
ImageTag imageTag = (ImageTag) tag;
if (!imageTag.importSupported()) {
continue;
}
List<File> existingFilesForImageTag = new ArrayList<>();
List<File> existingAlphaFilesForImageTag = new ArrayList<>();
for (File f : allFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingFilesForImageTag.add(f);
}
}
for (File f : alphaFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingAlphaFilesForImageTag.add(f);
}
}
existingFilesForImageTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
existingAlphaFilesForImageTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = alphaExtensions.indexOf(ext1) - alphaExtensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
if (!existingFilesForImageTag.isEmpty()) {
if (existingFilesForImageTag.size() > 1) {
Logger.getLogger(ImageImporter.class.getName()).log(Level.WARNING, "Multiple matching files for image tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForImageTag.get(0).getName()});
}
File sourceFile = existingFilesForImageTag.get(0);
if (printOut) {
System.out.println("Importing character " + characterId + " from file " + sourceFile.getName());
}
try {
importImage(imageTag, Helper.readFile(sourceFile.getPath()));
count++;
} catch (IOException ex) {
Logger.getLogger(ImageImporter.class.getName()).log(Level.WARNING, "Cannot import image " + characterId + " from file " + sourceFile.getName(), ex);
}
}
if (!existingAlphaFilesForImageTag.isEmpty()) {
if (existingAlphaFilesForImageTag.size() > 1) {
Logger.getLogger(ImageImporter.class.getName()).log(Level.WARNING, "Multiple matching files for image alpha tag {0} exists, {1} selected", new Object[]{characterId, existingAlphaFilesForImageTag.get(0).getName()});
}
File sourceFile = existingAlphaFilesForImageTag.get(0);
if (printOut) {
System.out.println("Importing character " + characterId + " alpha from file " + sourceFile.getName());
}
try {
importImageAlpha(imageTag, Helper.readFile(sourceFile.getPath()));
} catch (IOException ex) {
Logger.getLogger(ImageImporter.class.getName()).log(Level.WARNING, "Cannot import image " + characterId + " alpha from file " + sourceFile.getName(), ex);
}
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
}
return count;
}
}

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.importers;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.importers.svg.SvgImporter;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag;
import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag;
@@ -28,15 +29,26 @@ import com.jpexs.decompiler.flash.tags.DefineShape3Tag;
import com.jpexs.decompiler.flash.tags.DefineShape4Tag;
import com.jpexs.decompiler.flash.tags.DefineShapeTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.Helper;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
@@ -145,4 +157,75 @@ public class ShapeImporter {
return res;
}
public int bulkImport(File shapesDir, SWF swf, boolean noFill, boolean printOut) {
SvgImporter svgImporter = new SvgImporter();
Map<Integer, CharacterTag> characters = swf.getCharacters();
int shapeCount = 0;
List<String> extensions = Arrays.asList("svg", "png", "jpg", "jpeg", "gif", "bmp");
File allFiles[] = shapesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
for (String ext : extensions) {
if (nameLower.endsWith("." + ext)) {
return true;
}
}
return false;
}
});
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ShapeTag) {
ShapeTag shapeTag = (ShapeTag) tag;
List<File> existingFilesForShapeTag = new ArrayList<>();
for (File f : allFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingFilesForShapeTag.add(f);
}
}
existingFilesForShapeTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
if (existingFilesForShapeTag.isEmpty()) {
continue;
}
if (existingFilesForShapeTag.size() > 1) {
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Multiple matching files for shape tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForShapeTag.get(0).getName()});
}
File sourceFile = existingFilesForShapeTag.get(0);
try {
if (printOut) {
System.out.println("Importing character " + characterId + " from file " + sourceFile.getName());
}
if (sourceFile.getAbsolutePath().toLowerCase().endsWith(".svg")) {
svgImporter.importSvg(shapeTag, Helper.readTextFile(sourceFile.getAbsolutePath()), !noFill);
} else {
importImage(shapeTag, Helper.readFile(sourceFile.getAbsolutePath()), 0, !noFill);
}
shapeCount++;
} catch (IOException ex) {
Logger.getLogger(ShapeImporter.class.getName()).log(Level.WARNING, "Cannot import shape " + characterId + " from file " + sourceFile.getName(), ex);
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
}
return shapeCount;
}
}

View File

@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.tags.base.AloneTag;
import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.decompiler.flash.types.BasicType;
@@ -46,7 +47,7 @@ import java.util.logging.Logger;
* @author JPEXS
*/
@SWFVersion(from = 3) //Note: GIF and PNG since version
public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag, HasSeparateAlphaChannel {
public static final int ID = 35;
@@ -139,10 +140,12 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
setModified(true);
}
@Override
public byte[] getImageAlpha() throws IOException {
return SWFInputStream.uncompressByteArray(bitmapAlphaData.getRangeData());
}
@Override
public void setImageAlpha(byte[] data) throws IOException {
ImageFormat fmt = ImageTag.getImageFormat(imageData);
if (fmt != ImageFormat.JPEG) {
@@ -159,6 +162,11 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
setModified(true);
}
@Override
public boolean hasAlphaChannel() {
return bitmapAlphaData.getLength() > 0;
}
@Override
public ImageFormat getImageFormat() {
ImageFormat fmt = getOriginalImageFormat();
@@ -175,18 +183,18 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
@Override
public InputStream getOriginalImageData() {
if (bitmapAlphaData.getLength() == 0) { // No alpha
JpegFixer jpegFixer = new JpegFixer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
jpegFixer.fixJpeg(new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength()), baos);
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, null, ex);
}
return new ByteArrayInputStream(baos.toByteArray());
//if (bitmapAlphaData.getLength() == 0) { // No alpha
JpegFixer jpegFixer = new JpegFixer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
jpegFixer.fixJpeg(new ByteArrayInputStream(imageData.getArray(), imageData.getPos(), imageData.getLength()), baos);
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, null, ex);
}
return new ByteArrayInputStream(baos.toByteArray());
//}
return null;
//return null;
}
@Override
@@ -245,7 +253,7 @@ public class DefineBitsJPEG3Tag extends ImageTag implements AloneTag {
} catch (IOException ex) {
Logger.getLogger(DefineBitsJPEG3Tag.class.getName()).log(Level.SEVERE, "Failed to get image", ex);
}
SerializableImage img = new SerializableImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE);
Graphics g = img.getGraphics();
g.setColor(SWF.ERROR_COLOR);

View File

@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.SWFOutputStream;
import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType;
import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.tags.base.AloneTag;
import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel;
import com.jpexs.decompiler.flash.tags.base.ImageTag;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.decompiler.flash.types.BasicType;
@@ -46,7 +47,7 @@ import java.util.logging.Logger;
* @author JPEXS
*/
@SWFVersion(from = 10)
public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag, HasSeparateAlphaChannel {
public static final int ID = 90;
@@ -144,10 +145,12 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
setModified(true);
}
@Override
public byte[] getImageAlpha() throws IOException {
return SWFInputStream.uncompressByteArray(bitmapAlphaData.getRangeData());
}
@Override
public void setImageAlpha(byte[] data) throws IOException {
ImageFormat fmt = ImageTag.getImageFormat(imageData);
if (fmt != ImageFormat.JPEG) {
@@ -163,6 +166,11 @@ public class DefineBitsJPEG4Tag extends ImageTag implements AloneTag {
clearCache();
setModified(true);
}
@Override
public boolean hasAlphaChannel() {
return bitmapAlphaData.getLength() > 0;
}
@Override
public ImageFormat getImageFormat() {

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2010-2022 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.tags.base;
import java.io.IOException;
/**
*
* @author JPEXS
*/
public interface HasSeparateAlphaChannel {
public boolean hasAlphaChannel();
public byte[] getImageAlpha() throws IOException;
public void setImageAlpha(byte[] data) throws IOException;
}

View File

@@ -218,6 +218,7 @@ import java.util.logging.Logger;
import com.jpexs.decompiler.flash.Bundle;
import com.jpexs.decompiler.flash.gui.translator.Translator;
import com.jpexs.decompiler.flash.importers.SymbolClassImporter;
import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel;
import java.awt.Font;
import java.util.Comparator;
@@ -389,6 +390,7 @@ public class CommandLineArgumentParser {
out.println(" image:png - PNG format for Images");
out.println(" image:jpeg - JPEG format for Images");
out.println(" image:bmp - BMP format for Images");
out.println(" image:png_gif_jpeg_alpha - PNG/GIF/JPEG+ALPHA format for Images");
out.println(" text:plain - Plain text format for Texts");
out.println(" text:formatted - Formatted text format for Texts");
out.println(" text:svg - SVG format for Texts");
@@ -3246,7 +3248,7 @@ public class CommandLineArgumentParser {
CharacterTag characterTag = swf.getCharacter(imageId);
String repFile = args.pop();
byte[] data = Helper.readFile(repFile);
if (characterTag instanceof DefineBitsJPEG3Tag || characterTag instanceof DefineBitsJPEG4Tag) {
if (characterTag instanceof HasSeparateAlphaChannel) {
ImageTag imageTag = (ImageTag) characterTag;
new ImageImporter().importImageAlpha(imageTag, data);
} else {
@@ -3699,68 +3701,8 @@ public class CommandLineArgumentParser {
System.exit(1);
}
ShapeImporter shapeImporter = new ShapeImporter();
SvgImporter svgImporter = new SvgImporter();
Map<Integer, CharacterTag> characters = swf.getCharacters();
int shapeCount = 0;
List<String> extensions = Arrays.asList("svg", "png", "jpg", "jpeg", "gif", "bmp");
File allFiles[] = shapesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
for (String ext : extensions) {
if (nameLower.endsWith("." + ext)) {
return true;
}
}
return false;
}
});
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ShapeTag) {
ShapeTag shapeTag = (ShapeTag) tag;
List<File> existingFilesForShapeTag = new ArrayList<>();
for (File f : allFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingFilesForShapeTag.add(f);
}
}
existingFilesForShapeTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
if (existingFilesForShapeTag.isEmpty()) {
continue;
}
if (existingFilesForShapeTag.size() > 1) {
logger.log(Level.WARNING, "Multiple matching files for shape tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForShapeTag.get(0).getName()});
}
File sourceFile = existingFilesForShapeTag.get(0);
try {
System.out.println("Importing character " + characterId + " from file " + sourceFile.getName());
if (sourceFile.getAbsolutePath().toLowerCase().endsWith(".svg")) {
svgImporter.importSvg(shapeTag, Helper.readTextFile(sourceFile.getAbsolutePath()), !noFill);
} else {
shapeImporter.importImage(shapeTag, Helper.readFile(sourceFile.getAbsolutePath()), 0, !noFill);
}
shapeCount++;
} catch (IOException ex) {
logger.log(Level.WARNING, "Cannot import shape " + characterId + " from file " + sourceFile.getName(), ex);
}
}
}
int shapeCount = shapeImporter.bulkImport(shapesDir, swf, noFill, true);
System.out.println("Writing outfile");
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) {
swf.saveTo(fos);
@@ -3796,64 +3738,7 @@ public class CommandLineArgumentParser {
System.exit(1);
}
ImageImporter imageImporter = new ImageImporter();
int imageCount = 0;
Map<Integer, CharacterTag> characters = swf.getCharacters();
final List<String> extensions = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp");
File allFiles[] = imagesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
for (String ext : extensions) {
if (nameLower.endsWith("." + ext)) {
return true;
}
}
return false;
}
});
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ImageTag) {
ImageTag imageTag = (ImageTag) tag;
if (!imageTag.importSupported()) {
continue;
}
List<File> existingFilesForImageTag = new ArrayList<>();
for (File f : allFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingFilesForImageTag.add(f);
}
}
existingFilesForImageTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
if (existingFilesForImageTag.isEmpty()) {
continue;
}
if (existingFilesForImageTag.size() > 1) {
logger.log(Level.WARNING, "Multiple matching files for image tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForImageTag.get(0).getName()});
}
File sourceFile = existingFilesForImageTag.get(0);
try {
System.out.println("Importing character " + characterId + " from file " + sourceFile.getName());
imageImporter.importImage(imageTag, Helper.readFile(sourceFile.getPath()));
imageCount++;
} catch (IOException ex) {
logger.log(Level.WARNING, "Cannot import image " + characterId + " from file " + sourceFile.getName(), ex);
}
}
}
int imageCount = imageImporter.bulkImport(imagesDir, swf, true);
System.out.println("Writing outfile");
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) {
swf.saveTo(fos);

View File

@@ -233,6 +233,7 @@ import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -262,6 +263,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.Box;
@@ -3078,67 +3080,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
@Override
public Void doInBackground() throws Exception {
try {
Map<Integer, CharacterTag> characters = swf.getCharacters();
List<String> extensions = Arrays.asList("svg", "png", "jpg", "jpeg", "gif", "bmp");
File allFiles[] = fShapesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
for (String ext : extensions) {
if (nameLower.endsWith("." + ext)) {
return true;
}
}
return false;
}
});
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ShapeTag) {
ShapeTag shapeTag = (ShapeTag) tag;
List<File> existingFilesForShapeTag = new ArrayList<>();
for (File f : allFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingFilesForShapeTag.add(f);
}
}
existingFilesForShapeTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
if (existingFilesForShapeTag.isEmpty()) {
continue;
}
if (existingFilesForShapeTag.size() > 1) {
Logger.getLogger(MainPanel.class.getName()).log(Level.WARNING, "Multiple matching files for shape tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForShapeTag.get(0).getName()});
}
File sourceFile = existingFilesForShapeTag.get(0);
try {
if (sourceFile.getAbsolutePath().toLowerCase().endsWith(".svg")) {
svgImporter.importSvg(shapeTag, Helper.readTextFile(sourceFile.getAbsolutePath()), !noFill);
} else {
shapeImporter.importImage(shapeTag, Helper.readFile(sourceFile.getAbsolutePath()), 0, !noFill);
}
count++;
} catch (IOException ex) {
Logger.getLogger(MainPanel.class.getName()).log(Level.WARNING, "Cannot import shape " + characterId + " from file " + sourceFile.getName(), ex);
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
}
count = shapeImporter.bulkImport(fShapesDir, swf, noFill, false);
swf.clearImageCache();
swf.clearShapeCache();
} catch (Exception ex) {
@@ -3197,65 +3139,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
@Override
public Void doInBackground() throws Exception {
try {
Map<Integer, CharacterTag> characters = swf.getCharacters();
List<String> extensions = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp");
File allFiles[] = fImagesDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
String nameLower = name.toLowerCase();
for (String ext : extensions) {
if (nameLower.endsWith("." + ext)) {
return true;
}
}
return false;
}
});
for (int characterId : characters.keySet()) {
CharacterTag tag = characters.get(characterId);
if (tag instanceof ImageTag) {
ImageTag imageTag = (ImageTag) tag;
if (!imageTag.importSupported()) {
continue;
}
List<File> existingFilesForImageTag = new ArrayList<>();
for (File f : allFiles) {
if (f.getName().startsWith("" + characterId + ".") || f.getName().startsWith("" + characterId + "_")) {
existingFilesForImageTag.add(f);
}
}
existingFilesForImageTag.sort(new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
String ext1 = o1.getName().substring(o1.getName().lastIndexOf(".") + 1);
String ext2 = o2.getName().substring(o2.getName().lastIndexOf(".") + 1);
int ret = extensions.indexOf(ext1) - extensions.indexOf(ext2);
if (ret == 0) {
return o1.getName().compareTo(o2.getName());
}
return ret;
}
});
if (existingFilesForImageTag.isEmpty()) {
continue;
}
if (existingFilesForImageTag.size() > 1) {
Logger.getLogger(MainPanel.class.getName()).log(Level.WARNING, "Multiple matching files for image tag {0} exists, {1} selected", new Object[]{characterId, existingFilesForImageTag.get(0).getName()});
}
File sourceFile = existingFilesForImageTag.get(0);
try {
imageImporter.importImage(imageTag, Helper.readFile(sourceFile.getPath()));
count++;
} catch (IOException ex) {
Logger.getLogger(MainPanel.class.getName()).log(Level.WARNING, "Cannot import image " + characterId + " from file " + sourceFile.getName(), ex);
}
if (Thread.currentThread().isInterrupted()) {
break;
}
}
}
count = imageImporter.bulkImport(fImagesDir, swf, false);
swf.clearImageCache();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error during import", ex);
@@ -3298,7 +3182,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
String selFile = Helper.fixDialogFile(chooser.getSelectedFile()).getAbsolutePath();
boolean textsFolderExists = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME)).exists();
boolean textsFolderExists = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME)).exists();
File textsFile = new File(Path.combine(selFile, TextExportSettings.EXPORT_FOLDER_NAME, TextExporter.TEXT_EXPORT_FILENAME_FORMATTED));
if (!textsFolderExists) {
textsFile = new File(Path.combine(selFile, TextExporter.TEXT_EXPORT_FILENAME_FORMATTED));

View File

@@ -98,3 +98,6 @@ zoom.invalid = Invalid zoom value.
symbolclass = Symbol-Class mapping
symbolclass.csv = CSV
#after 18.0.0
images.png_gif_jpeg_alpha = PNG/GIF/JPEG+alpha

View File

@@ -97,3 +97,6 @@ zoom.invalid = Neplatn\u00e1 hodnota velikost.
symbolclass = Mapov\u00e1n\u00ed symbol\u016f na t\u0159\u00eddy
symbolclass.csv = CSV
#after 18.0.0
images.png_gif_jpeg_alpha = PNG/GIF/JPEG+alpha