Last active
June 4, 2020 20:00
-
-
Save naikrovek/e44f0309012fda3fe8c1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Graphics; | |
import java.awt.GridLayout; | |
import java.awt.image.BufferedImage; | |
import java.io.IOException; | |
import java.net.URL; | |
import javax.imageio.ImageIO; | |
import javax.swing.JComponent; | |
import javax.swing.JFrame; | |
/* | |
* from http://stackoverflow.com/questions/5940188/how-to-convert-a-24-bit-png-to-3-bit-png-using-floyd-steinberg-dithering | |
*/ | |
class Dither { | |
static class C3 { | |
int r, g, b; | |
public C3(int c) { | |
Color color = new Color(c); | |
r = color.getRed(); | |
g = color.getGreen(); | |
b = color.getBlue(); | |
} | |
public C3(int r, int g, int b) { | |
this.r = r; | |
this.g = g; | |
this.b = b; | |
} | |
public C3 add(C3 o) { | |
return new C3(r + o.r, g + o.g, b + o.b); | |
} | |
public int clamp(int c) { | |
return Math.max(0, Math.min(255, c)); | |
} | |
public int diff(C3 o) { | |
int Rdiff = o.r - r; | |
int Gdiff = o.g - g; | |
int Bdiff = o.b - b; | |
int distanceSquared = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; | |
return distanceSquared; | |
} | |
public C3 mul(double d) { | |
return new C3((int) (d * r), (int) (d * g), (int) (d * b)); | |
} | |
public C3 sub(C3 o) { | |
return new C3(r - o.r, g - o.g, b - o.b); | |
} | |
public Color toColor() { | |
return new Color(clamp(r), clamp(g), clamp(b)); | |
} | |
public int toRGB() { | |
return toColor().getRGB(); | |
} | |
} | |
private static C3 findClosestPaletteColor(C3 c, C3[] palette) { | |
C3 closest = palette[0]; | |
for (C3 n : palette) { | |
if (n.diff(c) < closest.diff(c)) { | |
closest = n; | |
} | |
} | |
return closest; | |
} | |
private static BufferedImage floydSteinbergDithering(BufferedImage img) { | |
C3[] palette = new C3[] { | |
new C3( 0, 0, 0), // black | |
new C3( 0, 0, 255), // green | |
new C3( 0, 255, 0), // blue | |
new C3( 0, 255, 255), // cyan | |
new C3(255, 0, 0), // red | |
new C3(255, 0, 255), // purple | |
new C3(255, 255, 0), // yellow | |
new C3(255, 255, 255) // white | |
}; | |
int w = img.getWidth(); | |
int h = img.getHeight(); | |
C3[][] d = new C3[h][w]; | |
for (int y = 0; y < h; y++) { | |
for (int x = 0; x < w; x++) { | |
d[y][x] = new C3(img.getRGB(x, y)); | |
} | |
} | |
for (int y = 0; y < img.getHeight(); y++) { | |
for (int x = 0; x < img.getWidth(); x++) { | |
C3 oldColor = d[y][x]; | |
C3 newColor = findClosestPaletteColor(oldColor, palette); | |
img.setRGB(x, y, newColor.toColor().getRGB()); | |
C3 err = oldColor.sub(newColor); | |
if (x + 1 < w) { | |
d[y][x + 1] = d[y][x + 1].add(err.mul(7. / 16)); | |
} | |
if (x - 1 >= 0 && y + 1 < h) { | |
d[y + 1][x - 1] = d[y + 1][x - 1].add(err.mul(3. / 16)); | |
} | |
if (y + 1 < h) { | |
d[y + 1][x] = d[y + 1][x].add(err.mul(5. / 16)); | |
} | |
if (x + 1 < w && y + 1 < h) { | |
d[y + 1][x + 1] = d[y + 1][x + 1].add(err.mul(1. / 16)); | |
} | |
} | |
} | |
return img; | |
} | |
public static void main(String[] args) throws IOException { | |
GammaCorrection gamma = new GammaCorrection(); | |
final BufferedImage original = ImageIO.read(new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png")).getSubimage(100, 100, 300, 300); | |
final BufferedImage gcorrect = gamma.gammaCorrection(original.getSubimage(0, 0, original.getWidth(), original.getHeight()), 1 / 1.8); | |
final BufferedImage dithered = floydSteinbergDithering(gcorrect.getSubimage(0, 0, gcorrect.getWidth(), gcorrect.getHeight())); | |
JFrame frame = new JFrame("Dither Test"); | |
frame.setLayout(new GridLayout(1, 2)); | |
frame.add(new JComponent() { | |
private static final long serialVersionUID = 2963702769416707676L; | |
@Override | |
protected void paintComponent(Graphics g) { | |
super.paintComponent(g); | |
g.drawImage(original, 0, 0, this); | |
} | |
}); | |
frame.add(new JComponent() { | |
private static final long serialVersionUID = -6919658458441878769L; | |
@Override | |
protected void paintComponent(Graphics g) { | |
super.paintComponent(g); | |
g.drawImage(dithered, 0, 0, this); | |
} | |
}); | |
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | |
frame.setSize(616, 338); | |
frame.setVisible(true); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.image.BufferedImage; | |
/** | |
* Gamma correction algorithm | |
* | |
* Author: Bostjan Cigan (http://zerocool.is-a-geek.net) | |
* | |
* Modified for use as an instance. | |
*/ | |
public class GammaCorrection { | |
// Convert R, G, B, Alpha to standard 8 bit | |
private static int colorToRGB(int alpha, int red, int green, int blue) { | |
int newPixel = 0; | |
newPixel += alpha; | |
newPixel = newPixel << 8; | |
newPixel += red; | |
newPixel = newPixel << 8; | |
newPixel += green; | |
newPixel = newPixel << 8; | |
newPixel += blue; | |
return newPixel; | |
} | |
// Create the gamma correction lookup table | |
private static int[] gamma_LUT(double gamma_new) { | |
int[] gamma_LUT = new int[256]; | |
for (int i = 0; i < gamma_LUT.length; i++) { | |
gamma_LUT[i] = (int) (255 * Math.pow((double) i / (double) 255, gamma_new)); | |
} | |
return gamma_LUT; | |
} | |
public BufferedImage gammaCorrection(BufferedImage original, double gamma) { | |
int alpha, red, green, blue; | |
int newPixel; | |
double gamma_new = 1 / gamma; | |
int[] gamma_LUT = gamma_LUT(gamma_new); | |
BufferedImage gamma_cor = new BufferedImage(original.getWidth(), original.getHeight(), original.getType()); | |
for (int i = 0; i < original.getWidth(); i++) { | |
for (int j = 0; j < original.getHeight(); j++) { | |
// Get pixels by R, G, B | |
alpha = new Color(original.getRGB(i, j)).getAlpha(); | |
red = new Color(original.getRGB(i, j)).getRed(); | |
green = new Color(original.getRGB(i, j)).getGreen(); | |
blue = new Color(original.getRGB(i, j)).getBlue(); | |
red = gamma_LUT[red]; | |
green = gamma_LUT[green]; | |
blue = gamma_LUT[blue]; | |
// Return back to original format | |
newPixel = colorToRGB(alpha, red, green, blue); | |
// Write pixels into image | |
gamma_cor.setRGB(i, j, newPixel); | |
} | |
} | |
return gamma_cor; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment