Use config type based image loading

Rename `path` key to `image`
This commit is contained in:
Astrash
2023-03-01 13:25:20 +11:00
parent 345012810a
commit d3e0831d9e
5 changed files with 88 additions and 60 deletions

View File

@@ -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<Supplier<ObjectTemplate<Image>>> IMAGE_REGISTRY_KEY = new TypeKey<>() {
};
public static final TypeKey<Supplier<ObjectTemplate<ColorSampler>>> 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<Supplier<ObjectTemplate<Image>>> imageRegistry = pack.getOrCreateRegistry(IMAGE_REGISTRY_KEY);
imageRegistry.register(addon.key("BITMAP"), () -> new ImageTemplate(pack.getLoader(), pack));
})
.then(event -> {
CheckedRegistry<Supplier<ObjectTemplate<ColorSampler>>> colorSamplerRegistry = event.getPack().getOrCreateRegistry(

View File

@@ -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<Image> {
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<String, Image> map) implements Properties {
}
}

View File

@@ -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<String, Image> 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);
}
}
}
}

View File

@@ -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<Image> {
@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);
}
}
}

View File

@@ -11,7 +11,7 @@ import com.dfsek.terra.addons.image.sampler.image.transform.Alignment;
public abstract class ImageColorSamplerTemplate implements ObjectTemplate<ColorSampler> {
@Value("path")
@Value("image")
protected Image image;
@Value("align")