Last active
September 9, 2023 17:11
-
-
Save NebulaBC/046cf361c6ea175e0cee34b96f7d69f5 to your computer and use it in GitHub Desktop.
Generate a fake discord screenshot in Kotlin. Created for use with a JDA moderation bot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import java.awt.* | |
| import java.awt.geom.AffineTransform | |
| import java.awt.image.BufferedImage | |
| import java.io.File | |
| import java.text.SimpleDateFormat | |
| import java.util.* | |
| object DiscordMessageCreator { | |
| fun generateDiscordScreenshot( | |
| message: String, | |
| name: String, | |
| roleColor: Color, | |
| date: Date, | |
| profilePicture: BufferedImage | |
| ): BufferedImage { | |
| val canvasSize = calculateCanvasSize(message) | |
| val width = canvasSize.first | |
| val height = canvasSize.second | |
| val image = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) | |
| val g2d = image.createGraphics() | |
| prepG2d(g2d, width, height) | |
| val nameOffset = drawNameText(g2d, name, roleColor) | |
| drawDatetime(g2d, date, nameOffset) | |
| drawMessageText(g2d, message) | |
| drawProfilePicture(g2d, profilePicture) | |
| g2d.dispose() | |
| return image | |
| } | |
| private fun prepG2d(g2d: Graphics2D, width: Int, height: Int) { | |
| g2d.setRenderingHint( | |
| RenderingHints.KEY_ANTIALIASING, | |
| RenderingHints.VALUE_ANTIALIAS_ON | |
| ) | |
| g2d.color = Color(54, 57, 63, 255) | |
| g2d.fillRect(0, 0, width, height) | |
| } | |
| private fun drawDatetime(g2d: Graphics2D, date: Date, offset: Int) { | |
| g2d.color = Color(151, 153, 160) | |
| val font = Font.createFont(Font.TRUETYPE_FONT, File("whitneybook.otf")).deriveFont(12F) | |
| g2d.font = font | |
| val x = offset + 5 | |
| val y = 18 | |
| val sdf = SimpleDateFormat() | |
| sdf.timeZone = SimpleTimeZone(0, "GMT") | |
| sdf.applyPattern("dd MMM yyyy HH:mm:ss z") | |
| g2d.drawString(sdf.format(date), x, y) | |
| } | |
| private fun drawNameText(g2d: Graphics2D, name: String, color: Color): Int { | |
| g2d.color = color | |
| val font = Font.createFont(Font.TRUETYPE_FONT, File("whitneybold.otf")).deriveFont(16F) | |
| g2d.font = font | |
| val x = 65 | |
| val y = 18 | |
| g2d.drawString(name, x, y) | |
| return x + getTextWidth(g2d, name, font) | |
| } | |
| private fun drawMessageText(g2d: Graphics2D, message: String) { | |
| g2d.color = Color.WHITE | |
| val font = Font.createFont(Font.TRUETYPE_FONT, File("whitneybook.otf")).deriveFont(16F) | |
| g2d.font = font | |
| val x = 65 | |
| val y = 40 | |
| g2d.drawString(message, x, y) | |
| } | |
| private fun drawProfilePicture(g2d: Graphics2D, overlayImage: BufferedImage) { | |
| val overlayWidth = 48 | |
| val overlayHeight = 48 | |
| val resizedOverlayImage = BufferedImage(overlayWidth, overlayHeight, BufferedImage.TYPE_INT_ARGB) | |
| val g2dOverlay = resizedOverlayImage.createGraphics() | |
| g2dOverlay.setRenderingHint( | |
| RenderingHints.KEY_ANTIALIASING, | |
| RenderingHints.VALUE_ANTIALIAS_ON | |
| ) | |
| val at = AffineTransform.getScaleInstance( | |
| overlayWidth.toDouble() / overlayImage.width, | |
| overlayHeight.toDouble() / overlayImage.height | |
| ) | |
| g2dOverlay.drawRenderedImage(overlayImage, at) | |
| val circleImage = createCircular(resizedOverlayImage, overlayWidth) | |
| val overlayX = 0 | |
| val overlayY = 0 | |
| g2d.drawImage(circleImage, overlayX, overlayY, null) | |
| g2dOverlay.dispose() | |
| } | |
| private fun calculateCanvasSize(text: String): Pair<Int, Int> { | |
| val THUMBNAILSIZE = 48 | |
| val MINWIDTH = 250 | |
| val FONTSIZE = 25 | |
| var deltaWidth = THUMBNAILSIZE + 15 | |
| var width = MINWIDTH | |
| for (paragraph in text.split("\n")) { | |
| val paragraphs = paragraph.length * 9 | |
| if (paragraphs > width) { | |
| width = paragraphs | |
| } | |
| } | |
| val deltaHeight = THUMBNAILSIZE / 2 | |
| val height = text.split("\n").size * FONTSIZE | |
| return Pair(deltaWidth + width, deltaHeight + height) | |
| } | |
| private fun getTextWidth(g2d: Graphics2D, text: String, font: Font): Int { | |
| val fontMetrics: FontMetrics = g2d.getFontMetrics(font) | |
| return fontMetrics.stringWidth(text) | |
| } | |
| private fun createCircular(image: BufferedImage, size: Int): BufferedImage { | |
| val output = BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB) | |
| val g2 = output.createGraphics() | |
| try { | |
| g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON) | |
| g2.fillOval(0, 0, size, size) | |
| g2.composite = AlphaComposite.SrcIn | |
| g2.drawImage(image, 0, 0, null) | |
| } finally { | |
| g2.dispose() | |
| } | |
| return output | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment