Processingで画像の読み込みと表示、移動と回転

# はじめに
 Processingで画像を表示する解説です。
gif, jpg, tga, pngに対応していますが。無劣化＆圧縮＆透明可のpngが使いやすいでしょう。
本投稿は次のTruchetタイルの記事に繋がります。

https://qiita.com/hextomino/items/5be81453b856940df92e

# 画像の準備
イラストレータで正方形のアートボードを用意します。書き出し時にサイズ指定するので、サイズは何でも構いません。

背景色となる四角と文字を書きます。
文字は何でも構いません。上下左右がわかるものにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/bd585293-9ece-e8c0-0e49-403bc17dd047.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/315092b6-208a-46dc-cd20-e07d97ca5c4d.png)

一度、通常のイラストレータ形式で保存します。
その後、書き出し＞Web用に保存を選択し、PNG-24の、サイズ64x64で、a.pngという名前で保存します。

※ファイル名に日本語を使ってはいけません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/d76c4633-1f00-1732-10d8-818a7f08fb9a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/979b3ef2-e14a-c481-f5a3-a62c6eb83289.png)




















# 画像の読み込みと表示

以下のプログラムをコピペ。
プログラムを保存し、保存したフォルダに、a.pngを移動します。

または、processingのウィンドウに画像ファイルをドラッグ＆ドロップします。
この場合はdataという名前のフォルダが自動生成され、その中にファイルコピーされます。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");
image(a, 0, 0);
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/4440e6de-4e50-5daf-b451-052540b5481b.png)































loadImage("ファイル名")で画像の読み込み。
image(PImage,x座標,y座標)で画像の表示。

# 画像を並べて表示①

for文を入れ子構造で使い、縦横に並べる。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for(int y=0; y<640; y+=64){
  for(int x=0; x<640; x+=64){
    image(a, x, y);
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/1d5c3a86-2b23-2431-bdf2-0b32a4a3b9ac.png)


































# 画像を並べて表示②

translateを使うが、うまくいかない例。
思っていた移動をしてくれない。
64
64+64
64+64+64
となって、移動距離が積算されてしまう。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for(int y=0; y<640; y+=64){
  for(int x=0; x<640; x+=64){
    translate(x, y);
    image(a, 0, 0);
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/be8cdcd4-19e1-7686-90d7-c736543ca7ed.png)


理由：
内部では、移動、回転、拡縮をつかさどる行列があり、積算されてゆく。



















-------------------
translateを使い、うまくいく例。
描画の前に、行列リセット(resetMatrix)＞移動＞描画をする。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for(int y=0; y<640; y+=64){
  for(int x=0; x<640; x+=64){
    resetMatrix();
    translate(x, y);
    image(a, 0, 0);
  }
}
```
以下のように書いても、表示は可能だが、
頭の中がごちゃごちゃになるだろう。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for(int y=0; y<10; y++){
  for(int x=0; x<10; x++){
    image(a, 0, 0);
    translate(64, 0);
  }
  translate(-640, 0);
  translate(0, 64);
}
```

# pushとpop
内部では、移動、回転、拡縮をつかさどる行列があり、積算されてゆく。
push命令は、その行列の状態を一時的に保存する。
pop命令はその保存した状態に戻す。
pushとpopで挟むことで、移動、回転、拡縮の影響が一時的なものになる。

```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for (int y=0; y<640; y+=64) {
  for (int x=0; x<640; x+=64) {
    push();
      translate(x, y);
      image(a, 0, 0);
    pop();
  }
}
```

# 回転
rotate命令で画像を回転させることができる。
ただし、回転中心は「原点中心」であることに注意。
「回転＞移動＞描画」の例を示す。全体が回転する。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for (int y=0; y<640; y+=64) {
  for (int x=0; x<640; x+=64) {
    push();
      rotate(PI*0.25);
      translate(x, y);
      image(a, 0, 0);
    pop();
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/f0fb5c69-b905-a90a-7cb0-51357d99ae29.png)
















「移動＞回転＞描画」の例を示す。個々が回転する。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for (int y=0; y<640; y+=64) {
  for (int x=0; x<640; x+=64) {
    push();
      translate(x, y);
      rotate(PI*0.25);
      image(a, 0, 0);
    pop();
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/ee4c43eb-3d51-ee8d-b5e8-00853d173fd1.png)
















「回転してから移動する」のと、「移動してから回転する」のは、結果が異なる。

# 移動と回転の順序は逆から

「画像を回転させる」操作は、感覚的には、画像の中心で回転してほしい。
原点中心から、変更するには次のようにする。
```java:抜粋
translate(a.width/2, a.height/2);
rotate(PI*0.25);
translate(-a.width/2, -a.height/2);
image(a, 0, 0);
```
１行目：表示したい位置に移動する。
２行目：回転する。
３行目：画像の中心を原点に移動する。
４行目：描画
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/80924384-48fd-9480-76ca-de6f167486bf.png)
　ここで、注意が必要なのは「原点に移動して、回転して、好きな位置に移動する」という操作を、逆順（下から上へ）に書く必要がある。これは、行列に起因するものであるが、理由は割愛する。

ここまでを総括した、プログラム例を以下に示す。
```java
PImage a;

size(640, 640);
a = loadImage("a.png");

for (int y=0; y<640; y+=64) {
  for (int x=0; x<640; x+=64) {
    push();
      translate(x, y);
      rotate((x+y)*0.0013);
      translate(-a.width/2, -a.height/2);
      image(a, 0, 0);
    pop();
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/1f55610f-04ae-e016-f847-7287b8f2c1ce.png)

# 拡大縮小：スケール
image命令で、引数を２つ追加すると、表示サイズを変更できます。
image(PImage,x座標,y座標,横サイズ,縦サイズ)で画像の表示。
※元のサイズよりも、大きくなるとボケます。

```java
size(800, 400);
a = loadImage("a.png");

image(a,   0, 0, 400, 400);
image(a, 400, 0, 200, 200);
image(a, 600, 0, 100, 100);
image(a, 700, 0,  50,  50);
image(a, 750, 0,  25,  25);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/ed86f3a8-b60c-6c9f-b218-f688eb8c6220.png)

他にも、scale命令で大きさが変更できます。

scale(2)で２倍、
scale(0.5)で半分、
に大きさ変更ができます。
※アニメーションにしています。

```java
PImage a;

void setup() {
  size(800, 600);
  a = loadImage("a.png");
}

void draw(){
  background(255);
  push();
    translate(width/2, height/2);
    scale(10*sin(millis()*0.001));
    rotate(millis()*0.002);
    translate(-a.width/2, -a.height/2);
    image(a, 0, 0);
  pop();
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/9399362d-c253-82a6-bb31-1cb8ce11f7d8.png)