diff --git a/README.md b/README.md index 78c5a1f..ee50161 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Who knows ? - Uses `Spring Boot` as base, because life is too short. - Uses [Jaudiotagger](https://www.jthink.net/jaudiotagger/). +- Uses [image-to-ascii](https://github.com/seujorgenochurras/image-to-ascii) # Requirements for hacking the codebase @@ -34,7 +35,7 @@ The needed `reachabilty metadata` are in the [src/main/resources/META-INF/native # JUST MAKE A FUCKING .EXE FILE AND GIVE IT TO ME -The running executable available in the [bin](https://github.com/mpalourdio/flhacker/raw/main/bin/flhacker) is linux x64 only. I may forget to update the bin because this is not automated for now. It may also not target your OS/CPU architecture. +The running executable available in the [zip](https://github.com/mpalourdio/flhacker/raw/main/bin/flhacker.zip) is linux x64 only. I may forget to update the bin because this is not automated for now. It may also not target your OS/CPU architecture. The best way to be up-to-date is to clone the repo and compile the sources if you know what you are doing (or open an issue). diff --git a/bin/flacker.zip b/bin/flacker.zip new file mode 100644 index 0000000..3a0e43f Binary files /dev/null and b/bin/flacker.zip differ diff --git a/bin/flhacker b/bin/flhacker deleted file mode 100755 index 758f264..0000000 Binary files a/bin/flhacker and /dev/null differ diff --git a/pom.xml b/pom.xml index 341f873..f10c1fe 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,12 @@ 3.0.1 + + io.github.seujorgenochurras + image-to-ascii + 0.0.4 + + commons-io commons-io diff --git a/src/main/java/com/mpalourdio/projects/flhacker/FlhackerApplication.java b/src/main/java/com/mpalourdio/projects/flhacker/FlhackerApplication.java index d8e9fc1..72c5235 100644 --- a/src/main/java/com/mpalourdio/projects/flhacker/FlhackerApplication.java +++ b/src/main/java/com/mpalourdio/projects/flhacker/FlhackerApplication.java @@ -9,6 +9,10 @@ package com.mpalourdio.projects.flhacker; +import io.github.seujorgenochurras.image.ascii.AsciiParser; +import io.github.seujorgenochurras.image.ascii.ParserBuilder; +import io.github.seujorgenochurras.image.ascii.algorithm.pixel.bright.Algorithms; +import io.github.seujorgenochurras.image.ascii.algorithm.pixel.color.DefaultColorType; import org.apache.commons.cli.*; import org.apache.commons.io.FileUtils; import org.jaudiotagger.audio.AudioFileIO; @@ -24,14 +28,13 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; @SpringBootApplication public class FlhackerApplication { static final String TMP_DIR = System.getProperty("java.io.tmpdir"); private static final String TMP_RESIZED_ARTWORK = TMP_DIR + "/resized.jpg"; + private static final int TARGET_SIZE = 80; public static final String FILE_CMD_LONG_OPTION = "file"; @@ -40,10 +43,9 @@ public static void main(String[] args) throws IOException, CannotReadException, // init cleanup if files already exist var tmpResizedFile = new File(TMP_RESIZED_ARTWORK); - FileUtils.deleteQuietly(new File(Img2Ascii.TMP_ASCIIART_TXT)); FileUtils.deleteQuietly(tmpResizedFile); - // CLI handgling + // CLI handling var options = new Options(); var input = new Option("f", FILE_CMD_LONG_OPTION, true, "input file path which containe the artwork to print"); input.setRequired(true); @@ -61,22 +63,38 @@ public static void main(String[] args) throws IOException, CannotReadException, System.exit(1); } - // main process - var audioFile = new File(cmd.getOptionValue(FILE_CMD_LONG_OPTION)); - var extractedArtwork = AudioFileIO.read(audioFile) - .getTag() - .getFirstArtwork() - .getImage(); + try { + // extract artwork + var audioFile = new File(cmd.getOptionValue(FILE_CMD_LONG_OPTION)); + var extractedArtwork = AudioFileIO.read(audioFile) + .getTag() + .getFirstArtwork() + .getImage(); + + // resize and save tmp artwork + var scaledArtwork = ((BufferedImage) extractedArtwork).getScaledInstance(TARGET_SIZE, TARGET_SIZE, Image.SCALE_DEFAULT); + var resized = new BufferedImage(TARGET_SIZE, TARGET_SIZE, BufferedImage.TYPE_INT_RGB); + resized.getGraphics().drawImage(scaledArtwork, 0, 0, null); - var scaledArtwork = ((BufferedImage) extractedArtwork).getScaledInstance(TARGET_SIZE, TARGET_SIZE, Image.SCALE_DEFAULT); - var resized = new BufferedImage(TARGET_SIZE, TARGET_SIZE, BufferedImage.TYPE_INT_RGB); - resized.getGraphics().drawImage(scaledArtwork, 0, 0, null); + ImageIO.write(resized, "png", tmpResizedFile); - ImageIO.write(resized, "png", tmpResizedFile); + // tmp artwork to ascii art + var symbols = new String[]{" ", ".", "-", "I", "W", "@"}; + var parserConfig = ParserBuilder.startBuild() + .parserAlgorithm(Algorithms.HUMAN_EYE_ALGORITHM) + .scaled() + .height(TARGET_SIZE) + .width(TARGET_SIZE) + .getScale() + .symbols(symbols) + .colorAlgorithm(DefaultColorType.ANSI) + .build(); - var img2Ascii = new Img2Ascii(); - img2Ascii.convertToAscii(TMP_RESIZED_ARTWORK); + var asciiArt = AsciiParser.parse(TMP_RESIZED_ARTWORK, parserConfig); - System.out.println(Files.readString(Path.of(Img2Ascii.TMP_ASCIIART_TXT))); + System.out.println(asciiArt); + } finally { + FileUtils.deleteQuietly(tmpResizedFile); + } } } diff --git a/src/main/java/com/mpalourdio/projects/flhacker/Img2Ascii.java b/src/main/java/com/mpalourdio/projects/flhacker/Img2Ascii.java deleted file mode 100644 index f22bfed..0000000 --- a/src/main/java/com/mpalourdio/projects/flhacker/Img2Ascii.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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. - */ - -package com.mpalourdio.projects.flhacker; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; - -import static com.mpalourdio.projects.flhacker.FlhackerApplication.TMP_DIR; - -public class Img2Ascii { - - static final String TMP_ASCIIART_TXT = TMP_DIR + "/asciiart.txt"; - private final PrintWriter prntwrt; - private final FileWriter filewrt; - - public Img2Ascii() throws IOException { - filewrt = new FileWriter(TMP_ASCIIART_TXT, false); - prntwrt = new PrintWriter(filewrt); - } - - public void convertToAscii(String imgname) throws IOException { - var img = ImageIO.read(new File(imgname)); - - for (var i = 0; i < img.getHeight(); i++) { - for (var j = 0; j < img.getWidth(); j++) { - var pixcol = new Color(img.getRGB(j, i)); - var pixval = (pixcol.getRed() * 0.30) + (pixcol.getBlue() * 0.59) + (pixcol.getGreen() * 0.11); - print(strChar(pixval)); - } - prntwrt.println(""); - prntwrt.flush(); - filewrt.flush(); - } - } - - private String strChar(double g) { - var str = " "; - if (g >= 240) { - str = " "; - } else if (g >= 210) { - str = "."; - } else if (g >= 190) { - str = "*"; - } else if (g >= 170) { - str = "+"; - } else if (g >= 120) { - str = "^"; - } else if (g >= 110) { - str = "&"; - } else if (g >= 80) { - str = "8"; - } else if (g >= 60) { - str = "#"; - } else { - str = "@"; - } - return str; - } - - private void print(String str) throws IOException { - prntwrt.print(str); - prntwrt.flush(); - filewrt.flush(); - } -} diff --git a/src/main/resources/META-INF/native-image/reflect-config.json b/src/main/resources/META-INF/native-image/reflect-config.json index b4b8916..a1b107e 100644 --- a/src/main/resources/META-INF/native-image/reflect-config.json +++ b/src/main/resources/META-INF/native-image/reflect-config.json @@ -76,6 +76,9 @@ { "name":"jakarta.validation.Validator" }, +{ + "name":"java.awt.image.ColorConvertOp" +}, { "name":"java.io.FilePermission" }, @@ -124,6 +127,9 @@ "name":"java.net.URLPermission", "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] }, +{ + "name":"java.nio.ByteBuffer" +}, { "name":"java.security.AllPermission" }, @@ -243,6 +249,10 @@ "name":"org.jaudiotagger.tag.datatype.PartOfSet", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.datatype.PartOfSet"] }] }, +{ + "name":"org.jaudiotagger.tag.datatype.StringHashMap", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.datatype.StringHashMap"] }] +}, { "name":"org.jaudiotagger.tag.datatype.StringNullTerminated", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.datatype.StringNullTerminated"] }] @@ -263,6 +273,18 @@ "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC"] }] }, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC"] }, {"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyPIC"] }] +}, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyAPIC"] }, {"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyPIC"] }] +}, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyCOMM", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyCOMM"] }] +}, { "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyMCDI", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyMCDI"] }] @@ -271,6 +293,10 @@ "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTALB", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTALB"] }] }, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTCOM", + "methods":[{"name":"","parameterTypes":["java.nio.ByteBuffer","int"] }, {"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTCOM"] }] +}, { "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTCON", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTCON"] }] @@ -283,6 +309,10 @@ "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTDRC", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTYER"] }] }, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTENC", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTENC"] }] +}, { "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTIT2", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTIT2"] }] @@ -307,6 +337,14 @@ "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTPOS", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTPOS"] }] }, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTRCK", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTRCK"] }] +}, +{ + "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTYER", + "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTYER"] }] +}, { "name":"org.jaudiotagger.tag.id3.framebody.FrameBodyTPUB", "methods":[{"name":"","parameterTypes":["org.jaudiotagger.tag.id3.framebody.FrameBodyTPUB"] }]