Utils.java
/*
* ..::jDrawingLib::..
*
* Copyright (C) Federico Vera 2012 - 2023 <[email protected]>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or any later
* version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.dkt.graphics.utils;
import com.dkt.graphics.canvas.Canvas;
import com.dkt.graphics.elements.GraphicE;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
*
* @author Federico Vera {@literal<[email protected]>}
*/
public class Utils {
/**
* Don't let anyone initialize this class
*/
private Utils(){}
/**
* Generates a new {@link Color} based on the color but with the given
* alpha
*
* @param color the original color
* @param alpha the alpha value if the value is bigger than 255 it will be set
* to 255, and if the value is smaller than 0 then it will be set to 0
* @return A new color with the same RGB value as the argument but with the
* specified alpha
* @throws IllegalArgumentException if color is {@code null}
*/
public static Color getColorWithAlpha(Color color, int alpha){
if (color == null){
throw new IllegalArgumentException("Color can't be null!");
}
//Ensure the value is within an interval
int a = Math.max(alpha, 0 );
a = Math.min(a, 255);
final int r = color.getRed ();
final int g = color.getGreen();
final int b = color.getBlue ();
return new Color(r, g, b, a);
}
/**
* Saves a 1:1 screenshot of the canvas<br>
* The image is saved using the {@code png} format, so if the file doesn't
* end with {@code .png} the extension will be appended
*
* @param canvas The {@link Canvas} to print
* @param path The path of the file
* @param back {@code true} if you want to paint the background and {@code
* false} otherwise ({@code false} is needed when painting with transparent
* components.
* @throws IOException If the image can't be written
* @throws IllegalArgumentException If either the canvas or the path are
* {@code null}
*/
public static void saveScreenshot(
Canvas canvas,
String path,
boolean back) throws IOException
{
if (canvas == null){
throw new IllegalArgumentException("Canvas can't be null");
}
if (path == null){
throw new IllegalArgumentException("Path can't be null");
}
final File file = new File(path.endsWith(".png") ? path : path + ".png");
final int width = canvas.getXSize();
final int height = canvas.getYSize();
final BufferedImage img = new BufferedImage(
width,
height,
BufferedImage.TYPE_INT_ARGB
);
final Graphics2D g2d = img.createGraphics();
canvas.paintDrawableArea(g2d, back);
ImageIO.write(img, "png", file);
}
/**
* Retrieves a 1:1 image of the canvas
*
* @param canvas The {@link Canvas} to print
* @param back {@code true} if you want to paint the background and {@code
* false} otherwise ({@code false} is needed when painting with transparent
* components.
* @return a {@link BufferedImage} the same size of the canvas
* @throws IllegalArgumentException If the canvas is {@code null}
*/
public static BufferedImage getImage(Canvas canvas, boolean back) {
if (canvas == null){
throw new IllegalArgumentException("Canvas can't be null");
}
final int width = canvas.getXSize();
final int height = canvas.getYSize();
final BufferedImage img = new BufferedImage(
width,
height,
BufferedImage.TYPE_INT_ARGB
);
final Graphics2D g2d = img.createGraphics();
canvas.paintDrawableArea(g2d, back);
return img;
}
/**
* Trims a given image to its minimum size without loosing any part of the
* drawing.
*
* @param img The image to trim
* @param omit The {@code Color} to omit when trimming (what to consider as
* not drawn). Usually is {@link Color#WHITE} or
* {@code new Color(0, true)}
* @return a {@link BufferedImage} result of trimming the original image
* @throws IllegalArgumentException If {@code img} is {@code null}
*/
public static BufferedImage trimImage(BufferedImage img, Color omit) {
if (img == null){
throw new IllegalArgumentException("The image can't be null");
}
final int w = img.getWidth ();
final int h = img.getHeight();
final int c = omit == null ? 0 : omit.getRGB();
final int[] data = img.getRGB(0, 0, w, h, null, 0, w);
//Search for the image bounds
int l = w;
int r = 0;
int u = h;
int d = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
if (data[i * w + j] != c) {
//Using the unbrached versions of min and max gives a
//significant performance improvement in this case
l = MathUtils.min(l, j);
r = MathUtils.max(r, j);
u = MathUtils.min(u, i);
d = MathUtils.max(d, i);
}
}
}
return img.getSubimage(l, u, r - l, d - u);
}
/**
* Generates a texture from a given file
*
* @param path the path of the image file
* @return A {@link TexturePaint} for this file
* @throws IOException If the image can't be read or if the file isn't a
* valid image
* @throws IllegalArgumentException If the path is {@code null}
*/
public static Paint getTexture(String path) throws IOException {
if (path == null){
throw new IllegalArgumentException("Path can't be null");
}
final File file = new File(path);
final BufferedImage bi = ImageIO.read(file);
final int width = bi.getWidth ();
final int height = bi.getHeight();
final Rectangle2D r2d = new Rectangle(width, height);
return new TexturePaint(bi, r2d);
}
/**
* Draws a {@code GraphicE} into a {@code BufferedImage}
*
* @param e element to draw
* @param w width of the image
* @param h height of the image
* @return a {@code BufferedImage} that represents the {@code GraphicE}
*/
public static BufferedImage draw(GraphicE e, int w, int h) {
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
e.draw(g2d);
g2d.dispose();
return image;
}
}