ハメ太郎のブログ

意味のあることなんて無い

Processing でドット絵を描く

ドット絵とは?

・ピクセルが目視できるほど解像度が低い

・使われてる色が少ない

ファミコン風、高解像度の格ゲーキャラドット等種類は様々

→既存の絵をドット絵風に変換することはできないか?

 元絵

f:id:hametaro:20140815232458p:plain

f:id:hametaro:20140816003520p:plain

//ドット一つをオブジェクト一つとみなし、ColorDotクラスを作った。
//引数は左上の座標とドットサイズ。
//ドット内部の点の色を総計し、平均を出す。
//平均を出す際にはR,G,Bに一度分解しなければならない
PImage img;
int pallet_r = {
0,39,0,71,143,171,167,127,67,0,
0,0,27,117,0,35,131,191,231,219,
203,139,0,0,0,0,188,63,95,167,
247,255,255,255,243,131,79,88,0,255,
171,199,215,255,255,255,255,255,227,171,
179,159
};
int
pallet_g = {
0,27,0,0,0,0,0,11,47,71,
81,63,63,117,115,59,0,0,0,43,
79,115,151,171,147,131,188,191,115,139,
123,119,119,155,191,211,223,248,235,255,
231,215,203,199,199,191,219,231,255,243,
255,255
};
int pallet_b = {
0,143,171,159,119,19,0,0,0,0,
0,23,95,117,239,239,243,191,91,0,
15,0,0,0,59,139,188,255,255,253,
255,183,99,59,63,19,75,152,219,255,
255,255,255,255,219,179,171,163,163,191,
207,243
};

final int dotSize = 3;
final int n = 100000;
Dot dots = new Dot[n];
void setup() {
String imgPath = selectInput();
img = loadImage(imgPath);
noStroke();
size(img.width,img.height);
background(255);
image(img,0, 0);
loadPixels();
for(int i = 0; i < width/dotSize; i++){
for(int j = 0; j < height/dotSize; j++){
dots[i+(j*width/dotSize)] = new Dot(i*dotSize,j*dotSize,dotSize);
}
}

}

void draw() {
for(int i = 0; i < width/dotSize; i++){
for(int j = 0; j < height/dotSize;j++){
dots[i+(j*width/dotSize)].draw();
}
}
}
void keyPressed() {
if (key == ENTER) { // Enterキーに反応
save("output.png");
}
}
class Dot{
int x,y;//ドット左上の点の座標
int dotSize;//ドットサイズ
float c_r = red(pixels[x+y*width]);
float c_g = green(pixels[x+y*width]);
float c_b = blue(pixels[x+y*width]);
color c;//ドットの平均の色
float []temp_color_distance = new float [52];


//コンストラクタ
Dot(int def_x, int def_y, int def_dotSize){
x = def_x;
y = def_y;
dotSize = def_dotSize;
//ドット内の色の平均
for(int i = 0; i < dotSize; i++){
for(int j = 0; j < dotSize; j++){
c_r += red(pixels[(i+x) + (y+j)*width]);
c_g += green(pixels[(i+x) +(y+j)*width]);
c_b += blue(pixels[(i+x) + (y+j)*width]);
}
}
c_r = c_r/(dotSize*dotSize);
c_g = c_g/(dotSize*dotSize);
c_b = c_b/(dotSize*dotSize);
//ドットの平均とパレット[i]との色の距離
for(int i = 0; i < 51; i++){
temp_color_distance[i] =
(c_r-pallet_r[i])*(c_r-pallet_r[i])+
(c_g-pallet_g[i])*(c_g-pallet_g[i])+
(c_b-pallet_b[i])*(c_b-pallet_b[i]);
}
//temp_color_distanceが最小になるカラーパレットを探す
float temp_color_distance_min = temp_color_distance[0];
for(int i = 0; i < 51; i++){
if(temp_color_distance_min > temp_color_distance[i]){
temp_color_distance_min = temp_color_distance[i];
}
}
//最小となる=一番近い色のカラーパレットで色を置き換える
for(int i = 0; i < 51; i++){
if(temp_color_distance[i] == temp_color_distance_min){
c_r = pallet_r[i];
c_g = pallet_g[i];
c_b = pallet_b[i];
}
}
}
//ドットを描くメソッド
void draw(){
c = color(int(c_r),int(c_g),int(c_b));
fill(c);
rect(x, y, dotSize, dotSize);
}
}

 

f:id:hametaro:20141107044609p:plain

f:id:hametaro:20141107044625p:plain

f:id:hametaro:20141107044633p:plain

f:id:hametaro:20141107044641p:plain

f:id:hametaro:20141107044704p:plain