From 96f992222810d6e1ad58991148a85e1589afffa8 Mon Sep 17 00:00:00 2001 From: Yannic Link Date: Sat, 3 Apr 2021 20:16:58 +0200 Subject: [PATCH] =?UTF-8?q?Pat=20Command=20l=C3=A4uft=20jetzt=20auch=20ohn?= =?UTF-8?q?e=20Python=20sondern=20in=20reinem=20Java?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yoshibot/command/commands/PatCommand.java | 107 ++++++------ .../yoshibot/utils/GifSequenceWriter.java | 153 ++++++++++++++++++ .../yoshibot/utils/Resources.java | 8 - rsc/pat.py | 34 ---- 4 files changed, 209 insertions(+), 93 deletions(-) create mode 100644 app/src/main/java/de/yannicpunktdee/yoshibot/utils/GifSequenceWriter.java delete mode 100644 rsc/pat.py diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PatCommand.java b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PatCommand.java index 412d9a4..714acd2 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PatCommand.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/command/commands/PatCommand.java @@ -2,20 +2,21 @@ package de.yannicpunktdee.yoshibot.command.commands; import de.yannicpunktdee.yoshibot.command.YoshiCommand; import de.yannicpunktdee.yoshibot.command.YoshiCommandContext; -import de.yannicpunktdee.yoshibot.utils.Logger; +import de.yannicpunktdee.yoshibot.utils.GifSequenceWriter; import de.yannicpunktdee.yoshibot.utils.Resources; import net.dv8tion.jda.api.entities.Message; -import java.io.BufferedReader; +import javax.imageio.ImageIO; +import javax.imageio.stream.FileImageOutputStream; +import javax.imageio.stream.ImageOutputStream; +import java.awt.*; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class PatCommand extends YoshiCommand { @@ -28,57 +29,61 @@ public class PatCommand extends YoshiCommand { if (!super.execute()) return false; List attachments = context.getEvent().getMessage().getAttachments(); - String path = ""; - if (context.containsArguments(new String[]{"name"})) { - path = Resources.getImagePath() + context.getArgument("name") + ".png"; - File image = new File(path); - if (!image.exists()) { - sendMessage("Bilddatei existiert nicht."); - return false; - } - } else if (attachments.size() == 1) { - path = Resources.getTempPath() + UUID.randomUUID().toString() + ".png"; - CompletableFuture future = attachments.get(0).downloadToFile(path); - future.exceptionally(e -> { - sendMessage("Der Anhang konnte nicht gedownloaded werden."); - return null; - }); - try { - future.get(); - sendMessage("Bild erfolgreich heruntergeladen."); - } catch (InterruptedException | ExecutionException e) { - sendMessage("Die Bilddatei konnte nicht ordnungsgemäß erstellt werden."); - return false; - } - } else { + if(attachments.size() != 1){ + sendMessage("Um dieses Kommando auszuführen benötigt es EINE Bilddatei."); return false; } - - String outPath = Resources.getTempPath().replace('\\', '/') + UUID.randomUUID().toString() + ".gif"; + Message.Attachment attachment = attachments.get(0); + + String inPath = + Resources.getTempPath() + + UUID.randomUUID().toString() + + "." + attachment.getFileExtension(); + File outFile = new File(Resources.getTempPath() + UUID.randomUUID().toString() + ".gif"); + + CompletableFuture future = attachment.downloadToFile(inPath); + future.exceptionally(e -> { + sendMessage("Der Anhang konnte nicht gedownloaded werden."); + return null; + }); try { - ProcessBuilder pb = new ProcessBuilder( - "python3", - Resources.getPatPath(), - "--image", - path, - "--patfolder", - Resources.getPatPngPath(), - "--out", - outPath); - - Process p = pb.start(); - String error = new BufferedReader(new InputStreamReader(p.getErrorStream())).lines().collect( - Collectors.joining()); - if (error.length() > 0) { - Logger.log(error, Logger.Type.ERROR); - } - p.waitFor(); - System.out.println(outPath); - context.getEvent().getTextChannel().sendFile(new File(outPath)).queue(); - } catch (IOException | InterruptedException e) { + future.get(); + } catch (InterruptedException | ExecutionException e) { + sendMessage("Die Bilddatei konnte nicht ordnungsgemäß erstellt werden."); return false; } - + + try { + BufferedImage inPicture= ImageIO.read(new File(inPath)); + BufferedImage pat1Picture= ImageIO.read(new File(Resources.getPatPngPath() + "pat1.png")); + BufferedImage pat2Picture= ImageIO.read(new File(Resources.getPatPngPath() + "pat2.png")); + BufferedImage pat3Picture= ImageIO.read(new File(Resources.getPatPngPath() + "pat3.png")); + BufferedImage frame1 = getOutFrame(pat1Picture, inPicture, 100, 100, 400, 400); + ImageOutputStream output = new FileImageOutputStream(outFile); + GifSequenceWriter writer = new GifSequenceWriter(output, frame1.getType(), 100, true); + writer.writeToSequence(frame1); + writer.writeToSequence(getOutFrame(pat2Picture, inPicture, 100, 70, 400, 430)); + writer.writeToSequence(getOutFrame(pat3Picture, inPicture, 100, 50, 400, 450)); + writer.close(); + output.close(); + } catch (IOException e) { + sendMessage("Gif konnte nicht erstellt werden,"); + e.printStackTrace(); + return false; + } + + context.getEvent().getTextChannel().sendFile(outFile).queue(); + return true; } + + private BufferedImage getOutFrame(BufferedImage patHandGraphics, BufferedImage personGraphics, int x, int y, int width, int height){ + BufferedImage outFrame = new BufferedImage(500, 500, BufferedImage.TYPE_INT_RGB); + Graphics2D g = outFrame.createGraphics(); + g.setColor(Color.black); + g.drawImage(personGraphics, x, y, width, height, null); + g.drawImage(patHandGraphics, 0, 0, 500, 400, null); + return outFrame; + } + } diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/utils/GifSequenceWriter.java b/app/src/main/java/de/yannicpunktdee/yoshibot/utils/GifSequenceWriter.java new file mode 100644 index 0000000..6aaa5ab --- /dev/null +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/utils/GifSequenceWriter.java @@ -0,0 +1,153 @@ +package de.yannicpunktdee.yoshibot.utils; + +// +// GifSequenceWriter.java +// +// Created by Elliot Kroo on 2009-04-25. +// +// This work is licensed under the Creative Commons Attribution 3.0 Unported +// License. To view a copy of this license, visit +// http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative +// Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + + +import javax.imageio.*; +import javax.imageio.metadata.*; +import javax.imageio.stream.*; +import java.awt.image.*; +import java.io.*; +import java.util.Iterator; + +public class GifSequenceWriter { + protected ImageWriter gifWriter; + protected ImageWriteParam imageWriteParam; + protected IIOMetadata imageMetaData; + + /** + * Creates a new GifSequenceWriter + * + * @param outputStream the ImageOutputStream to be written to + * @param imageType one of the imageTypes specified in BufferedImage + * @param timeBetweenFramesMS the time between frames in miliseconds + * @param loopContinuously wether the gif should loop repeatedly + * @throws IIOException if no gif ImageWriters are found + * @author Elliot Kroo (elliot[at]kroo[dot]net) + */ + public GifSequenceWriter( + ImageOutputStream outputStream, + int imageType, + int timeBetweenFramesMS, + boolean loopContinuously) throws IIOException, IOException { + // my method to create a writer + gifWriter = getWriter(); + imageWriteParam = gifWriter.getDefaultWriteParam(); + ImageTypeSpecifier imageTypeSpecifier = + ImageTypeSpecifier.createFromBufferedImageType(imageType); + + imageMetaData = + gifWriter.getDefaultImageMetadata(imageTypeSpecifier, + imageWriteParam); + + String metaFormatName = imageMetaData.getNativeMetadataFormatName(); + + IIOMetadataNode root = (IIOMetadataNode) + imageMetaData.getAsTree(metaFormatName); + + IIOMetadataNode graphicsControlExtensionNode = getNode( + root, + "GraphicControlExtension"); + + graphicsControlExtensionNode.setAttribute("disposalMethod", "none"); + graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE"); + graphicsControlExtensionNode.setAttribute( + "transparentColorFlag", + "FALSE"); + graphicsControlExtensionNode.setAttribute( + "delayTime", + Integer.toString(timeBetweenFramesMS / 10)); + graphicsControlExtensionNode.setAttribute( + "transparentColorIndex", + "0"); + + IIOMetadataNode commentsNode = getNode(root, "CommentExtensions"); + commentsNode.setAttribute("CommentExtension", "Created by MAH"); + + IIOMetadataNode appEntensionsNode = getNode( + root, + "ApplicationExtensions"); + + IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension"); + + child.setAttribute("applicationID", "NETSCAPE"); + child.setAttribute("authenticationCode", "2.0"); + + int loop = loopContinuously ? 0 : 1; + + child.setUserObject(new byte[]{0x1, (byte) (loop & 0xFF), (byte) + ((loop >> 8) & 0xFF)}); + appEntensionsNode.appendChild(child); + + imageMetaData.setFromTree(metaFormatName, root); + + gifWriter.setOutput(outputStream); + + gifWriter.prepareWriteSequence(null); + } + + public void writeToSequence(RenderedImage img) throws IOException { + gifWriter.writeToSequence( + new IIOImage( + img, + null, + imageMetaData), + imageWriteParam); + } + + /** + * Close this GifSequenceWriter object. This does not close the underlying + * stream, just finishes off the GIF. + */ + public void close() throws IOException { + gifWriter.endWriteSequence(); + } + + /** + * Returns the first available GIF ImageWriter using + * ImageIO.getImageWritersBySuffix("gif"). + * + * @return a GIF ImageWriter object + * @throws IIOException if no GIF image writers are returned + */ + private static ImageWriter getWriter() throws IIOException { + Iterator iter = ImageIO.getImageWritersBySuffix("gif"); + if (!iter.hasNext()) { + throw new IIOException("No GIF Image Writers Exist"); + } else { + return iter.next(); + } + } + + /** + * Returns an existing child node, or creates and returns a new child node (if + * the requested node does not exist). + * + * @param rootNode the IIOMetadataNode to search for the child node. + * @param nodeName the name of the child node. + * @return the child node, if found or a new node created with the given name. + */ + private static IIOMetadataNode getNode( + IIOMetadataNode rootNode, + String nodeName) { + int nNodes = rootNode.getLength(); + for (int i = 0; i < nNodes; i++) { + if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) + == 0) { + return ((IIOMetadataNode) rootNode.item(i)); + } + } + IIOMetadataNode node = new IIOMetadataNode(nodeName); + rootNode.appendChild(node); + return (node); + } + +} diff --git a/app/src/main/java/de/yannicpunktdee/yoshibot/utils/Resources.java b/app/src/main/java/de/yannicpunktdee/yoshibot/utils/Resources.java index 6190f67..9b3c9f2 100644 --- a/app/src/main/java/de/yannicpunktdee/yoshibot/utils/Resources.java +++ b/app/src/main/java/de/yannicpunktdee/yoshibot/utils/Resources.java @@ -37,8 +37,6 @@ public final class Resources { @Getter private static String ttsPath; @Getter - private static String patPath; - @Getter private static String patPngPath; @Getter private static String imagePath; @@ -78,7 +76,6 @@ public final class Resources { if (isOk) isOk = initGuildId(); if (isOk) isOk = initChannelRestrict(); if (isOk) isOk = initTagFilter(); - if (isOk) isOk = initPat(); if (isOk) isOk = initPatPngPath(); if (isOk) isOk = initImages(); @@ -258,11 +255,6 @@ public final class Resources { return true; } - private static boolean initPat() { - patPath = verifyExists(resourcePath + "pat.py", File::isFile); - return patPath != null; - } - private static boolean initImages() { imagePath = verifyExists(resourcePath + "image/", File::isDirectory); if (imagePath != null) { diff --git a/rsc/pat.py b/rsc/pat.py deleted file mode 100644 index 9c21408..0000000 --- a/rsc/pat.py +++ /dev/null @@ -1,34 +0,0 @@ -import argparse -from PIL import Image, ImageDraw, ImageFilter - -parser = argparse.ArgumentParser() -parser.add_argument("--patfolder") -parser.add_argument("--image") -parser.add_argument("--out") -args = parser.parse_args() - -patfolder = args.patfolder -personImage = args.image -outPath = args.out - -frame1 = Image.open(patfolder + "pat1.png").resize((500, 400)) -frame2 = Image.open(patfolder + "pat2.png").resize((500, 400)) -frame3 = Image.open(patfolder + "pat3.png").resize((500, 400)) - -person1 = Image.open(personImage).resize((400,400)) -person2 = Image.open(personImage).resize((400,430)) -person3 = Image.open(personImage).resize((400,450)) - -image1 = Image.new('RGBA', (500,500)) -image1.paste(person1, (100,100)) -image1.paste(frame1, (0,0), frame1) - -image2 = Image.new('RGBA', (500,500)) -image2.paste(person2, (100,70)) -image2.paste(frame2, (0,0), frame2) - -image3 = Image.new('RGBA', (500,500)) -image3.paste(person3, (100,50)) -image3.paste(frame3, (0,0), frame3) - -image1.save(outPath, save_all=True,append_images=[image2,image3],optimize=False,duration=100,loop=0) \ No newline at end of file