processingでモザイク処理。intとcolorの関係も。

processingでモザイク処理をしたいと思います。

https://kumohara-tagebuch.hatenablog.com/entry/2022/05/16/013859

の続きみたいなもの。

使用している関数など(重要なもの)

get関数

PImageのメソッドであるget()を用いている。これは

Pimage img;
int x=10 , y=10;
img = loadImage("hoge.png");
int c = img.get(x,y);

のように使い、 get()の返り値はint型(整数)か、引数によってはPImageを出す。今回は用いる画像の任意の1ピクセルの色が欲しいので、int型で扱う。

参考までに PImageのリファレンスはこちら processing.org get()のリファレンスはこちら processing.org

colorのリファレンスはこちら。 processing.org

colorとintの関係。

読み飛ばしても大丈夫。自分のメモ用に。

実はcolor型はint型と同義である。 バイナリで、 Aが透明度、Rが赤、Gが緑、Bが青色を示している。 AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB(2) AARRGGBB(16) であらわされる符号付32bitの整数である。 32bitでピンとくるかもしれないが、int型も符号付32bitである。 つまり、color col=color(255,255,0);は、()内のものを、int型に直して(ちょっとこの表現は語弊が起きそうだけど)いる。

このことは、次のサンプルコードからもわかる。

int c1=0xffffff00;//16進数表記
int c2=0b11111111111111111111111100000000;//二進数表記
int c3=-256;//十進数表記(これは符号付二進数で保存されているため)
color col=color(255, 255, 0);

void setup() {
  size(350, 450);
  noLoop();
}
void draw() {
  background(255);
  fill(col);
  rect(150, 50, 50, 50);
  fill(c1);
  rect(150, 150, 50, 50);
  fill(c2);
  rect(150,250,50,50);
  fill(c3);
  rect(150,350,50,50);
}

fill()はcolor型か、#ffffffか、0xffffffffで入れろとリファレンスでいわれているが、普通に十進数で入れても問題ないのである。(実用性は皆無だけど)

そして、bitシフトを用いることで、RGBの値のRだけ、Gだけ、Bだけを高速に出すことができる。

processing.org

このリファレンスのサンプルコードにそのようなことができるコードがある。

モザイク処理のプログラムにも同じ挙動のものがあるが、わかりやすいように少しリファレンスのサンプルコードと異なる。

モザイク処理

自分が作ったコードは以下である。 img.get(i,j)で色を拾って、その色で同じ場所に円を書いてあるだけである。

float I=1;//読み込み画像の大きさを変える
int n=2;
char mode='a';
float m=5;//モザイクの粗さ
PImage img;//画像を保存する変数
void setup() { 
  img=loadImage("aiu.jpg");//画像読み込み。
  surface.setResizable(true);//ここから二行の物はウィンドウサイズを可変にするため
  surface.setSize(int(img.width/I),int(img.height/I));
  background(255);
  frameRate(5);
  //noLoop();//draw部のループはしない
}

void draw() {
  //image(img, 0, 0,width,height);

  colorMode(RGB, 255, 255, 255, 100);//colorModeをHSVに。しかしこのコードでは使っていない
  noStroke();
  int r,g,b;
  color col=0;
  for (int i=0; i<width; i+=m) {
    for (int j=0; j<height; j+=m) {
      int c=img.get(i,j);
      r=(c & 0x00ff0000);//抜き出したいところ以外はすべて0にする。
      g=(c & 0x0000ff00);
      b=(c & 0x000000ff);
      r=r>>2*8;
      g=g>>8;
      b=b>>0;
      if(mode=='r')col=color(r,0,0);
      if(mode=='g') col=color(0,g,0);
      if(mode=='b') col=color(0,0,b);
      if(mode== 'a' ) col=color(r,g,b);
      fill(col);
      ellipse(i,j,m,m);
    }
  }
}


void keyPressed() {
  if (key=='s'||key=='S')save("hue.png");
  if (key=='r'||key=='R'){mode='r';background(255);}
  if (key=='g'||key=='G'){mode='g';background(255);}
  if (key=='b'||key=='B'){mode='b';background(255);}
  if (key=='a'||key=='A'){mode='a';background(255);}
}

実行した結果は以下である。(ちなみに上記のままだと、noLoop()でないので、少し塗りつぶされていくのに注意。(じゃなきゃ、r,g,bそれぞれの値を抜き出した結果を出せないんだもん!!))

元画像とモザイク画像