diff --git a/src/main/java/com/volmit/iris/core/loader/ImageResourceLoader.java b/src/main/java/com/volmit/iris/core/loader/ImageResourceLoader.java
new file mode 100644
index 000000000..e525e4ffe
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/loader/ImageResourceLoader.java
@@ -0,0 +1,150 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 Arcane Arts (Volmit Software)
+ *
+ * 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
+ * (at your option) 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 .
+ */
+
+package com.volmit.iris.core.loader;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.IrisSettings;
+import com.volmit.iris.engine.object.IrisImage;
+import com.volmit.iris.engine.object.IrisObject;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.collection.KSet;
+import com.volmit.iris.util.data.KCache;
+import com.volmit.iris.util.scheduling.PrecisionStopwatch;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+public class ImageResourceLoader extends ResourceLoader {
+ public ImageResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
+ super(root, idm, folderName, resourceTypeName, IrisImage.class);
+ loadCache = new KCache<>(this::loadRaw, IrisSettings.get().getPerformance().getObjectLoaderCacheSize());
+ }
+
+ public boolean supportsSchemas() {
+ return false;
+ }
+
+ public long getSize() {
+ return loadCache.getSize();
+ }
+
+ public long getTotalStorage() {
+ return getSize();
+ }
+
+ protected IrisImage loadFile(File j, String name) {
+ try {
+ PrecisionStopwatch p = PrecisionStopwatch.start();
+ BufferedImage bu = ImageIO.read(j);
+ IrisImage img = new IrisImage(bu);
+ img.setLoadFile(j);
+ img.setLoader(manager);
+ img.setLoadKey(name);
+ logLoad(j, img);
+ tlt.addAndGet(p.getMilliseconds());
+ return img;
+ } catch (Throwable e) {
+ Iris.reportError(e);
+ Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
+ return null;
+ }
+ }
+
+ public String[] getPossibleKeys() {
+ if (possibleKeys != null) {
+ return possibleKeys;
+ }
+
+ Iris.debug("Building " + resourceTypeName + " Possibility Lists");
+ KSet m = new KSet<>();
+
+ for (File i : getFolders()) {
+ for (File j : i.listFiles()) {
+ if (j.isFile() && j.getName().endsWith(".png")) {
+ m.add(j.getName().replaceAll("\\Q.png\\E", ""));
+ } else if (j.isDirectory()) {
+ for (File k : j.listFiles()) {
+ if (k.isFile() && k.getName().endsWith(".png")) {
+ m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.png\\E", ""));
+ } else if (k.isDirectory()) {
+ for (File l : k.listFiles()) {
+ if (l.isFile() && l.getName().endsWith(".png")) {
+ m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.png\\E", ""));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ KList v = new KList<>(m);
+ possibleKeys = v.toArray(new String[0]);
+ return possibleKeys;
+ }
+
+ public File findFile(String name) {
+ for (File i : getFolders(name)) {
+ for (File j : i.listFiles()) {
+ if (j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
+ return j;
+ }
+ }
+
+ File file = new File(i, name + ".png");
+
+ if (file.exists()) {
+ return file;
+ }
+ }
+
+ Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
+
+ return null;
+ }
+
+ public IrisImage load(String name) {
+ return load(name, true);
+ }
+
+ private IrisImage loadRaw(String name) {
+ for (File i : getFolders(name)) {
+ for (File j : i.listFiles()) {
+ if (j.isFile() && j.getName().endsWith(".png") && j.getName().split("\\Q.\\E")[0].equals(name)) {
+ return loadFile(j, name);
+ }
+ }
+
+ File file = new File(i, name + ".png");
+
+ if (file.exists()) {
+ return loadFile(file, name);
+ }
+ }
+
+ Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
+
+ return null;
+ }
+
+ public IrisImage load(String name, boolean warn) {
+ return loadCache.get(name);
+ }
+}
diff --git a/src/main/java/com/volmit/iris/core/loader/IrisData.java b/src/main/java/com/volmit/iris/core/loader/IrisData.java
index 79ff87dae..c29196199 100644
--- a/src/main/java/com/volmit/iris/core/loader/IrisData.java
+++ b/src/main/java/com/volmit/iris/core/loader/IrisData.java
@@ -38,6 +38,7 @@ import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.engine.object.IrisEntity;
import com.volmit.iris.engine.object.IrisExpression;
import com.volmit.iris.engine.object.IrisGenerator;
+import com.volmit.iris.engine.object.IrisImage;
import com.volmit.iris.engine.object.IrisJigsawPiece;
import com.volmit.iris.engine.object.IrisJigsawPool;
import com.volmit.iris.engine.object.IrisJigsawStructure;
@@ -86,6 +87,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
private ResourceLoader blockLoader;
private ResourceLoader expressionLoader;
private ResourceLoader objectLoader;
+ private ResourceLoader imageLoader;
private ResourceLoader scriptLoader;
private ResourceLoader caveLoader;
private ResourceLoader ravineLoader;
@@ -186,6 +188,10 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
return loadAny(key, (dm) -> dm.getCaveLoader().load(key, false));
}
+ public static IrisImage loadAnyImage(String key) {
+ return loadAny(key, (dm) -> dm.getImageLoader().load(key, false));
+ }
+
public static IrisDimension loadAnyDimension(String key) {
return loadAny(key, (dm) -> dm.getDimensionLoader().load(key, false));
}
@@ -336,6 +342,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
this.blockLoader = registerLoader(IrisBlockData.class);
this.expressionLoader = registerLoader(IrisExpression.class);
this.objectLoader = registerLoader(IrisObject.class);
+ this.imageLoader = registerLoader(IrisImage.class);
this.scriptLoader = registerLoader(IrisScript.class);
gson = builder.create();
}
diff --git a/src/main/java/com/volmit/iris/engine/object/IrisImage.java b/src/main/java/com/volmit/iris/engine/object/IrisImage.java
new file mode 100644
index 000000000..f09d1488a
--- /dev/null
+++ b/src/main/java/com/volmit/iris/engine/object/IrisImage.java
@@ -0,0 +1,116 @@
+/*
+ * Iris is a World Generator for Minecraft Bukkit Servers
+ * Copyright (c) 2021 Arcane Arts (Volmit Software)
+ *
+ * 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
+ * (at your option) 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 .
+ */
+
+package com.volmit.iris.engine.object;
+
+import com.volmit.iris.core.loader.IrisRegistrant;
+import com.volmit.iris.util.json.JSONObject;
+import com.volmit.iris.util.plugin.VolmitSender;
+
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+
+public class IrisImage extends IrisRegistrant {
+ private BufferedImage image;
+
+ public int getRawValue(int x, int z)
+ {
+ if(x >= w || z >= h || x < 0 || z < 0)
+ {
+ return 0;
+ }
+
+ return image.getRGB(x, z);
+ }
+
+ public double getValue(IrisImageChannel channel, int x, int z)
+ {
+ int color = getRawValue(x + (image.getWidth()/2), z + (image.getHeight()/2));
+
+ switch(channel)
+ {
+ case RED -> {
+ return ((color >> 16) & 0xFF) / 255D;
+ }
+ case GREEN -> {
+ return ((color >> 8) & 0xFF) / 255D;
+ }
+ case BLUE -> {
+ return ((color >> 0) & 0xFF) / 255D;
+ }
+ case SATURATION -> {
+ return Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, null)[1];
+ }
+ case HUE -> {
+ return Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, null)[0];
+ }
+ case BRIGHTNESS -> {
+ return Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, null)[2];
+ }
+ case COMPOSITE_ADD_RGB -> {
+ return ((((color >> 16) & 0xFF) / 255D) + (((color >> 8) & 0xFF) / 255D) + (((color >> 0) & 0xFF) / 255D)) / 3D;
+ }
+ case COMPOSITE_MUL_RGB -> {
+ return (((color >> 16) & 0xFF) / 255D) * (((color >> 8) & 0xFF) / 255D) * (((color >> 0) & 0xFF) / 255D);
+ }
+ case COMPOSITE_MAX_RGB -> {
+ return Math.max(Math.max((((color >> 16) & 0xFF) / 255D), (((color >> 8) & 0xFF) / 255D)), (((color >> 0) & 0xFF) / 255D));
+ }
+ case COMPOSITE_ADD_HSB -> {
+ float[] hsb = Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, null);
+ return (hsb[0] + hsb[1] + hsb[2]) / 3D;
+ }
+ case COMPOSITE_MUL_HSB -> {
+ float[] hsb = Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, null);
+ return hsb[0] * hsb[1] * hsb[2];
+ }
+ case COMPOSITE_MAX_HSB -> {
+ float[] hsb = Color.RGBtoHSB((color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, null);
+ return Math.max(hsb[0], Math.max(hsb[1], hsb[2]));
+ }
+ case RAW -> {
+ return color;
+ }
+ }
+ }
+
+ public IrisImage()
+ {
+ this(new BufferedImage(4, 4, BufferedImage.TYPE_INT_RGB));
+ }
+
+ public IrisImage(BufferedImage image)
+ {
+ this.image = image;
+ }
+
+ @Override
+ public String getFolderName() {
+ return "images";
+ }
+
+ @Override
+ public String getTypeName() {
+ return "Image";
+ }
+
+ @Override
+ public void scanForErrors(JSONObject p, VolmitSender sender) {
+
+ }
+}