diff --git a/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java b/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java index 9294ff3..521e903 100644 --- a/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java +++ b/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileDecoder.java @@ -10,6 +10,8 @@ import java.io.OutputStream; import javax.imageio.ImageIO; +import net.lax1dude.eaglercraft.bintools.utils.LabPBR2Eagler; + /** * Copyright (c) 2023-2024 lax1dude. All Rights Reserved. * @@ -38,30 +40,45 @@ public class EBPFileDecoder { } public static void _main(String[] args) throws IOException { - if(args.length > 1 && args.length < 4 && args[0].equals("-r")) { + boolean labPBR = false; + if(args.length > 1 && args[0].equalsIgnoreCase("--labPBR")) { + labPBR = true; + String[] e = new String[args.length - 1]; + System.arraycopy(args, 1, e, 0, e.length); + args = e; + } + if(args.length > 1 && args.length < 4 && args[0].equalsIgnoreCase("-r")) { File input = new File(args[1]); if(!input.isDirectory()) { System.err.println("Error: Not a directory: " + input.getAbsolutePath()); System.exit(-1); return; } - convertDir(input, args.length == 3 ? new File(args[2]) : input); + convertDir(input, args.length == 3 ? new File(args[2]) : input, labPBR); }else if(args.length == 2) { System.out.println("Reading input file..."); BufferedImage img; try(InputStream is = new FileInputStream(new File(args[0]))) { - img = read(is); + img = readEBP(is); + } + if(labPBR) { + System.out.println("Converting from Eagler to LabPBR..."); + LabPBR2Eagler.convertEaglerToLabPBR(img, img); } File output = new File(args[1]); System.out.println("Writing PNG: " + output.getAbsolutePath()); ImageIO.write(img, "PNG", output); }else { - System.out.println("Usage: ebp-decode "); - System.out.println(" ebp-decode -r [output directory]"); + System.out.println("Usage: ebp-decode [--labPBR] "); + System.out.println(" ebp-decode [--labPBR] -r [output directory]"); } } public static void convertDir(File inputDir, File outputDir) throws IOException { + convertDir(inputDir, outputDir, false); + } + + public static void convertDir(File inputDir, File outputDir, boolean labPBR) throws IOException { if(!outputDir.isDirectory() && !outputDir.mkdirs()) { throw new IOException("Could not create directory: " + outputDir.getAbsolutePath()); } @@ -69,7 +86,7 @@ public class EBPFileDecoder { for(int i = 0; i < f.length; ++i) { String name = f[i].getName(); if(f[i].isDirectory()) { - convertDir(f[i], new File(outputDir, name)); + convertDir(f[i], new File(outputDir, name), labPBR); continue; } if(!name.toLowerCase().endsWith(".ebp")) { @@ -79,13 +96,16 @@ public class EBPFileDecoder { System.out.println(f[i].getAbsolutePath()); BufferedImage img; try(InputStream is = new FileInputStream(f[i])) { - img = read(is); + img = readEBP(is); + } + if(labPBR) { + LabPBR2Eagler.convertEaglerToLabPBR(img, img); } ImageIO.write(img, "PNG", ff); } } - public static BufferedImage read(InputStream is) throws IOException { + public static BufferedImage readEBP(InputStream is) throws IOException { if(is.read() != '%' || is.read() != 'E' || is.read() != 'B' || is.read() != 'P') { throw new IOException("Not an EBP file!"); } diff --git a/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileEncoder.java b/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileEncoder.java index 7aaf9f6..74b7a28 100644 --- a/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileEncoder.java +++ b/src/main/java/net/lax1dude/eaglercraft/bintools/EBPFileEncoder.java @@ -13,6 +13,8 @@ import java.util.Set; import javax.imageio.ImageIO; +import net.lax1dude.eaglercraft.bintools.utils.LabPBR2Eagler; + /** * Copyright (c) 2023-2024 lax1dude. All Rights Reserved. * @@ -40,29 +42,44 @@ public class EBPFileEncoder { } public static void _main(String[] args) throws IOException { - if(args.length > 1 && args.length < 4 && args[0].equals("-r")) { + boolean labPBR = false; + if(args.length > 1 && args[0].equalsIgnoreCase("--labPBR")) { + labPBR = true; + String[] e = new String[args.length - 1]; + System.arraycopy(args, 1, e, 0, e.length); + args = e; + } + if(args.length > 1 && args.length < 4 && args[0].equalsIgnoreCase("-r")) { File input = new File(args[1]); if(!input.isDirectory()) { System.err.println("Error: Not a directory: " + input.getAbsolutePath()); System.exit(-1); return; } - convertDir(input, args.length == 3 ? new File(args[2]) : input); + convertDir(input, args.length == 3 ? new File(args[2]) : input, labPBR); }else if(args.length == 2) { System.out.println("Reading input file..."); BufferedImage img = ImageIO.read(new File(args[0])); File output = new File(args[1]); + if(labPBR) { + System.out.println("Converting from LabPBR to Eagler..."); + LabPBR2Eagler.convertLabPBRToEagler(img, img); + } System.out.println("Encoding EBP: " + output.getAbsolutePath()); try(OutputStream os = new FileOutputStream(output)) { - write(img, os); + writeEBP(img, os); } }else { - System.out.println("Usage: ebp-encode "); - System.out.println(" ebp-encode -r [output directory]"); + System.out.println("Usage: ebp-encode [--labPBR] "); + System.out.println(" ebp-encode [--labPBR] -r [output directory]"); } } public static void convertDir(File inputDir, File outputDir) throws IOException { + convertDir(inputDir, outputDir, false); + } + + public static void convertDir(File inputDir, File outputDir, boolean labPBR) throws IOException { if(!outputDir.isDirectory() && !outputDir.mkdirs()) { throw new IOException("Could not create directory: " + outputDir.getAbsolutePath()); } @@ -70,7 +87,7 @@ public class EBPFileEncoder { for(int i = 0; i < f.length; ++i) { String name = f[i].getName(); if(f[i].isDirectory()) { - convertDir(f[i], new File(outputDir, name)); + convertDir(f[i], new File(outputDir, name), labPBR); continue; } if(!name.toLowerCase().endsWith(".png")) { @@ -78,13 +95,17 @@ public class EBPFileEncoder { } File ff = new File(outputDir, name.substring(0, name.length() - 3) + "ebp"); System.out.println(f[i].getAbsolutePath()); + BufferedImage img = ImageIO.read(f[i]); + if(labPBR) { + LabPBR2Eagler.convertLabPBRToEagler(img, img); + } try(OutputStream os = new FileOutputStream(ff)) { - write(ImageIO.read(f[i]), os); + writeEBP(img, os); } } } - public static void write(BufferedImage img, OutputStream fos) throws IOException { + public static void writeEBP(BufferedImage img, OutputStream fos) throws IOException { fos.write(new byte[] { '%', 'E', 'B', 'P'}); fos.write(1); // v1 fos.write(3); // 3 component diff --git a/src/main/java/net/lax1dude/eaglercraft/bintools/utils/LabPBR2Eagler.java b/src/main/java/net/lax1dude/eaglercraft/bintools/utils/LabPBR2Eagler.java new file mode 100644 index 0000000..7400999 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/bintools/utils/LabPBR2Eagler.java @@ -0,0 +1,47 @@ +package net.lax1dude.eaglercraft.bintools.utils; + +import java.awt.image.BufferedImage; + +/** + * Copyright (c) 2024 lax1dude. All Rights Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public class LabPBR2Eagler { + + /** + * See net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.PBRTextureMapUtils + */ + public static void convertLabPBRToEagler(BufferedImage input, BufferedImage output) { + for(int w = input.getWidth(), x = 0; x < w; ++x) { + for(int h = input.getHeight(), y = 0; y < h; ++y) { + int pixel = input.getRGB(x, y); + int a = (pixel >>> 24) & 0xFF; + if(a == 0xFF) a = 0; + output.setRGB(x, y, (pixel & 0x00FFFF00) | Math.min(a << 2, 0xFF) | 0xFF000000); + } + } + } + + public static void convertEaglerToLabPBR(BufferedImage input, BufferedImage output) { + for(int w = input.getWidth(), x = 0; x < w; ++x) { + for(int h = input.getHeight(), y = 0; y < h; ++y) { + int pixel = input.getRGB(x, y); + int a = (pixel >>> 2) & 0x3F; + if(a == 0) a = 0xFF; + output.setRGB(x, y, (pixel & 0x00FFFF00) | (a << 24)); + } + } + } + +}