diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java index cb556b563..831e4828a 100644 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/ImageLibraryAddon.java @@ -4,7 +4,7 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import java.util.function.Supplier; -import com.dfsek.terra.addons.image.config.ImageLoader; +import com.dfsek.terra.addons.image.config.image.ImageTemplate; import com.dfsek.terra.addons.image.config.sampler.ConstantColorSamplerTemplate; import com.dfsek.terra.addons.image.config.sampler.image.SingleImageColorSamplerTemplate; import com.dfsek.terra.addons.image.config.sampler.image.TileImageColorSamplerTemplate; @@ -25,6 +25,9 @@ import com.dfsek.terra.api.util.reflection.TypeKey; public class ImageLibraryAddon implements AddonInitializer { + public static final TypeKey>> IMAGE_REGISTRY_KEY = new TypeKey<>() { + }; + public static final TypeKey>> COLOR_PICKER_REGISTRY_KEY = new TypeKey<>() { }; @@ -42,7 +45,8 @@ public class ImageLibraryAddon implements AddonInitializer { .priority(10) .then(event -> { ConfigPack pack = event.getPack(); - pack.applyLoader(Image.class, new ImageLoader(pack.getLoader(), pack)); + CheckedRegistry>> imageRegistry = pack.getOrCreateRegistry(IMAGE_REGISTRY_KEY); + imageRegistry.register(addon.key("BITMAP"), () -> new ImageTemplate(pack.getLoader(), pack)); }) .then(event -> { CheckedRegistry>> colorSamplerRegistry = event.getPack().getOrCreateRegistry( diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/ImageLoader.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/ImageLoader.java deleted file mode 100644 index cedfbb3bb..000000000 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/ImageLoader.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.dfsek.terra.addons.image.config; - -import com.dfsek.tectonic.api.depth.DepthTracker; -import com.dfsek.tectonic.api.exception.LoadException; -import com.dfsek.tectonic.api.loader.ConfigLoader; -import com.dfsek.tectonic.api.loader.type.TypeLoader; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.imageio.ImageIO; -import java.io.IOException; -import java.lang.reflect.AnnotatedType; -import java.util.concurrent.ConcurrentHashMap; - -import com.dfsek.terra.addons.image.image.BufferedImageWrapper; -import com.dfsek.terra.addons.image.image.Image; -import com.dfsek.terra.api.config.ConfigPack; -import com.dfsek.terra.api.config.Loader; -import com.dfsek.terra.api.properties.Properties; - - -public class ImageLoader implements TypeLoader { - - private static final Logger logger = LoggerFactory.getLogger(ImageLoader.class); - - private final Loader files; - - private final ConfigPack pack; - - public ImageLoader(Loader files, ConfigPack pack) { - this.files = files; - this.pack = pack; - if(!pack.getContext().has(ImageCache.class)) - pack.getContext().put(new ImageCache(new ConcurrentHashMap<>())); - } - - @Override - public Image load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker) - throws LoadException { - return pack.getContext().get(ImageCache.class).map.computeIfAbsent((String) c, imagePath -> { - try { - return new BufferedImageWrapper(ImageIO.read(files.get(imagePath))); - } catch(IllegalArgumentException e) { - throw new LoadException("Unable to load image (image might be too large?)", e, depthTracker); - } catch(IOException e) { - throw new LoadException("Unable to load image", e, depthTracker); - } - }); - } - - /* - * Cache prevents configs from loading the same image multiple times into memory - */ - private record ImageCache(ConcurrentHashMap map) implements Properties { - } -} diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java new file mode 100644 index 000000000..5f96ea390 --- /dev/null +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageCache.java @@ -0,0 +1,46 @@ +package com.dfsek.terra.addons.image.config.image; + +import javax.imageio.ImageIO; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; + +import com.dfsek.terra.addons.image.image.BufferedImageWrapper; +import com.dfsek.terra.addons.image.image.Image; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.Loader; +import com.dfsek.terra.api.properties.Properties; + + +/* + * Cache prevents configs from loading the same image multiple times into memory + */ +record ImageCache(ConcurrentHashMap map) implements Properties { + public static Image load(String path, ConfigPack pack, Loader files) throws IOException { + ImageCache cache; + if(!pack.getContext().has(ImageCache.class)) { + cache = new ImageCache(new ConcurrentHashMap<>()); + pack.getContext().put(cache); + } else { + cache = pack.getContext().get(ImageCache.class); + } + + if(cache.map.containsKey(path)) { + return cache.map.get(path); + } else { + try { + BufferedImageWrapper image = new BufferedImageWrapper(ImageIO.read(files.get(path))); + cache.map.put(path, image); + return image; + } catch(IllegalArgumentException e) { + throw new IllegalArgumentException("Unable to load image (image might be too large?)", e); + } catch(IOException e) { + if(e instanceof FileNotFoundException) { + // Rethrow using nicer message + throw new IOException("Unable to load image: No such file or directory: " + path, e); + } + throw new IOException("Unable to load image", e); + } + } + } +} diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java new file mode 100644 index 000000000..7590ca1b4 --- /dev/null +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/image/ImageTemplate.java @@ -0,0 +1,35 @@ +package com.dfsek.terra.addons.image.config.image; + +import com.dfsek.tectonic.api.config.template.annotations.Value; +import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; + +import java.io.IOException; + +import com.dfsek.terra.addons.image.image.Image; +import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.config.Loader; + + +public class ImageTemplate implements ObjectTemplate { + + @Value("path") + private String path; + + private final Loader files; + + private final ConfigPack pack; + + public ImageTemplate(Loader files, ConfigPack pack) { + this.files = files; + this.pack = pack; + } + + @Override + public Image get() { + try { + return ImageCache.load(path, pack, files); + } catch(IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/sampler/image/ImageColorSamplerTemplate.java b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/sampler/image/ImageColorSamplerTemplate.java index 98e61baa8..3e129ba6e 100644 --- a/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/sampler/image/ImageColorSamplerTemplate.java +++ b/common/addons/library-image/src/main/java/com/dfsek/terra/addons/image/config/sampler/image/ImageColorSamplerTemplate.java @@ -11,7 +11,7 @@ import com.dfsek.terra.addons.image.sampler.image.transform.Alignment; public abstract class ImageColorSamplerTemplate implements ObjectTemplate { - @Value("path") + @Value("image") protected Image image; @Value("align")