From d4463b33342ccb5ea86c2a2c9da37b9b861b6674 Mon Sep 17 00:00:00 2001 From: nextdaydelivery <79922345+nxtdaydelivery@users.noreply.github.com> Date: Thu, 23 Jun 2022 17:54:47 +0100 Subject: image stuff --- .../java/cc/polyfrost/oneconfig/images/Image.java | 284 +++++++++++++++++++++ .../oneconfig/internal/assets/Colors.java | 30 +++ .../polyfrost/oneconfig/renderer/AssetLoader.java | 34 ++- 3 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 src/main/java/cc/polyfrost/oneconfig/images/Image.java (limited to 'src/main/java') diff --git a/src/main/java/cc/polyfrost/oneconfig/images/Image.java b/src/main/java/cc/polyfrost/oneconfig/images/Image.java new file mode 100644 index 0000000..9cc75a0 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/images/Image.java @@ -0,0 +1,284 @@ +package cc.polyfrost.oneconfig.images; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; + +/** An Image wrapper class that is used by the OneConfig system.*/ +@SuppressWarnings("unused") +public class Image { + private BufferedImage image; + private Graphics2D graphics = null; + private final int width, height; + + + /** + * Create a new Image from the file. This can be as a resource location inside your JAR. + * @param filePath The path to the image file. + */ + public Image(String filePath) throws IOException { + image = ImageIO.read(Objects.requireNonNull(Image.class.getResourceAsStream(filePath))); + width = image.getWidth(); + height = image.getHeight(); + } + + /** + * Create a new Image from the file. + * @param is InputStream to the image file. + */ + public Image(InputStream is) throws IOException { + image = ImageIO.read(is); + width = image.getWidth(); + height = image.getHeight(); + } + + /** + * Create a new Image from the file. + * @param file File to the image file. + */ + public Image(File file) throws IOException { + image = ImageIO.read(Objects.requireNonNull(file)); + width = image.getWidth(); + height = image.getHeight(); + } + + /** + * Create a new Image from the BufferedImage. + */ + public Image(BufferedImage image) { + this.image = image; + width = image.getWidth(); + height = image.getHeight(); + } + + /** Create a new blank image with the specified width and height. */ + public Image(int width, int height) { + this.width = width; + this.height = height; + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + } + + /** Get the image as a BufferedImage. */ + public BufferedImage getImage() { + return image; + } + + protected void setImage(BufferedImage img) { + image = img; + } + + /** Get the graphics object associated with the image. */ + public Graphics2D getG2D() { + if (graphics == null) { + graphics = image.createGraphics(); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + } + return graphics; + } + + + /** Dispose of the graphics object. */ + public void dispose() { + if(graphics != null) { + graphics.dispose(); + graphics = null; + } + } + + /** Get the width of the image. */ + public int getWidth() { + return width; + } + + /** Get the height of the image. */ + public int getHeight() { + return height; + } + + /** Crop the image to the specified width and height. + * @param startX The x coordinate of the top-left corner of the crop. + * @param startY The y coordinate of the top-left corner of the crop. + * @param width The width of the crop. + * @param height The height of the crop. + */ + public void crop(int startX, int startY, int width, int height) { + image = image.getSubimage(startX, startY, width, height); + } + + /** Get the color of a pixel in the image. */ + public void getColorAtPos(int x, int y) { + image.getRGB(x, y); + } + + /** Set the color of a pixel in the image. */ + public void setColorAtPos(int x, int y, int argb) { + image.setRGB(x, y, argb); + } + + /** Attempt to save the image to the specified file. */ + public void save(String filePath) throws IOException { + ImageIO.write(image, "png", new File(filePath)); + } + + + + + // MASK METHODS + public void setBrightness(float brightness) { + maskColor(new Color(0f,0f,0f,brightness)); + } + + public void maskColor(Color color) { + Graphics2D g2d = getG2D(); + g2d.setColor(color); + g2d.fillRect(0,0,width,height); + dispose(); + } + + public void maskPaint(Paint paint) { + Graphics2D g2d = getG2D(); + g2d.setPaint(paint); + g2d.fillRect(0,0,width,height); + dispose(); + } + + + + + + + // LINE METHODS + public void drawLine(Stroke stroke, int sx, int sy, int ex, int ey) { + Graphics2D g2d = getG2D(); + g2d.setStroke(stroke); + g2d.drawLine(sx, sy, ex, ey); + dispose(); + } + + public void drawLine(int sx, int sy, int ex, int ey, int width) { + drawLine(new BasicStroke(width), sx, sy, ex, ey); + } + + + + + + // SHAPE METHODS + public void drawTexturedRect(TexturePaint paint, int x, int y, int width, int height) { + Graphics2D g2d = getG2D(); + g2d.setPaint(paint); + g2d.fillRect(x, y, width, height); + dispose(); + } + + public void drawRect(int x, int y, int width, int height, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.drawRect(x, y, width, height); + dispose(); + } + public void drawRoundedRect(int x, int y, int width, int height, int radius, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.fillRoundRect(x, y, width, height, radius, radius); + dispose(); + } + + public void drawPolygon(int x, int y, Polygon polygon, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.translate(x, y); + g2d.fillPolygon(polygon); + dispose(); + } + + public void drawOval(int x, int y, int width, int height, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.fillOval(x, y, width, height); + dispose(); + } + + public void drawTriangle(Point p1, Point p2, Point p3, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.fillPolygon(new int[] {p1.x, p2.x, p3.x}, new int[] {p1.y, p2.y, p3.y}, 3); + dispose(); + } + + public void drawCircle(int x, int y, int radius, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.fillRoundRect(x, y, radius, radius, radius, radius); + dispose(); + } + + + + + + + // STRING METHODS + public void drawString(String text, int x, int y, Font font, int color) { + Graphics2D g2d = getG2D(); + g2d.setColor(new Color(color, true)); + g2d.setFont(font); + g2d.drawString(text, x, y); + dispose(); + } + + + + // IMAGE METHODS + /** Scale the image by the given factor (1.0 = no change). */ + public void scale(double sx, double sy) { + if(sx == 1.0 && sy == 1.0) return; + BufferedImage old = image; + image = new BufferedImage((int) (Math.abs(sx * image.getWidth())), (int) (Math.abs(image.getHeight() * sy)), BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = getG2D(); + g2d.drawImage(old, new AffineTransformOp(AffineTransform.getScaleInstance(sx, sy), AffineTransformOp.TYPE_BILINEAR), 0, 0); + dispose(); + } + /** + * Scale the image to the specified width and height. + */ + public void setSize(int width, int height) { + if(width == this.width && height == this.height) return; + scale(width / (double) this.width, height / (double) this.height); + } + + /** Rotate the image by the given angle (in degrees). */ + public void rotate(double angle) { + if(angle == 0 || angle == 360) return; + Graphics2D g2d = getG2D(); + g2d.drawImage(image, new AffineTransformOp(AffineTransform.getRotateInstance(Math.toRadians(angle)), AffineTransformOp.TYPE_BILINEAR), 0, 0); + dispose(); + } + + /** Translate the image by the given amount. */ + public void translate(int moveX, int moveY) { + Graphics2D g2d = getG2D(); + g2d.drawImage(image, new AffineTransformOp(AffineTransform.getTranslateInstance(moveX, moveY), AffineTransformOp.TYPE_BILINEAR), 0, 0); + dispose(); + } + + /** Flip the image horizontally. */ + public void flipHorizontal() { + scale(-1, 1); + } + + /** Flip the image vertically. */ + public void flipVertical() { + scale(1, -1); + } + + + + + +} diff --git a/src/main/java/cc/polyfrost/oneconfig/internal/assets/Colors.java b/src/main/java/cc/polyfrost/oneconfig/internal/assets/Colors.java index 49a4ca3..84f766f 100644 --- a/src/main/java/cc/polyfrost/oneconfig/internal/assets/Colors.java +++ b/src/main/java/cc/polyfrost/oneconfig/internal/assets/Colors.java @@ -2,6 +2,7 @@ package cc.polyfrost.oneconfig.internal.assets; import java.awt.*; +@SuppressWarnings("unused") public class Colors { // the color library public static final int TRANSPARENT = new Color(0, 0, 0, 0).getRGB(); // Transparent @@ -44,4 +45,33 @@ public class Colors { public static boolean ROUNDED_CORNERS = true; public static final float CORNER_RADIUS_WIN = 20f; public static final float CORNER_RADIUS = 12f; + + /** List of all colors used by Minecraft in its code. + * Source: Click Here + * */ + public static class MinecraftColors { + /** Letter Code used before colors in Minecraft */ + public static final String CODE = "\u00a7"; + + public static final String RESET = "\u00a70"; + + public static final int DARK_RED = new Color(170, 0, 0).getRGB(); // Mapped to 4 + public static final int RED = new Color(255, 85, 85).getRGB(); // Mapped to c + public static final int GOLD = new Color(255, 170, 0).getRGB(); // Mapped to 6 + public static final int YELLOW = new Color(255, 255, 85).getRGB(); // Mapped to e + public static final int DARK_GREEN = new Color(0, 170, 0).getRGB(); // Mapped to 2 + public static final int GREEN = new Color(85, 255, 85).getRGB(); // Mapped to a + public static final int AQUA = new Color(85, 255, 255).getRGB(); // Mapped to b + public static final int DARK_AQUA = new Color(0, 170, 170).getRGB(); // Mapped to 3 + public static final int DARK_BLUE = new Color(0, 0, 170).getRGB(); // Mapped to 1 + public static final int BLUE = new Color(85, 85, 255).getRGB(); // Mapped to 9 + public static final int LIGHT_PURPLE = new Color(255, 85, 255).getRGB(); // Mapped to d + public static final int DARK_PURPLE = new Color(170, 0, 170).getRGB(); // Mapped to 5 + public static final int WHITE = new Color(255, 255, 255).getRGB(); // Mapped to f + public static final int GRAY = new Color(170, 170, 170).getRGB(); // Mapped to 7 + public static final int DARK_GRAY = new Color(85, 85, 85).getRGB(); // Mapped to 8 + public static final int BLACK = new Color(0, 0, 0).getRGB(); // Mapped to 0 + + + } } diff --git a/src/main/java/cc/polyfrost/oneconfig/renderer/AssetLoader.java b/src/main/java/cc/polyfrost/oneconfig/renderer/AssetLoader.java index ee6c326..379a3e2 100644 --- a/src/main/java/cc/polyfrost/oneconfig/renderer/AssetLoader.java +++ b/src/main/java/cc/polyfrost/oneconfig/renderer/AssetLoader.java @@ -3,17 +3,22 @@ package cc.polyfrost.oneconfig.renderer; import cc.polyfrost.oneconfig.internal.assets.Images; import cc.polyfrost.oneconfig.internal.assets.SVGs; import cc.polyfrost.oneconfig.utils.IOUtils; +import org.lwjgl.BufferUtils; import org.lwjgl.nanovg.NSVGImage; import org.lwjgl.nanovg.NanoSVG; import org.lwjgl.nanovg.NanoVG; import org.lwjgl.stb.STBImage; import org.lwjgl.system.MemoryUtil; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.ByteBuffer; +import java.nio.IntBuffer; import java.util.HashMap; +import java.util.Objects; /** * Loads images and SVGs from resources into NanoVG. @@ -36,7 +41,7 @@ public final class AssetLoader { * * @param vg The NanoVG context. * @param fileName The name of the file to load. - * @return Whether the assets was loaded successfully. + * @return Whether the asset was loaded successfully. */ public boolean loadImage(long vg, String fileName) { if (!imageHashMap.containsKey(fileName)) { @@ -189,4 +194,31 @@ public final class AssetLoader { svgHashMap.remove(image); } } + + /** + * Convert the given image (as a quantified path) to an IntBuffer, of its pixels, in order, stored as integers in ARGB format. + * Mostly an internal method; used by LWJGL. + * @param fileName quantified path to the image + * @return intBuffer of the image's pixels in ARGB format + */ + public IntBuffer imageToIntBuffer(String fileName) { + try { + InputStream inputStream = this.getClass().getResourceAsStream(fileName); + BufferedImage img = ImageIO.read(Objects.requireNonNull(inputStream)); + int width = img.getWidth(); + int height = img.getHeight(); + IntBuffer intBuffer = BufferUtils.createIntBuffer(256); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + intBuffer.put(img.getRGB(x, y)); + } + } + return intBuffer; + } catch (Exception e) { + e.printStackTrace(); + System.err.println("Failed to load asset: " + fileName); + return BufferUtils.createIntBuffer(256); + } + + } } -- cgit