Implement color parsing from strings

This commit is contained in:
Astrash
2023-05-02 12:52:13 +10:00
parent 39d21fbe08
commit 105be0c346
5 changed files with 111 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import java.util.Map;
import com.dfsek.terra.addons.image.config.ColorLoader.ColorString;
import com.dfsek.terra.addons.image.converter.mapping.ColorMapping;
import com.dfsek.terra.addons.image.util.MapUtil;
import com.dfsek.terra.api.world.biome.Biome;
@@ -13,11 +14,11 @@ import com.dfsek.terra.api.world.biome.Biome;
public class DefinedBiomeColorMappingTemplate implements ObjectTemplate<ColorMapping<Biome>> {
@Value("map")
Map<String, Biome> map;
Map<ColorString, Biome> map;
@Override
public ColorMapping<Biome> get() {
var map = MapUtil.mapKeys(this.map, Integer::decode);
var map = MapUtil.mapKeys(this.map, ColorString::getColor);
return () -> map;
}
}

View File

@@ -4,6 +4,8 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import java.util.function.Supplier;
import com.dfsek.terra.addons.image.config.ColorLoader;
import com.dfsek.terra.addons.image.config.ColorLoader.ColorString;
import com.dfsek.terra.addons.image.config.noisesampler.ChannelNoiseSamplerTemplate;
import com.dfsek.terra.addons.image.config.noisesampler.DistanceTransformNoiseSamplerTemplate;
import com.dfsek.terra.addons.image.config.image.ImageTemplate;
@@ -61,7 +63,8 @@ public class ImageLibraryAddon implements AddonInitializer {
.applyLoader(DistanceTransform.CostFunction.class,
(type, o, loader, depthTracker) -> DistanceTransform.CostFunction.valueOf((String) o))
.applyLoader(DistanceTransform.Normalization.class,
(type, o, loader, depthTracker) -> DistanceTransform.Normalization.valueOf((String) o));
(type, o, loader, depthTracker) -> DistanceTransform.Normalization.valueOf((String) o))
.applyLoader(ColorString.class, new ColorLoader());
CheckedRegistry<Supplier<ObjectTemplate<NoiseSampler>>> noiseRegistry = event.getPack().getOrCreateRegistry(
NOISE_SAMPLER_TOKEN);

View File

@@ -0,0 +1,92 @@
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 java.lang.reflect.AnnotatedType;
import com.dfsek.terra.addons.image.config.ColorLoader.ColorString;
import com.dfsek.terra.addons.image.util.ColorUtil;
public class ColorLoader implements TypeLoader<ColorString> {
@Override
public ColorString load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader,
DepthTracker depthTracker) throws LoadException {
return new ColorString((String) o);
}
public static class ColorString {
private final int argb;
public ColorString(String string) throws IllegalArgumentException {
this.argb = parse(string);
}
public int getColor() {
return argb;
}
private static int parse(String string) throws IllegalArgumentException {
if (string.length() == 0)
throw new IllegalArgumentException("Empty string cannot be parsed as a valid color");
String[] split = string.split(",");
if (split.length == 1)
return parseHex(string);
else if (split.length == 3)
return parseChannels("255", split[0], split[1], split[2]);
else if (split.length == 4)
return parseChannels(split[0], split[1], split[2], split[3]);
else
throw new IllegalArgumentException("Invalid channels provided, required format RED,GREEN,BLUE or ALPHA,RED,GREEN,BLUE");
}
private static int parseHex(String hex) throws IllegalArgumentException {
if (hex.startsWith("#"))
hex = hex.substring(1);
int alpha = 255;
int red = 0;
int green = 0;
int blue = 0;
try {
if(hex.length() == 8) {
alpha = Integer.parseInt(hex.substring(0, 2), 16);
hex = hex.substring(2);
}
if(hex.length() != 6)
throw new IllegalArgumentException("Invalid color channels, required format AARRGGBB or RRGGBB");
red = Integer.parseInt(hex.substring(0, 2), 16);
green = Integer.parseInt(hex.substring(2, 4), 16);
blue = Integer.parseInt(hex.substring(4, 6), 16);
return ColorUtil.rgbValidated(alpha, red, green, blue);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Failed to parse hex color", e);
}
}
private static int parseChannels(String alpha, String red, String green, String blue) throws IllegalArgumentException {
try {
int a = Integer.decode(alpha);
int r = Integer.decode(red);
int g = Integer.decode(green);
int b = Integer.decode(blue);
return ColorUtil.rgbValidated(a, r, g, b);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid channel value", e);
}
}
}
}

View File

@@ -4,15 +4,16 @@ import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
import com.dfsek.terra.addons.image.config.ColorLoader.ColorString;
public class ConstantColorSamplerTemplate implements ObjectTemplate<ColorSampler> {
@Value("color")
private int color;
private ColorString color;
@Override
public ColorSampler get() {
return ((x, z) -> color);
return ((x, z) -> color.argb());
}
}

View File

@@ -76,6 +76,15 @@ public class ColorUtil {
return rgbAlpha(alpha) | rgbRed(red) | rgbGreen(green) | rgbBlue(blue);
}
public static int rgbValidated(int alpha, int red, int green, int blue) throws IllegalArgumentException {
if (alpha < 0 || alpha > 255 ||
red < 0 || red > 255 ||
green < 0 || green > 255 ||
blue < 0 || blue > 255
) throw new IllegalArgumentException("Channel values must be in range 0-255");
return rgb(alpha, red, green, blue);
}
public static int rgbAlpha(int alpha) { return alpha << 24; }
public static int rgbRed(int red) { return red << 16; }