フォトモザイクやりたいな〜その１

はい、今回は画像周り。
最近数年やらなかったことをまとめて叩き込んでおります。
できることは増やしておかないとね。

画像の平均値とか色と色の距離とか。
最終的にやりたいのはフォトモザイク。えっと、一枚の画像があって、それのいろをもとに
例えばtwitterのフォローアーの画像で元の絵になるようにならべたりとかするやつ。
今回は元絵の平均色だすところとかまで。
平均色は全部足して割ればいいから簡単。
なぜにUnityでやる？ときかれればmacにFlashいれてないから・・・。phpのローカル開発環境もいれてないからいちいちサーバーにあげてテストするのもめんどくさいのです。という個人的な理由です。

こんなカラフルな画像があって、500*500
<img width="194" alt="スクリーンショット 2016-09-08 10.17.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/01926fff-fe18-6509-535d-cd74e2fa425b.png">

10 *10だと
<img width="175" alt="スクリーンショット 2016-09-08 10.18.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/3728de37-6a31-fa55-f1ec-50b37d8ab320.png">

20*20
<img width="184" alt="スクリーンショット 2016-09-08 10.17.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/98e837e1-8df2-db3e-2604-2ab4c9679e5c.png">

50*50
<img width="173" alt="スクリーンショット 2016-09-08 10.20.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/4d2e52ad-e453-eef5-fb99-6b433628bbf9.png">

になるようにしたよというだけ。

とりあえず簡単に縦横が同じサイズのもののみしか考慮しないでやってみたところ。

```csharp
	public RawImage baseImg;
	public RawImage resultImg;
	public Texture2D baseTex;

	void Start () {
		int w = baseImg.texture.width;
		int h = baseImg.texture.height;

		int cellCount = 50;
		int cellSize = w / cellCount;

		Texture2D avarageTex = new Texture2D(cellCount, cellCount, TextureFormat.RGBA32, false);
		int xIndex = 0;
		int yIndex = 0;
		for(int y = 0; y < h; y += cellSize)
		{
			xIndex = 0;
			for(int x = 0; x < w; x += cellSize)
			{
				Color c = GetAvarageColor(baseTex, x, y, cellSize, cellSize);
				avarageTex.SetPixel(xIndex, yIndex, c);
				xIndex++;
			}
			yIndex++;
		}
		avarageTex.Apply();
		resultImg.texture = avarageTex;

	}

	// 1ます分の平均色を計算
	private Color GetAvarageColor(Texture2D tex, int startX, int startY, int cellWidth, int cellHeight)
	{
		float rrr = 0;
		float ggg = 0;
		float bbb = 0;

		for(int y = startY; y < startY + cellHeight; y++)
		{
			for(int x = startX; x < startX + cellWidth; x++)
			{
				Color c = tex.GetPixel(x,y);
				rrr += c.r;
				ggg += c.g;
				bbb += c.b;
			}
		}

		rrr /= (float)cellWidth * (float)cellHeight;
		ggg /= (float)cellWidth * (float)cellHeight;
		bbb /= (float)cellWidth * (float)cellHeight;

		return new Color(rrr, ggg, bbb, 1);
	}
```


この続きはなんか適当に大量の同じサイズの画像とかを用意して、
事前に平均の色を計算させておき、それをテキストか何かにまとめておく。
ここまでは事前にやっておかないと、表示まで時間かかっちゃうもんね。
あとは先ほどの計算したブロッグごとの色を元にたくさんの画像から色の近い順ものを当てはめていく。
色と色の距離は三平方の定理？みたいなのでもとめられるのでこれが近いものをセットしてあげれば完成するはず。

とりあえず画像を調達しにflickrからとりあえず100枚ぐらい適当にダウンロードしてきて、
automatorさんに200px*200pxとかのサイズにしてもらった。100枚とかでたりるかな・・・・って気もするけどいいや。
デスクトップに吐き出して途中NOOOOOO!ってなったりしたけど。ちゃんと片付けました。
<img width="300" alt="スクリーンショット 2016-09-08 10.55.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/f57b145b-e81b-42eb-0b6e-c903849b2a39.png">

次は各画像ごとの平均色をまとめたファイルとか作る作業
フォーマットは画像名:平均色r,g,b　みたいなかんじでいいかな。

まぁとりあえずこんな感じで・・・。

```csharp
	public string pathImgList;

	void Start () {
		pathImgList = Application.dataPath + "/Resources/Texture";
		StreamWriter sw = null;
		FileInfo fi;
		fi = new FileInfo(Application.dataPath + "/Resources/imgData.txt");

		// .metaがはいってしまうので.jpgのみに絞る
		string[] imgPathList = Directory.GetFiles( pathImgList, "*.jpg");
		int imgCount = imgPathList.Length;
		for( int i = 0; i < imgCount; i++ )
		{
			var s = File.ReadAllBytes(imgPathList[i]);
			Texture2D tex = new Texture2D(2, 2);
			tex.LoadImage(s);

			int w = tex.width;
			int h = tex.height;

			Color c = GetAvarageColor(tex, 0, 0, w, h);

			sw = fi.AppendText();

			sw.WriteLine(imgPathList[i].Replace(pathImgList + "/", "") + ":" + c.r + ","+ c.g + ","+ c.b );


			Debug.Log(imgPathList[i] + ":" + c);
			sw.Flush();
			sw.Close();
		}
	}

```

実行するとこんな感じのファイルが出力される。
あとは気合だね。うん、最初から気合だったね。
<img width="333" alt="スクリーンショット 2016-09-08 15.39.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/46444/26e2b477-368d-8978-7091-a9d139f3aec3.png">

一旦ここまで。