diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d39678 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +target +*.bat +*.cmd +*.png +*.mkv +nbactions.xml diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8d4b554 --- /dev/null +++ b/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + com.tmworks + telopGenerator + 1.0.0 + jar + + + club.tmworks + telopeditor + 1.0 + + + com.tmworks + lyricsmovie + + + + + + UTF-8 + 11 + 11 + + \ No newline at end of file diff --git a/src/main/java/com/tmworks/telopgenerator/PngGenerator.java b/src/main/java/com/tmworks/telopgenerator/PngGenerator.java new file mode 100644 index 0000000..187d6f6 --- /dev/null +++ b/src/main/java/com/tmworks/telopgenerator/PngGenerator.java @@ -0,0 +1,230 @@ +/* + * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license + * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template + */ +package com.tmworks.telopgenerator; + +import club.tmworks.telopeditor.model.ProjectInfo; +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ConvolveOp; +import java.awt.image.Kernel; +import java.io.File; +import java.io.IOException; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * + * @author bythe + */ +public class PngGenerator { + + int width = 1920; + int height = 1080; + + int fontSize = 96; + + int shadingSize = 30; + + Color fontColor = Color.white; + + Color shadingColor = Color.BLACK; + + Font fontFront = new Font("HGP明朝E", Font.PLAIN, fontSize); + Font fontShading = new Font("HGP明朝E", Font.PLAIN, fontSize); + + private String locationVertical = ""; + private String locationHorizontal = ""; + + public PngGenerator() { + + } + + public void setLocation(String vertical, String horizontal) { + this.locationVertical = vertical; + this.locationHorizontal = horizontal; + } + + public void setShadingSize(int size) { + this.shadingSize = size; + } + + public void setFontFront(String fontName, int fontStyle, int fontSize) { + this.fontFront = new Font(fontName, fontStyle, fontSize); + } + + public void setFontShading(String fontName, int fontStyle, int fontSize) { + this.fontShading = new Font(fontName, fontStyle, fontSize); + } + + public void setFontName(String fontName) { + this.fontFront = new Font(fontName, this.fontFront.getStyle(), this.fontSize); + this.fontShading = new Font(fontName, this.fontFront.getStyle(), this.fontSize); + } + + public void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + public void setFontSize(int size) { + this.fontSize = size; + this.fontFront = this.fontFront.deriveFont(Float.valueOf(this.fontSize)); + this.fontShading = this.fontFront.deriveFont(Float.valueOf(this.fontSize)); + } + + public void generate(String fileName, String text) { + try { + BufferedImage img = this.getTelopImage(text); + + ImageIO.write(img, "png", new File(fileName)); + } catch (IOException e) { + Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, (Supplier) e); + } + } + + /** + * センタリング時の描画開始点X座標 + * + * @param text + * @return + */ + public float getCenteringLocationX(String text) { + if (text.length() < 1) { + return 0f; + } + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g2d = img.createGraphics(); + FontRenderContext frc = g2d.getFontRenderContext(); + TextLayout layout = new TextLayout(text, this.fontFront, frc); + Rectangle2D rect = layout.getBounds(); + + float margine = 0f; + switch (this.locationHorizontal) { + case ProjectInfo.HORIZONTAL_LEFT: + margine = (float) rect.getWidth() / text.length(); + break; + case ProjectInfo.HORIZONTAL_CENTER: + margine = ((float) (this.width - rect.getWidth())) / 2.0f; + break; + case ProjectInfo.HORIZOTAL_RIGHT: + margine = (float) this.width - (float) rect.getWidth() - (float) rect.getWidth() / (float) text.length(); + break; + } + return margine; + } + + public float getCenteringLocationY(String text) { + if (text.length() < 1) { + return 0f; + } + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g2d = img.createGraphics(); + FontRenderContext frc = g2d.getFontRenderContext(); + TextLayout layout = new TextLayout(text, this.fontFront, frc); + Rectangle2D rect = layout.getBounds(); + + float margine = 0f; + switch (this.locationVertical) { + case ProjectInfo.VERTICAL_TOP: + margine = (float) rect.getHeight() * 2.0f; + break; + case ProjectInfo.VERTICAL_CENTER: + margine = ((float) (img.getHeight() - rect.getHeight())) / 2.0f; + margine = (float) rect.getHeight() + margine; + break; + case ProjectInfo.VERTICAL_BOTTOM: + margine = ((float) (img.getHeight()) - (float) rect.getHeight() * 1.5f); + break; + } + + return margine; + } + + private void modfySize(String text) { + if (text.length() < 1) { + return; + } + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + Graphics2D g2d = img.createGraphics(); + FontRenderContext frc = g2d.getFontRenderContext(); + TextLayout layout = new TextLayout(text, this.fontFront, frc); + Rectangle2D rect = layout.getBounds(); + if (this.width < rect.getWidth() + this.shadingSize * 2) { + this.width = (int) rect.getWidth() + this.shadingSize * 2; + } + if (this.height < rect.getHeight() + this.shadingSize * 2) { + this.height = (int) rect.getHeight() + this.shadingSize * 2; + } + } + + public BufferedImage getTelopImage(String text) { + + this.modfySize(text); + + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + + Graphics2D g2d = img.createGraphics(); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f)); + Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, img.getHeight(), img.getHeight()); + g2d.fill(rect); + g2d.setPaintMode(); + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + + // ぼかした文字背景 + g2d.setColor(this.shadingColor); + g2d.setFont(this.fontShading); + g2d.drawString(text, this.getCenteringLocationX(text), this.getCenteringLocationY(text)); //文字を書く + img = this.getShadingImage(img, this.shadingSize, 100f); + + // テロップ文字 + g2d = img.createGraphics(); + g2d.setColor(this.fontColor); + g2d.setFont(this.fontFront); + g2d.drawString(text, this.getCenteringLocationX(text), this.getCenteringLocationY(text)); //文字を書く + img = this.getShadingImage(img, 3, 10f); + return img; + } + + /** + * ぼかし + * + * @param im + * @param shadingSize + * @param shardeRate + * @return + */ + public BufferedImage getShadingImage(BufferedImage im, int shadingSize, float shardeRate) { + + int ssize = shadingSize * shadingSize; + + float[] data = new float[ssize]; + for (int i = 0; i < data.length; i++) { + data[i] = 1 / shardeRate; + } + + int w1 = im.getWidth(), h1 = im.getHeight(); + BufferedImage im2 = new BufferedImage(w1, h1, im.getType()); + + Kernel kernel = new Kernel(shadingSize, shadingSize, data); + ConvolveOp op = new ConvolveOp(kernel); + op.filter(im, im2); + + return im2; + } + + public static void main(String[] args) { + new PngGenerator().generate("sample.png", "中々いいでんな。"); + } +}