Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ public static class Items {
() -> new FilmRollItem(FilmType.COLOR, Mth.color(0.4F, 0.4F, 1.0F), new Item.Properties()
.stacksTo(16)));

public static final Supplier<FilmRollItem> COLOR_POSITIVE_FILM = Register.item("color_positive_film",
() -> new FilmRollItem(FilmType.COLOR_POSITIVE, Mth.color(0.8F, 0.4F, 1.0F), new Item.Properties()
.stacksTo(16)));

public static final Supplier<DevelopedFilmItem> DEVELOPED_BLACK_AND_WHITE_FILM = Register.item("developed_black_and_white_film",
() -> new DevelopedFilmItem(FilmType.BLACK_AND_WHITE, new Item.Properties()
.stacksTo(1)));
Expand All @@ -140,6 +144,10 @@ public static class Items {
() -> new DevelopedFilmItem(FilmType.COLOR, new Item.Properties()
.stacksTo(1)));

public static final Supplier<DevelopedFilmItem> DEVELOPED_COLOR_POSITIVE_FILM = Register.item("developed_color_positive_film",
() -> new DevelopedFilmItem(FilmType.COLOR_POSITIVE, new Item.Properties()
.stacksTo(1)));

public static final Supplier<PhotographItem> PHOTOGRAPH = Register.item("photograph",
() -> new PhotographItem(new Item.Properties()
.stacksTo(1)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,12 @@ public void startPrintingProcess(boolean advanceFrameOnFinish) {

if (getActualProcess(filmStack) == Lightroom.Process.CHROMATIC)
printTime = Config.Common.LIGHTROOM_CHROMATIC_PRINT_TIME.get();
else if (film.getType() == FilmType.BLACK_AND_WHITE)
printTime = Config.Common.LIGHTROOM_BW_PRINT_TIME.get();
else
printTime = Config.Common.LIGHTROOM_COLOR_PRINT_TIME.get();
else {
printTime = switch (film.getType()) {
case BLACK_AND_WHITE,COLOR_POSITIVE -> Config.Common.LIGHTROOM_BW_PRINT_TIME.get();
case COLOR -> Config.Common.LIGHTROOM_COLOR_PRINT_TIME.get();
};
}

advanceFrame = advanceFrameOnFinish;

Expand Down Expand Up @@ -353,7 +355,10 @@ protected int[] getRequiredDyeSlotsForPrint(ItemStack film, ItemStack paper, Lig
return ArrayUtils.EMPTY_INT_ARRAY;

if (process == Lightroom.Process.REGULAR) {
return filmItem.getType() == FilmType.COLOR ? Lightroom.DYES_FOR_COLOR : Lightroom.DYES_FOR_BW;
return switch (filmItem.getType()) {
case BLACK_AND_WHITE -> Lightroom.DYES_FOR_BW;
case COLOR, COLOR_POSITIVE -> Lightroom.DYES_FOR_COLOR;
};
}

if (process == Lightroom.Process.CHROMATIC) {
Expand Down Expand Up @@ -433,9 +438,10 @@ protected void storeExperienceForPrint(ItemStack film, CompoundTag frame, Lightr
xp = result.getItem() instanceof ChromaticSheetItem ? 0 : Config.Common.LIGHTROOM_EXPERIENCE_PER_PRINT_CHROMATIC.get();
}
else if (film.getItem() instanceof IFilmItem filmItem)
xp = filmItem.getType() == FilmType.COLOR
? Config.Common.LIGHTROOM_EXPERIENCE_PER_PRINT_COLOR.get()
: Config.Common.LIGHTROOM_EXPERIENCE_PER_PRINT_BW.get();
xp = switch (filmItem.getType()) {
case BLACK_AND_WHITE -> Config.Common.LIGHTROOM_EXPERIENCE_PER_PRINT_BW.get();
case COLOR, COLOR_POSITIVE -> Config.Common.LIGHTROOM_EXPERIENCE_PER_PRINT_COLOR.get();
};

if (xp > 0) {
float variability = level.getRandom().nextFloat() * 0.3f + 1f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.mojang.blaze3d.platform.NativeImage;
import io.github.mortuusars.exposure.camera.capture.Capture;
import io.github.mortuusars.exposure.camera.infrastructure.FilmType;
import io.github.mortuusars.exposure.util.Color;
import net.minecraft.util.FastColor;
import net.minecraft.util.Mth;
import net.minecraft.world.level.material.MapColor;

Expand All @@ -12,6 +14,13 @@
public class DitheringColorConverter implements IImageToMapColorsConverter {
private record NegatableColor(int r, int g, int b) {}

protected FilmType filmType;

public DitheringColorConverter setFilmType(FilmType type) {
this.filmType = type;
return this;
}

public static MapColor[] getMapColors() {
MapColor[] colors = new MapColor[64];
for (int i = 0; i <= 63; i++){
Expand All @@ -22,37 +31,105 @@ public static MapColor[] getMapColors() {

@Override
public byte[] convert(Capture capture, NativeImage image) {

if (capture.getFilmType() == FilmType.COLOR_POSITIVE || filmType == FilmType.COLOR_POSITIVE) {
applySaturation(image, 2.0f);
}

return convert(image);
}

//AI slop for increasing saturation
private void applySaturation(NativeImage image, float saturationMultiplier) {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
int abgr = image.getPixelRGBA(x, y);

int alpha = FastColor.ABGR32.alpha(abgr);
if (alpha == 0) continue;

int blue = FastColor.ABGR32.blue(abgr);
int green = FastColor.ABGR32.green(abgr);
int red = FastColor.ABGR32.red(abgr);

float[] hsb = rgbToHsb(red, green, blue);

hsb[1] *= saturationMultiplier;
hsb[1] = Mth.clamp(hsb[1], 0.0f, 1.0f);

int newAbgr = hsbToAbgr(hsb[0], hsb[1], hsb[2], alpha);
image.setPixelRGBA(x, y, newAbgr);
}
}
}

// --- Lightweight, AWT-Free HSB/RGB Conversion Methods ---

private static float[] rgbToHsb(int r, int g, int b) {
float hue, saturation, brightness;
int cmax = Math.max(r, g);
if (b > cmax) cmax = b;
int cmin = Math.min(r, g);
if (b < cmin) cmin = b;

brightness = ((float) cmax) / 255.0f;
if (cmax != 0)
saturation = ((float) (cmax - cmin)) / ((float) cmax);
else
saturation = 0;

if (saturation == 0) {
hue = 0;
} else {
float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
if (r == cmax)
hue = bluec - greenc;
else if (g == cmax)
hue = 2.0f + redc - bluec;
else
hue = 4.0f + greenc - redc;
hue = hue / 6.0f;
if (hue < 0)
hue = hue + 1.0f;
}
return new float[]{hue, saturation, brightness};
}

private static int hsbToAbgr(float hue, float saturation, float brightness, int alpha) {
int r = 0, g = 0, b = 0;
if (saturation == 0) {
r = g = b = (int) (brightness * 255.0f + 0.5f);
} else {
float h = (hue - (float)Math.floor(hue)) * 6.0f;
float f = h - (float)java.lang.Math.floor(h);
float p = brightness * (1.0f - saturation);
float q = brightness * (1.0f - saturation * f);
float t = brightness * (1.0f - (saturation * (1.0f - f)));
switch ((int) h) {
case 0 -> { r = (int) (brightness * 255.0f + 0.5f); g = (int) (t * 255.0f + 0.5f); b = (int) (p * 255.0f + 0.5f); }
case 1 -> { r = (int) (q * 255.0f + 0.5f); g = (int) (brightness * 255.0f + 0.5f); b = (int) (p * 255.0f + 0.5f); }
case 2 -> { r = (int) (p * 255.0f + 0.5f); g = (int) (brightness * 255.0f + 0.5f); b = (int) (t * 255.0f + 0.5f); }
case 3 -> { r = (int) (p * 255.0f + 0.5f); g = (int) (q * 255.0f + 0.5f); b = (int) (brightness * 255.0f + 0.5f); }
case 4 -> { r = (int) (t * 255.0f + 0.5f); g = (int) (p * 255.0f + 0.5f); b = (int) (brightness * 255.0f + 0.5f); }
case 5 -> { r = (int) (brightness * 255.0f + 0.5f); g = (int) (p * 255.0f + 0.5f); b = (int) (q * 255.0f + 0.5f); }
}
}
return FastColor.ABGR32.color(alpha, b, g, r);
}

@Override
public byte[] convert(NativeImage image) {
if (filmType == FilmType.COLOR_POSITIVE) {
applySaturation(image, 2.0f);
}
int[][] pixels = convertToPixelArray(image);
return convert(pixels);

// int width = image.getWidth();
// int height = image.getHeight();
// MapColor[] mapColors = Arrays.stream(getMapColors()).filter(Objects::nonNull).toArray(MapColor[]::new);
//
// byte[] bytes = new byte[width * height];
//
// for (int x = 0; x < width; x++) {
// for (int y = 0; y < height; y++) {
// Color imageColor = new Color(pixels[y][x], true);
//
// byte b = (byte) floydDither(mapColors, pixels, x, y, imageColor);
//
// if (imageColor.getAlpha() == 0)
// b = (byte)MapColor.NONE.id;
//
// bytes[x + y * width] = b;
// }
// }
//
// return bytes;
}

public byte[] convert(int[][] pixels) {

MapColor[] mapColors = Arrays.stream(getMapColors()).filter(Objects::nonNull).toArray(MapColor[]::new);

int width = pixels[0].length;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.mojang.blaze3d.platform.NativeImage;
import io.github.mortuusars.exposure.camera.capture.Capture;
import io.github.mortuusars.exposure.camera.infrastructure.FilmType;
import net.minecraft.util.FastColor;
import net.minecraft.util.Mth;
import net.minecraft.world.level.material.MapColor;

import java.util.Arrays;
Expand All @@ -20,6 +22,9 @@ public static MapColor[] getMapColors() {

@Override
public byte[] convert(Capture capture, NativeImage image) {
if (capture.getFilmType() == FilmType.COLOR_POSITIVE) {
applySaturation(image, 2.0f);
}
return convert(image);
}

Expand Down Expand Up @@ -54,6 +59,86 @@ public byte[] convert(NativeImage image) {

private final double[] shadeCoeffs = { 0.71, 0.86, 1.0, 0.53 };


//AI slop for saturating an image

private void applySaturation(NativeImage image, float saturationMultiplier) {
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
int abgr = image.getPixelRGBA(x, y);

int alpha = FastColor.ABGR32.alpha(abgr);
if (alpha == 0) continue;

int blue = FastColor.ABGR32.blue(abgr);
int green = FastColor.ABGR32.green(abgr);
int red = FastColor.ABGR32.red(abgr);

float[] hsb = rgbToHsb(red, green, blue);

hsb[1] *= saturationMultiplier;
hsb[1] = Mth.clamp(hsb[1], 0.0f, 1.0f);

int newAbgr = hsbToAbgr(hsb[0], hsb[1], hsb[2], alpha);
image.setPixelRGBA(x, y, newAbgr);
}
}
}

private static float[] rgbToHsb(int r, int g, int b) {
float hue, saturation, brightness;
int cmax = Math.max(r, g);
if (b > cmax) cmax = b;
int cmin = Math.min(r, g);
if (b < cmin) cmin = b;

brightness = ((float) cmax) / 255.0f;
if (cmax != 0)
saturation = ((float) (cmax - cmin)) / ((float) cmax);
else
saturation = 0;

if (saturation == 0) {
hue = 0;
} else {
float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
if (r == cmax)
hue = bluec - greenc;
else if (g == cmax)
hue = 2.0f + redc - bluec;
else
hue = 4.0f + greenc - redc;
hue = hue / 6.0f;
if (hue < 0)
hue = hue + 1.0f;
}
return new float[]{hue, saturation, brightness};
}

private static int hsbToAbgr(float hue, float saturation, float brightness, int alpha) {
int r = 0, g = 0, b = 0;
if (saturation == 0) {
r = g = b = (int) (brightness * 255.0f + 0.5f);
} else {
float h = (hue - (float)Math.floor(hue)) * 6.0f;
float f = h - (float)java.lang.Math.floor(h);
float p = brightness * (1.0f - saturation);
float q = brightness * (1.0f - saturation * f);
float t = brightness * (1.0f - (saturation * (1.0f - f)));
switch ((int) h) {
case 0 -> { r = (int) (brightness * 255.0f + 0.5f); g = (int) (t * 255.0f + 0.5f); b = (int) (p * 255.0f + 0.5f); }
case 1 -> { r = (int) (q * 255.0f + 0.5f); g = (int) (brightness * 255.0f + 0.5f); b = (int) (p * 255.0f + 0.5f); }
case 2 -> { r = (int) (p * 255.0f + 0.5f); g = (int) (brightness * 255.0f + 0.5f); b = (int) (t * 255.0f + 0.5f); }
case 3 -> { r = (int) (p * 255.0f + 0.5f); g = (int) (q * 255.0f + 0.5f); b = (int) (brightness * 255.0f + 0.5f); }
case 4 -> { r = (int) (t * 255.0f + 0.5f); g = (int) (p * 255.0f + 0.5f); b = (int) (brightness * 255.0f + 0.5f); }
case 5 -> { r = (int) (brightness * 255.0f + 0.5f); g = (int) (p * 255.0f + 0.5f); b = (int) (q * 255.0f + 0.5f); }
}
}
return FastColor.ABGR32.color(alpha, b, g, r);
}

private double[] applyShade(double[] color, int shadeIndex) {
double coeff = shadeCoeffs[shadeIndex];
return new double[] { color[0] * coeff, color[1] * coeff, color[2] * coeff };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

public enum FilmType implements StringRepresentable {
BLACK_AND_WHITE("black_and_white", 255, 255, 255, 1.0F, 1.0F, 1.0F, 1.0F),
COLOR("color", 180, 130, 110, 1.2F, 0.96F, 0.75F, 1.0F);
COLOR("color", 180, 130, 110, 1.2F, 0.96F, 0.75F, 1.0F),
COLOR_POSITIVE("color_positive", 255, 255, 255, 0.0F, 0.0F, 0.0F, 1.0F);

@SuppressWarnings("deprecation")
public static final StringRepresentable.EnumCodec<FilmType> CODEC = StringRepresentable.fromEnum(FilmType::values);
Expand Down Expand Up @@ -47,6 +48,11 @@ public ItemStack createItemStack() {
}

public ItemStack createDevelopedItemStack() {
return new ItemStack(this == COLOR ? Exposure.Items.DEVELOPED_COLOR_FILM.get() : Exposure.Items.DEVELOPED_BLACK_AND_WHITE_FILM.get());
// Updated to a switch statement to handle all types
return switch (this) {
case BLACK_AND_WHITE -> new ItemStack(Exposure.Items.DEVELOPED_BLACK_AND_WHITE_FILM.get());
case COLOR -> new ItemStack(Exposure.Items.DEVELOPED_COLOR_FILM.get());
case COLOR_POSITIVE -> new ItemStack(Exposure.Items.DEVELOPED_COLOR_POSITIVE_FILM.get());
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import io.github.mortuusars.exposure.menu.LightroomMenu;
import io.github.mortuusars.exposure.render.image.RenderedImageProvider;
import io.github.mortuusars.exposure.render.modifiers.ExposurePixelModifiers;
import io.github.mortuusars.exposure.render.modifiers.IPixelModifier;
import io.github.mortuusars.exposure.util.ColorChannel;
import io.github.mortuusars.exposure.util.PagingDirection;
import net.minecraft.ChatFormatting;
Expand Down Expand Up @@ -294,8 +295,15 @@ public void renderFrame(@Nullable CompoundTag frame, PoseStack poseStack, float
poseStack.translate(x, y, 0);

MultiBufferSource.BufferSource bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder());

IPixelModifier modifier = switch (negative) {
case COLOR_POSITIVE -> ExposurePixelModifiers.EMPTY; //literally does nothing lmao
default -> ExposurePixelModifiers.NEGATIVE_FILM;
};

ExposureClient.getExposureRenderer().render(RenderedImageProvider.fromFrame(frame),
ExposurePixelModifiers.NEGATIVE_FILM, poseStack, bufferSource, 0, 0, size, size, LightTexture.FULL_BRIGHT,
modifier,
poseStack, bufferSource, 0, 0, size, size, LightTexture.FULL_BRIGHT,
negative.frameR, negative.frameG, negative.frameB, Mth.clamp((int) Math.ceil(alpha * 255), 0, 255));
bufferSource.endBatch();

Expand Down
4 changes: 3 additions & 1 deletion common/src/main/resources/assets/exposure/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,10 @@
"item.exposure.chromatic_sheet.info": "Use as a paper to print remaining layers",
"item.exposure.chromatic_sheet.use_tooltip": "Use to combine three layers into a Photograph",
"item.exposure.color_film": "Color Film",
"item.exposure.color_positive_film": "Color Positive Film",
"item.exposure.developed_black_and_white_film": "Developed Black and White Film",
"item.exposure.developed_color_film": "Developed Color Film",
"item.exposure.developed_color_positive_film": "Developed Color Positive Film",
"item.exposure.developed_film.tooltip.frame_count": "Frames: %s",
"item.exposure.film_roll.tooltip.details.develop": "Developed by crafting with:",
"item.exposure.film_roll.tooltip.developing_step": "Developing: %s",
Expand Down Expand Up @@ -186,4 +188,4 @@
"subtitle.exposure.photograph_frame.remove_item": "Photograph Frame empties",
"subtitle.exposure.photograph_frame.rotate_item": "Photograph Frame clicks",
"tooltip.exposure.hold_for_details": "§8Hold [§7Shift§8] for Details"
}
}
Loading