Originally Posted by
mige5
Does that also work for pictures like this:
I dont always have fading on them, so will it also work on these:
Do you just want this to replace black with X color and white with Y color? That's a bit different, I can write something up for you in a bit though.
Edit:
Code:
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.IOException;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public final class BlendTest {
@Test
public void benchmark() {
final int iterations = 1;
List<Blend> blendList = new ArrayList<>(iterations);
for (int i = 0; i != iterations; ++i) {
blendList.add(new Blend(320, 280, 0.2f));
}
long start = System.currentTimeMillis();
while (!blendList.isEmpty()) {
blendList.removeIf(Blend::blend);
}
System.out.printf("Iteration of %s blends took %d ms.\n", new DecimalFormat().format(iterations), (System.currentTimeMillis() - start));
}
@Test
public void visualization() throws IOException {
Blend blend = new Blend(ImageIO.read(Paths.get(System.getProperty("user.home"), "Downloads", "two.png").toFile().toURI().toURL()), 0.1f);
int stage = 0;
while (true) {
BufferedImage image = new BufferedImage(blend.width, blend.height, BufferedImage.TYPE_INT_RGB);
int[] data = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
System.arraycopy(blend.src, 0, data, 0, data.length);
ImageIO.write(image, "png", Paths.get("../", "dev", "blend").resolve("blend#" + (stage++) + ".png").toFile());
if (blend.blend()) {
break;
}
}
}
public static final class Blend {
private final int width;
private final int height;
private final int[] src;
private final int[] dst;
private final float t;
Blend(int width, int height, float t) {
this.width = width;
this.height = height;
this.src = new int[width * height];
this.dst = new int[width * height];
this.t = t;
fillDummyData();
}
Blend(BufferedImage image, float t) {
this.width = image.getWidth();
this.height = image.getHeight();
this.src = new int[width * height];
this.dst = new int[width * height];
this.t = t;
fillData(image);
}
void fillData(BufferedImage image) {
for (int y = 0; y != height; ++y) {
for (int x = 0; x != width; ++x) {
int color = image.getRGB(x, y);
src[y * width + x] = color;
// We have to calculate the luminance to see if the pixel RGB is closer to white or black.
int luminance = (int) ((((color >> 16) & 0xFF) * 0.2126) + (((color >> 8) & 0xFF) * 0.7152) + ((color & 0xFF) * 0.0722));
color = luminance < 128 ? 0x000000 : 0xFFFFFF;
if (color == 0x000000) {
// We are setting the primary filter color replacement to yellow.
// We can add a parameter for this.
dst[y * width + x] = 0xFFFF00;
} else {
// We are setting the secondary filter color replacement to red.
// We can add a parameter for this.
dst[y * width + x] = 0xFF0000;
}
}
}
}
void fillDummyData() {
for (int i = 0; i != (width * height); ++i) {
if (i < ((width * height + width * 2) / 3)) {
src[i] = 0x000000;
dst[i] = 0xFFFF00;
} else {
src[i] = 0xFFFFFF;
dst[i] = 0xFF0000;
}
}
}
boolean blend() {
for (int y = 0; y != height; ++y) {
for (int x = 0; x != width; ++x) {
int srcColor = src[y * width + x];
int dstColor = dst[y * width + x];
int r = (int) (QuickMaffs.lerp(((float)((srcColor >> 16) & 0xFF) / 255.0f), ((float) ((dstColor >> 16) & 0xFF) / 255.0f), t) * 255);
int g = (int) (QuickMaffs.lerp(((float)((srcColor >> 8) & 0xFF) / 255.0f), ((float) ((dstColor >> 8) & 0xFF) / 255.0f), t) * 255);
int b = (int) (QuickMaffs.lerp(((float)(srcColor & 0xFF) / 255.0f), ((float) (dstColor & 0xFF) / 255.0f), t) * 255);
int newColor = (r << 16) | (g << 8) | b;
if (newColor == srcColor) {
newColor = dstColor;
}
src[y * width + x] = newColor;
}
}
return src[width * height - width] == dst[width * height - width];
}
}
private static final class QuickMaffs {
static float lerp(float src, float dst, float t) {
return (1 - t) * src + t * dst;
}
}
}
Results: https://imgur.com/a/svSXZ