Added: #2504 WebP image format for export/import (not animated)

Limitation: It's not available on Mac x86-64 platform
This commit is contained in:
Jindra Petřík
2025-08-10 18:45:12 +02:00
parent d8dc85109b
commit 2df87d1a0a
29 changed files with 344 additions and 30 deletions

View File

@@ -20,6 +20,8 @@ All notable changes to this project will be documented in this file.
hilight float instruction blue
- Icons for every tag type
- [#2499] Information about frames which do not have ShowFrame tag
- [#2504] WebP image format for export/import (not animated)
Limitation: It's not available on Mac x86-64 platform
### Fixed
- [#2474] Gotos incorrectly decompiled
@@ -3951,6 +3953,7 @@ Major version of SWF to XML export changed to 2.
[#2478]: https://www.free-decompiler.com/flash/issues/2478
[#2485]: https://www.free-decompiler.com/flash/issues/2485
[#2499]: https://www.free-decompiler.com/flash/issues/2499
[#2504]: https://www.free-decompiler.com/flash/issues/2504
[#2474]: https://www.free-decompiler.com/flash/issues/2474
[#2480]: https://www.free-decompiler.com/flash/issues/2480
[#2338]: https://www.free-decompiler.com/flash/issues/2338

BIN
lib/webp4j-1.1.0.jar Normal file

Binary file not shown.

21
lib/webp4j.license.txt Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Mr Nanko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -124,9 +124,10 @@ It uses modified code of these libraries:
* UAB "DKD" NellyMoser ASAO codec (Decoding Nelly Moser sound format) - LGPL
* [Animated GIF Writer] (Frames to GIF export) - Creative Commons Attribution 3.0 Unported
* [Animated GIF Encoder] (Frames to GIF export)
* [gnujpdf] (PDF export) - LGPL License
* [openjdk8 Stroker] (Shapes - Miter clip drawing) - GPL License
* [Apache Flex SDK] (Decimal numbers support - Decimal128 class) - Apache Licence 2.0
* [gnujpdf] (PDF export) - LGPL
* [openjdk8 Stroker] (Shapes - Miter clip drawing) - GPL
* [Apache Flex SDK] (Decimal numbers support - Decimal128 class) - Apache License 2.0
* [webp4j] (WEBP format export/import) - MIT
And also links to these libraries:
@@ -166,3 +167,4 @@ And also links to these libraries:
[FLA Compound Document Tools]: https://github.com/jindrapetrik/flacomdoc
[TomlJ]: https://github.com/tomlj/tomlj
[ANTLR]: https://www.antlr.org/
[webp4j]: https://github.com/jindrapetrik/webp4j/tree/java8

Binary file not shown.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Mr Nanko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -242,7 +242,7 @@ auxiliary.show.customizer.message=<message>
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
<compilation-unit>
<package-root>src</package-root>
<classpath mode="compile">../../src;lib/LZMA.jar;lib/avi.jar;lib/cmykjpeg.jar;lib/ddsreader.jar;lib/gif.jar;lib/gnujpdf.jar;lib/jlayer-1.0.2.jar;lib/jpacker.jar;lib/nellymoser.jar;lib/sfntly.jar;lib/tga.jar;lib/ttf.jar;lib/vlcj-4.7.3.jar;lib/vlcj-natives-4.7.0.jar;lib/flashdebugger.jar;lib/jna-3.5.1.jar;lib/jna-platform-3.5.1.jar;lib/gifreader.jar;lib/miterstroke.jar;lib/decimal.jar;lib/flacomdoc.jar;lib/tomlj-1.1.1.jar;lib/decimal.jar</classpath>
<classpath mode="compile">../../src;lib/LZMA.jar;lib/avi.jar;lib/cmykjpeg.jar;lib/ddsreader.jar;lib/gif.jar;lib/gnujpdf.jar;lib/jlayer-1.0.2.jar;lib/jpacker.jar;lib/nellymoser.jar;lib/sfntly.jar;lib/tga.jar;lib/ttf.jar;lib/vlcj-4.7.3.jar;lib/vlcj-natives-4.7.0.jar;lib/flashdebugger.jar;lib/jna-3.5.1.jar;lib/jna-platform-3.5.1.jar;lib/gifreader.jar;lib/miterstroke.jar;lib/decimal.jar;lib/flacomdoc.jar;lib/tomlj-1.1.1.jar;lib/decimal.jar;lib/webp4j-1.1.0.jar</classpath>
<built-to>build</built-to>
<built-to>reports</built-to>
<built-to>dist</built-to>

View File

@@ -63,6 +63,7 @@ import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
import com.jpexs.helpers.SerializableImage;
import com.jpexs.helpers.utf8.Utf8Helper;
import dev.matrixlab.webp4j.WebPCodec;
import gnu.jpdf.PDFGraphics;
import gnu.jpdf.PDFJob;
import java.awt.AlphaComposite;
@@ -120,6 +121,9 @@ public class FrameExporter {
case SVG:
fem = FrameExportMode.SVG;
break;
case WEBP:
fem = FrameExportMode.WEBP;
break;
case SWF:
fem = FrameExportMode.SWF;
break;
@@ -160,6 +164,9 @@ public class FrameExporter {
case BMP:
fem = FrameExportMode.BMP;
break;
case WEBP:
fem = FrameExportMode.WEBP;
break;
case SWF:
fem = FrameExportMode.SWF;
break;
@@ -513,7 +520,9 @@ public class FrameExporter {
}
final Color fbackgroundColor = backgroundColor;
final boolean usesTransparency = settings.mode == FrameExportMode.PNG || settings.mode == FrameExportMode.GIF;
final boolean usesTransparency = settings.mode == FrameExportMode.PNG
|| settings.mode == FrameExportMode.GIF
|| settings.mode == FrameExportMode.WEBP;
final MyFrameIterator frameImages = new MyFrameIterator(tim, fframes, evl, usesTransparency, backgroundColor, settings, subFramesLength);
switch (settings.mode) {
@@ -545,6 +554,26 @@ public class FrameExporter {
}
}
break;
case WEBP:
for (File foutdir : foutdirs) {
frameImages.reset();
for (int i = 0; frameImages.hasNext(); i++) {
final int fi = i;
new RetryTask(() -> {
int fileNum = subFramesLength > 1 ? fi + 1 : (fframes.get(fi) + 1);
File f = new File(foutdir + File.separator + fileNum + ".webp");
BufferedImage img = frameImages.next();
if (img != null) {
try(FileOutputStream fos = new FileOutputStream(f)) {
fos.write(WebPCodec.encodeImage(img, 100f));
}
}
ret.add(f);
}, handler).run();
}
}
break;
case PNG:
for (File foutdir : foutdirs) {
frameImages.reset();

View File

@@ -33,6 +33,7 @@ import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
import dev.matrixlab.webp4j.WebPCodec;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
@@ -110,6 +111,11 @@ public class ImageExporter {
if (settings.mode == ImageExportMode.BMP) {
fileFormat = ImageFormat.BMP;
}
if (settings.mode == ImageExportMode.WEBP) {
fileFormat = ImageFormat.WEBP;
}
final File file = new File(outdir + File.separator + Helper.makeFileName(imageTag.getCharacterExportFileName() + "." + ImageHelper.getImageFormatString(fileFormat)));
final ImageFormat ffileFormat = fileFormat;
@@ -121,6 +127,10 @@ public class ImageExporter {
}
} else if (ffileFormat == ImageFormat.BMP) {
BMPFile.saveBitmap(imageTag.getImageCached().getBufferedImage(), file);
} else if (ffileFormat == ImageFormat.WEBP) {
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(file))) {
fos.write(WebPCodec.encodeImage(imageTag.getImageCached().getBufferedImage(), 100f));
}
} else {
ImageHelper.write(imageTag.getImageCached().getBufferedImage(), ffileFormat, file);
}

View File

@@ -48,6 +48,7 @@ import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
import com.jpexs.helpers.SerializableImage;
import com.jpexs.helpers.utf8.Utf8Helper;
import dev.matrixlab.webp4j.WebPCodec;
import java.awt.Graphics2D;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@@ -158,6 +159,7 @@ public class MorphShapeExporter {
break;
case PNG_START_END:
case BMP_START_END:
case WEBP_START_END:
double unzoom = settings.zoom;
st = mst.getStartShapeTag();
rect = st.getRect();
@@ -178,6 +180,10 @@ public class MorphShapeExporter {
st.toImage(0, 0, 0, new RenderContext(), img, img, false, m, m, m, m, new CXFORMWITHALPHA(), unzoom, false, new ExportRectangle(rect), new ExportRectangle(rect), true, Timeline.DRAW_MODE_ALL, 0, true);
if (settings.mode == MorphShapeExportMode.PNG_START_END) {
ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, fileStart);
} else if (settings.mode == MorphShapeExportMode.WEBP_START_END) {
try(FileOutputStream fos = new FileOutputStream(fileStart)) {
fos.write(WebPCodec.encodeImage(img.getBufferedImage(), 100f));
}
} else {
BMPFile.saveBitmap(img.getBufferedImage(), fileStart);
}
@@ -201,6 +207,10 @@ public class MorphShapeExporter {
st.toImage(0, 0, 0, new RenderContext(), img, img, false, m, m, m, m, new CXFORMWITHALPHA(), unzoom, false, new ExportRectangle(rect), new ExportRectangle(rect), true, Timeline.DRAW_MODE_ALL, 0, true);
if (settings.mode == MorphShapeExportMode.PNG_START_END) {
ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, fileEnd);
} else if (settings.mode == MorphShapeExportMode.WEBP_START_END) {
try(FileOutputStream fos = new FileOutputStream(fileEnd)) {
fos.write(WebPCodec.encodeImage(img.getBufferedImage(), 100f));
}
} else {
BMPFile.saveBitmap(img.getBufferedImage(), fileEnd);
}

View File

@@ -46,6 +46,7 @@ import com.jpexs.helpers.Helper;
import com.jpexs.helpers.Path;
import com.jpexs.helpers.SerializableImage;
import com.jpexs.helpers.utf8.Utf8Helper;
import dev.matrixlab.webp4j.WebPCodec;
import java.awt.Graphics2D;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
@@ -122,6 +123,7 @@ public class ShapeExporter {
break;
case PNG:
case BMP:
case WEBP:
int newWidth = (int) (rect.getWidth() * settings.zoom / SWF.unitDivisor) + 1;
int newHeight = (int) (rect.getHeight() * settings.zoom / SWF.unitDivisor) + 1;
SerializableImage img = new SerializableImage(newWidth, newHeight, SerializableImage.TYPE_INT_ARGB_PRE);
@@ -137,6 +139,10 @@ public class ShapeExporter {
st.toImage(0, 0, 0, new RenderContext(), img, img, false, m, m, m, m, new CXFORMWITHALPHA(), unzoom, false, new ExportRectangle(rect), new ExportRectangle(rect), true, Timeline.DRAW_MODE_ALL, 0, true);
if (settings.mode == ShapeExportMode.PNG) {
ImageHelper.write(img.getBufferedImage(), ImageFormat.PNG, file);
} else if (settings.mode == ShapeExportMode.WEBP) {
try(FileOutputStream fos = new FileOutputStream(file)) {
fos.write(WebPCodec.encodeImage(img.getBufferedImage(), 100f));
}
} else {
BMPFile.saveBitmap(img.getBufferedImage(), file);
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.exporters.modes;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
/**
* Button export mode.
*
@@ -34,8 +36,19 @@ public enum ButtonExportMode {
* BMP - Windows Bitmap
*/
BMP,
/**
* WEBP
*/
WEBP,
/**
* SWF - Shockwave Flash
*/
SWF,
SWF;
public boolean available() {
if (this == WEBP) {
return ImageFormat.WEBP.available();
}
return true;
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.exporters.modes;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
/**
* Frame export mode.
*
@@ -50,8 +52,19 @@ public enum FrameExportMode {
* BMP - Windows Bitmap
*/
BMP,
/**
* WEBP
*/
WEBP,
/**
* SWF - Shockwave Flash
*/
SWF,
SWF;
public boolean available() {
if (this == WEBP) {
return ImageFormat.WEBP.available();
}
return true;
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.exporters.modes;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
/**
* Image export mode.
*
@@ -42,5 +44,16 @@ public enum ImageExportMode {
/**
* PNG, GIF or JPEG, depending on what suits the best, plus alpha channel
*/
PNG_GIF_JPEG_ALPHA
PNG_GIF_JPEG_ALPHA,
/*
* WEBP
*/
WEBP;
public boolean available() {
if (this == WEBP) {
return ImageFormat.WEBP.available();
}
return true;
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.exporters.modes;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
/**
* Morph shape export mode.
*
@@ -44,10 +46,21 @@ public enum MorphShapeExportMode {
* BMP start and end frames - Windows Bitmap
*/
BMP_START_END,
/**
* WEBP start and end frames
*/
WEBP_START_END,
//GIF,
//AVI,
/**
* SWF - Shockwave Flash
*/
SWF,
SWF;
public boolean available() {
if (this == WEBP_START_END) {
return ImageFormat.WEBP.available();
}
return true;
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.exporters.modes;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
/**
* Shape export mode.
*
@@ -38,8 +40,19 @@ public enum ShapeExportMode {
* BMP - Windows Bitmap
*/
BMP,
/**
* WEBP
*/
WEBP,
/**
* SWF - Shockwave Flash
*/
SWF,
SWF;
public boolean available() {
if (this == WEBP) {
return ImageFormat.WEBP.available();
}
return true;
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.exporters.modes;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
/**
* Sprite export mode.
*
@@ -50,8 +52,19 @@ public enum SpriteExportMode {
* BMP - Windows Bitmap
*/
BMP,
/**
* WEBP
*/
WEBP,
/**
* SWF - Shockwave Flash
*/
SWF,
SWF;
public boolean available() {
if (this == WEBP) {
return ImageFormat.WEBP.available();
}
return true;
}
}

View File

@@ -60,6 +60,8 @@ public class MorphShapeExportSettings {
return ".png";
case BMP_START_END:
return ".bmp";
case WEBP_START_END:
return ".webp";
case SVG:
case SVG_START_END:
return ".svg";

View File

@@ -64,6 +64,8 @@ public class ShapeExportSettings {
return ".bmp";
case CANVAS:
return ".html";
case WEBP:
return ".webp";
case SWF:
return ".swf";
default:

View File

@@ -226,6 +226,8 @@ public class ImageHelper {
return "png";
case BMP:
return "bmp";
case WEBP:
return "webp";
}
throw new Error("Unsupported image format: " + format);

View File

@@ -31,6 +31,7 @@ import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.helpers.ByteArrayRange;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import dev.matrixlab.webp4j.WebPCodec;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -77,6 +78,20 @@ public class ImageImporter extends TagImporter {
ImageHelper.write(b, ImageFormat.PNG, baos);
newData = baos.toByteArray();
}
if (newData.length >= 4
&& newData[0] == 'R'
&& newData[1] == 'I'
&& newData[2] == 'F'
&& newData[3] == 'F')
{
if (!ImageFormat.WEBP.available()) {
throw new RuntimeException("WEBP format is not supported on your platform");
}
BufferedImage b = WebPCodec.decodeImage(newData);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageHelper.write(b, ImageFormat.PNG, baos);
newData = baos.toByteArray();
}
if (tagType == 0) {
if (it instanceof DefineBitsTag) {
@@ -94,7 +109,7 @@ public class ImageImporter extends TagImporter {
&& newData[3] == (byte) 0xe0) {
tagType = DefineBitsJPEG2Tag.ID;
} else {
tagType = DefineBitsLosslessTag.ID;
tagType = DefineBitsLossless2Tag.ID;
}
}

View File

@@ -38,10 +38,12 @@ import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
import com.jpexs.helpers.CancellableWorker;
import com.jpexs.helpers.Helper;
import dev.matrixlab.webp4j.WebPCodec;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
@@ -162,6 +164,21 @@ public class ShapeImporter {
ImageHelper.write(b, ImageFormat.PNG, baos);
newData = baos.toByteArray();
}
if (newData.length >= 4
&& newData[0] == 'R'
&& newData[1] == 'I'
&& newData[2] == 'F'
&& newData[3] == 'F')
{
if (!ImageFormat.WEBP.available()) {
throw new RuntimeException("WEBP format is not supported on your platform");
}
BufferedImage b = WebPCodec.decodeImage(newData);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageHelper.write(b, ImageFormat.PNG, baos);
newData = baos.toByteArray();
}
if (tagType == 0) {
if (ImageTag.getImageFormat(newData) == ImageFormat.JPEG) {

View File

@@ -16,6 +16,9 @@
*/
package com.jpexs.decompiler.flash.tags.enums;
import dev.matrixlab.webp4j.NativeWebP;
import dev.matrixlab.webp4j.WebPCodec;
/**
* Image format.
*
@@ -42,7 +45,11 @@ public enum ImageFormat {
/**
* BMP
*/
BMP(".bmp");
BMP(".bmp"),
/**
* WEBP
*/
WEBP(".webp");
private final String extension;
@@ -57,4 +64,15 @@ public enum ImageFormat {
public String getExtension() {
return extension;
}
public boolean available() {
if (this == WEBP) {
try {
new NativeWebP();
} catch (Throwable t) {
return false;
}
}
return true;
}
}

View File

@@ -329,7 +329,7 @@
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
<compilation-unit>
<package-root>src</package-root>
<classpath mode="compile">lib/jpproxy.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-fix.jar;lib/substance-6.2.jar;libsrc/ffdec_lib/src;lib/tablelayout.jar;lib/jsyntaxpane-0.9.5.jar;lib/JavactiveX.jar;lib/flashdebugger.jar;lib/treetable.jar;lib/minimal-json-0.9.5.jar;libsrc/ffdec_lib/lib/gnujpdf.jar;libsrc/ffdec_lib/lib/jna-3.5.1.jar;libsrc/ffdec_lib/lib/jna-platform-3.5.1.jar;libsrc/ffdec_lib/lib/flashdebugger.jar;lib/gifreader.jar;lib/jansi-2.4.0.jar;lib/decimal.jar</classpath>
<classpath mode="compile">lib/jpproxy.jar;lib/trident-6.2.jar;lib/substance-flamingo-6.2.jar;lib/flamingo-6.2.jar;lib/substance-fix.jar;lib/substance-6.2.jar;libsrc/ffdec_lib/src;lib/tablelayout.jar;lib/jsyntaxpane-0.9.5.jar;lib/JavactiveX.jar;lib/flashdebugger.jar;lib/treetable.jar;lib/minimal-json-0.9.5.jar;libsrc/ffdec_lib/lib/gnujpdf.jar;libsrc/ffdec_lib/lib/jna-3.5.1.jar;libsrc/ffdec_lib/lib/jna-platform-3.5.1.jar;libsrc/ffdec_lib/lib/flashdebugger.jar;lib/gifreader.jar;lib/jansi-2.4.0.jar;lib/decimal.jar;lib/webp4j-1.1.0.jar</classpath>
<built-to>build</built-to>
<built-to>javadoc</built-to>
<built-to>reports</built-to>

View File

@@ -210,8 +210,7 @@ alias /?
-format <format> (optional, html is default) Selects output format
<format> is currently only html
-locale <locale> (optional) Override default locale
<locale> is localization identifier, en for english for example
<format> is currently only html
<locale> is localization identifier, en for english for example
-getInstanceMetadata -instance <instanceName> [-outputFormat <outputFormat>] \
[-key <key> ] [-datafile <datafile>] <swffile>
@@ -324,8 +323,12 @@ Pre-options:
shape:png - PNG format for Shapes
shape:canvas - HTML5 Canvas format for Shapes
shape:bmp - BMP format for Shapes
shape:webp - WEBP format for Shapes
morphshape:svg - SVG format for MorphShapes
morphshape:canvas - HTML5 Canvas format for MorphShapes
morpshape:png_start_end - PNG start-end format for MorphShapes
morpshape:bmp_start_end - BMP start-end format for MorphShapes
morpshape:webp_start_end - WEBP start-end format for MorphShapes
frame:png - PNG format for Frames
frame:gif - GIF format for Frames
frame:avi - AVI format for Frames
@@ -333,6 +336,7 @@ Pre-options:
frame:canvas - HTML5 Canvas format for Frames
frame:pdf - PDF format for Frames
frame:bmp - BMP format for Frames
frame:webp - WEBP format for Frames
sprite:png - PNG format for Sprites
sprite:gif - GIF format for Sprites
sprite:avi - AVI format for Sprites
@@ -340,14 +344,17 @@ Pre-options:
sprite:canvas - HTML5 Canvas format for Sprites
sprite:pdf - PDF format for Sprites
sprite:bmp - BMP format for Sprites
sprite:webp - WEBP format for Sprites
button:png - PNG format for Buttons
button:svg - SVG format for Buttons
button:bmp - BMP format for Buttons
button:webp - WEBP format for Buttons
image:png_gif_jpeg - PNG/GIF/JPEG format for Images
image:png - PNG format for Images
image:jpeg - JPEG format for Images
image:bmp - BMP format for Images
image:png_gif_jpeg_alpha - PNG/GIF/JPEG+ALPHA format for Images
image:webp - WEBP format for Images
text:plain - Plain text format for Texts
text:formatted - Formatted text format for Texts
text:svg - SVG format for Texts

View File

@@ -59,10 +59,14 @@ import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
@@ -141,7 +145,7 @@ public class ExportDialog extends AppDialog {
ButtonExportMode.class
};
private final JComboBox[] combos;
private final JComboBox<ComboValue>[] combos;
private final JCheckBox[] checkBoxes;
@@ -157,9 +161,8 @@ public class ExportDialog extends AppDialog {
public <E> E getValue(Class<E> option) {
for (int i = 0; i < optionClasses.length; i++) {
if (option == optionClasses[i]) {
E[] values = option.getEnumConstants();
return values[combos[i].getSelectedIndex()];
if (option == optionClasses[i]) {
return (E) ((ComboValue) combos[i].getSelectedItem()).value;
}
}
@@ -199,10 +202,9 @@ public class ExportDialog extends AppDialog {
private void saveConfig() {
StringBuilder cfg = new StringBuilder();
for (int i = 0; i < optionNames.length; i++) {
int selIndex = combos[i].getSelectedIndex();
Object val = ((ComboValue) combos[i].getSelectedItem()).value;
Class c = optionClasses[i];
Object[] vals = c.getEnumConstants();
String key = optionNames[i] + "." + vals[selIndex].toString().toLowerCase(Locale.ENGLISH);
String key = optionNames[i] + "." + val.toString().toLowerCase(Locale.ENGLISH);
if (i > 0) {
cfg.append(",");
}
@@ -321,17 +323,31 @@ public class ExportDialog extends AppDialog {
for (int i = 0; i < optionNames.length; i++) {
Class c = optionClasses[i];
Object[] vals = c.getEnumConstants();
String[] names = new String[vals.length];
List<ComboValue> namesList = new ArrayList<>();
int itemIndex = -1;
for (int j = 0; j < vals.length; j++) {
try {
Method availableMethod = c.getMethod("available");
if (!(Boolean)availableMethod.invoke(vals[j]))
{
continue;
}
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) {
//ignore
}
//ignore
//ignore
String key = optionNames[i] + "." + vals[j].toString().toLowerCase(Locale.ENGLISH);
if (exportFormats.contains(key)) {
itemIndex = j;
}
names[j] = translate(key);
namesList.add(new ComboValue(vals[j], translate(key)));
}
ComboValue[] names = namesList.toArray(new ComboValue[0]);
combos[i] = new JComboBox<>(names);
if (itemIndex > -1) {
combos[i].setSelectedIndex(itemIndex);
@@ -494,4 +510,19 @@ public class ExportDialog extends AppDialog {
setVisible(true);
return result;
}
private class ComboValue {
public Object value;
public String text;
public ComboValue(Object value, String text) {
this.value = value;
this.text = text;
}
@Override
public String toString() {
return text;
}
}
}

View File

@@ -16,14 +16,21 @@
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.helpers.ImageHelper;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.helpers.Helper;
import dev.matrixlab.webp4j.WebPCodec;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
@@ -87,9 +94,26 @@ public class FileChooserImagePreview extends JComponent
return;
}
ImageIcon tmpIcon = new ImageIcon(file.getPath());
BufferedImage img = null;
if (file.getPath().toLowerCase().endsWith(".webp")) {
if (ImageFormat.WEBP.available()) {
try {
img = WebPCodec.decodeImage(Helper.readFile(file.getAbsolutePath()));
} catch (IOException ex) {
//ignore
}
}
} else {
try(FileInputStream fis = new FileInputStream(file)) {
img = ImageHelper.read(fis);
} catch (IOException ex) {
//ignore
}
}
if (img != null) {
ImageIcon tmpIcon = new ImageIcon(img);
if (tmpIcon != null) {
if (tmpIcon.getImageLoadStatus() == MediaTracker.COMPLETE) {
if (tmpIcon.getIconWidth() > PREVIEW_SIZE) {
thumbnail = new ImageIcon(tmpIcon.getImage().getScaledInstance(PREVIEW_SIZE, -1, Image.SCALE_DEFAULT));

View File

@@ -182,6 +182,7 @@ import com.jpexs.decompiler.flash.tags.base.SymbolClassTypeTag;
import com.jpexs.decompiler.flash.tags.base.TextImportErrorHandler;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.base.UnsupportedSamplingRateException;
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
import com.jpexs.decompiler.flash.tags.gfx.DefineExternalStreamSound;
import com.jpexs.decompiler.flash.tags.text.TextParseException;
import com.jpexs.decompiler.flash.timeline.AS3Package;
@@ -5253,10 +5254,19 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
//}
}
if (ti0 instanceof ImageTag) {
file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp", true, "importimage");
String filters = "*.jpg;*.jpeg;*.gif;*.png;*.bmp";
if (ImageFormat.WEBP.available()) {
filters += ";*.webp";
}
file = showImportFileChooser("filter.images|" + filters, true, "importimage");
}
if (ti0 instanceof ShapeTag) {
file = showImportFileChooser("filter.images|*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.svg", true, "importshape");
String filters = "*.jpg;*.jpeg;*.gif;*.png;*.bmp";
if (ImageFormat.WEBP.available()) {
filters += ";*.webp";
}
filters += ";*.svg";
file = showImportFileChooser("filter.images|" + filters, true, "importshape");
}
if (ti0 instanceof MorphShapeTag) {
return replaceMorphShape((MorphShapeTag) ti0, create, true);

View File

@@ -17,6 +17,7 @@ shapes = Shapes
shapes.svg = SVG
shapes.png = PNG
shapes.bmp = BMP
shapes.webp = WEBP
shapes.canvas = HTML5 Canvas
shapes.swf = SWF
texts = Texts
@@ -28,6 +29,7 @@ images.png_gif_jpeg=PNG/GIF/JPEG
images.png = PNG
images.jpeg = JPEG
images.bmp = BMP
images.webp = WEBP
movies = Movies
movies.flv = FLV (No audio)
sounds = Sounds
@@ -56,6 +58,7 @@ morphshapes.swf = SWF
morphshapes.bmp_start_end=BMP (start, end)
morphshapes.png_start_end=PNG (start, end)
morphshapes.svg_start_end=SVG (start, end)
morphshapes.webp_start_end=WEBP (start, end)
frames = Frames
frames.png = PNG
frames.gif = GIF
@@ -64,6 +67,7 @@ frames.svg = SVG
frames.canvas = HTML5 Canvas
frames.pdf = PDF
frames.bmp = BMP
frames.webp = WEBP
frames.swf = SWF
sprites = Sprites
sprites.png = PNG
@@ -73,11 +77,13 @@ sprites.svg = SVG
sprites.canvas = HTML5 Canvas
sprites.pdf = PDF
sprites.bmp = BMP
sprites.webp = WEBP
sprites.swf = SWF
buttons = Buttons
buttons.png = PNG
buttons.svg = SVG
buttons.bmp = BMP
buttons.webp = WEBP
buttons.swf = SWF
fonts = Fonts
fonts.ttf = TTF