Skip to content

Instantly share code, notes, and snippets.

@bholzer
Created February 25, 2017 06:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bholzer/efbf8bb9d8584da5c4f0856ee7285275 to your computer and use it in GitHub Desktop.
Save bholzer/efbf8bb9d8584da5c4f0856ee7285275 to your computer and use it in GitHub Desktop.
import java.awt.Color;
import java.util.*;
public class ColorListSorter {
public static void quickSort(List<Color> list, int pivot, int end) {
if (pivot < end) {
int q = partition(list, pivot, end);
quickSort(list, pivot, q);
quickSort(list, q+1, end);
}
}
public static int partition(List<Color> list, int pivot, int r) {
Color color = list.get(pivot);
int i = pivot-1;
int j = r+1;
while (true) {
i++;
while (i < r && (list.get(i).getBlue() < color.getBlue() || list.get(i).getRed() < color.getRed())) {
i++;
}
j--;
while (j > pivot && (list.get(j).getBlue() > color.getBlue() || list.get(i).getRed() < color.getRed())) {
j--;
}
if (i < j) {
Collections.swap(list, i, j);
} else {
return j;
}
}
}
}
import java.awt.Color;
import java.util.*;
public class ColorUtilities {
public static Color getClosestColorFrom(List<Color> colorList, Color closestTo) {
double shortestDistance = Double.MAX_VALUE;
Color closestColor = closestTo;
for (Color color : colorList) {
if (!color.equals(closestTo)) {
double distance = (closestTo.getRed()-color.getRed())*(closestTo.getRed()-color.getRed())+
(closestTo.getGreen()-color.getGreen())*(closestTo.getGreen()-color.getGreen())+
(closestTo.getBlue()-color.getBlue())*(closestTo.getBlue()-color.getBlue());
if (distance < shortestDistance) {
shortestDistance = distance;
closestColor = color;
}
}
}
return closestColor;
}
}
import java.awt.Color;
public class GridBlock {
public int x;
public int y;
public Color color;
public boolean filled;
public boolean active;
public GridBlock(int x, int y) {
this.x = x;
this.y = y;
this.active = false;
}
public String toString() {
return "("+this.x+","+this.y+") - "+this.color;
}
}
import java.awt.image.BufferedImage;
import java.awt.Color;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import java.util.*;
public class RgbGenerator {
public static int neighborhoodSize(int radius) {
if (radius == 1) return 8;
return neighborhoodSize(radius-1)+(radius*8);
}
public static void main(String[] args) {
long startTime = new Date().getTime();
int height = 512;
int width = 512;
int colorPerChannel = 64; //5 bits per channel, 15 bit color-depth
int startX = 256;
int startY = 256;
Random random = new Random();
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// Create evenly distributed Color list
List<Color> colors = new ArrayList<Color>();
for (int r = 0; r < colorPerChannel; r++) {
for (int g = 0; g < colorPerChannel; g++) {
for (int b = 0; b < colorPerChannel; b++) {
Color color = new Color(r*255/(colorPerChannel-1), g*255/(colorPerChannel-1), b*255/(colorPerChannel-1)); //scale values to be [0,255]
colors.add(color);
}
}
}
// Create a pixel grid
GridBlock[][] grid = new GridBlock[width][height];
for (int row = 0; row < width; row++) {
for (int col = 0; col < height; col++) {
grid[row][col] = new GridBlock(row,col);
}
}
// List for all pixels currently being considered
List<GridBlock> filledNodesWithNeighbors = new ArrayList<GridBlock>();
List<GridBlock> done = new ArrayList<GridBlock>();
// Give the starting pixel a color and add it to the active list
Color startColor = colors.remove(random.nextInt(colors.size()));
img.setRGB(startX, startY, startColor.getRGB());
grid[startX][startY].color = startColor;
filledNodesWithNeighbors.add(grid[startX][startY]);
done.add(grid[startX][startY]);
int stepsToTake = 1;
while (colors.size() > 0) {
List<GridBlock> perimeterNodes = new ArrayList<GridBlock>();
for (GridBlock currentNode : filledNodesWithNeighbors) {
int neighborhoodRadius = 1;
int rowStart = Math.max(currentNode.x-neighborhoodRadius, 0);
int rowFinish = Math.min(currentNode.x+neighborhoodRadius, width-1);
int colStart = Math.max(currentNode.y-neighborhoodRadius, 0);
int colFinish = Math.min(currentNode.y+neighborhoodRadius, height-1);
boolean hasEmptyNeighbor = false;
for (int row = rowStart; row <= rowFinish; row++) {
for (int col = colStart; col <= colFinish; col++) {
if (grid[row][col].color == null && !perimeterNodes.contains(grid[row][col]) && !done.contains(grid[row][col])) {
hasEmptyNeighbor = true;
perimeterNodes.add(grid[row][col]);
}
}
}
}
for (GridBlock node : perimeterNodes) {
node.color = ColorUtilities.getClosestColorFrom(colors, startColor);
colors.remove(node.color);
filledNodesWithNeighbors.add(node);
img.setRGB(node.x, node.y, node.color.getRGB());
done.add(node);
GridBlock currentNode = node;
for (int i = 0; i < stepsToTake; i++) {
List<GridBlock> unfilledNeighbors = new ArrayList<GridBlock>();
int neighborhoodRadius = 1;
int rowStart = Math.max(currentNode.x-neighborhoodRadius, 0);
int rowFinish = Math.min(currentNode.x+neighborhoodRadius, width-1);
int colStart = Math.max(currentNode.y-neighborhoodRadius, 0);
int colFinish = Math.min(currentNode.y+neighborhoodRadius, height-1);
for (int row = rowStart; row <= rowFinish; row++) {
for (int col = colStart; col <= colFinish; col++) {
if (grid[row][col].color == null) {
unfilledNeighbors.add(grid[row][col]);
}
}
}
if (unfilledNeighbors.size() > 0) {
currentNode = unfilledNeighbors.get(random.nextInt(unfilledNeighbors.size()));
currentNode.color = ColorUtilities.getClosestColorFrom(colors, startColor);
done.add(currentNode);
colors.remove(currentNode.color);
img.setRGB(currentNode.x, currentNode.y, currentNode.color.getRGB());
filledNodesWithNeighbors.add(currentNode);
} else {
filledNodesWithNeighbors.remove(currentNode);
}
}
}
}
System.out.println(colors.size()); //Make sure I used all the colors
try (OutputStream out = new BufferedOutputStream(new FileOutputStream("images/"+new Date().getTime()+".png"))) {
ImageIO.write(img, "png", out);
} catch (IOException e) {
e.printStackTrace();
}
long endTime = new Date().getTime();
long executionTime = (endTime-startTime)/1000;
System.out.println("Finished in "+executionTime+" seconds");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment