デバッグ用の画像データを生成する

画像処理のプログラムを作るときには、わかりやすいデータが格納されているデバッグ用の画像で実施しているコードが正しいか常に確認しなくてはなりません。

その確認作業には風景画像や人物写真を使うべきではありません。所望のアドレスに入っているデータが推測できないからです。(たとえ SIDBA や lenna であっても、使うべきではない )

私のおすすめは下記のような画像です。これらは(X,Y)座標に格納されている値が確実にわかる画像です。

水平ノコギリ波
垂直ノコギリ波
ななめノコギリ波
水平コサイン波 ( dycle = 4.0 )
垂直コサイン波 ( cycle = 4.0 )
水平垂直加算コサイン波 ( cycle = 4.0 )
水平グラデーション
垂直グラデーション
ななめグラデーション

下記のコードはこれらのテストパターンを byte[] データ配列に格納します。引数として与える width と height には 2 のべき乗の数値を与えるのがデバッグに使いやすいです。たとえば 256 とか 512 とか 1024 という値です。

また、width と height は違ったべき乗の値にしておくのが仕事のコツです。たとえば

width = 512;
height = 256;

こういう感じです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace aaa
{

	public class ApplicationUtility
	{

		public ApplicationUtility()
		{
		
		}

		// べったり同じ色のデータの画像を取得する.
		public bool GetDataFill( byte [] data, int width, int height, byte level )
		{

			int w = width;
			int h = height;
			int numpix = w * h;

			int adrs = 0;

			for ( int n = 0; n < numpix; n++ )
			{
				data[adrs] = level;
				adrs++;
			}

			return true;

		}

		// 水平ノコギリ波の画像を取得する.
		public bool GetDataSawtoothHorz( byte [] data, int width, int height )
		{

			int w = width;
			int h = height;

			byte level;

			int adrs;

			for ( int j = 0; j < h; j++ )
			{

				level = (byte)(j);
				adrs = w * j;

				for ( int i = 0; i < w; i++ )
				{
					data[ adrs ] = level;
					adrs++;
				}

			}

			return true;

		}

		// 垂直ノコギリ波の画像を取得する.
		public bool GetDataSawtoothVert( byte [] data, int width, int height )
		{

			int w = width;
			int h = height;
			
			byte level;

			int skip = w;
			int adrs;

			for ( int i = 0; i < w; i++ )
			{

				level = (byte)(i);
				adrs = i;

				for ( int j = 0; j < h; j++ )
				{
					data[ adrs ] = level;
					adrs += skip;
				}

			}

			return true;

		}

		// ななめノコギリ波の画像を取得する.
		public bool GetDataSawtoothNaname( byte [] data, int width, int height )
		{

			int w = width;
			int h = height;
			byte level;

			for ( int j = 0; j < h; j++ )
			{
				for ( int i = 0; i < w; i++ )
				{
					level = (byte)( i + j );
					data[ i + w  * j ] = level;
				}
			}

			return true;

		}

		// 水平コサインデータの画像を取得する.
		public bool GetDataCosWaveHorz( byte [] data, int width, int height, double cycle )
		{

			int w = width;
			int h = height;

			double two_pai = 2.0 * Math.PI;
			double rate;
			double rad;

			double tmp0;
			double tmp1;
			byte level;

			byte [] table = new byte[ h ];

			const double OFFSET = 1.0;
			const double MUL = 0.5;

			// テーブルを作る.
			for ( int j = 0; j < h; j++ )
			{
				// ラジアンを算出する.
				rate = (double)(j)/(double)( h - 1 );
				rad = rate * two_pai;

				// ここでコサインの計算をする.
				tmp0 = -( Math.Cos( cycle * rad ));

				// 0.0 から 1.0 が存在範囲.
				tmp1 = (( tmp0 + OFFSET ) * MUL );

				// 0 から 255 にキャストする.
				level = (byte)( Math.Round( tmp1 * 255.0 ));
				table[j] = level;
			}

			int adrs;

			// 水平の cos 波形2D, ( 0 から 1.0 ).
			for ( int j = 0; j < h; j++ )
			{

				level = table[j];
				adrs = w * j;

				for ( int i = 0; i < w; i++ )
				{
					data[ adrs ] = level;
					adrs++;
				}

			}

			return true;

		}

		// 垂直コサインデータの画像を取得する.
		public bool GetDataCosWaveVert( byte [] data, int width, int height, double cycle )
		{

			int w = width;
			int h = height;

			double two_pai = 2.0 * Math.PI;
			double rate;
			double rad;

			double tmp0;
			double tmp1;
			byte level;

			byte [] table = new byte[ w ];

			const double OFFSET = 1.0;
			const double MUL = 0.5;

			// テーブルを作る.
			for ( int i = 0; i < w; i++ )
			{
				// ラジアンを算出する.
				rate = (double)(i)/(double)( w - 1 );
				rad = rate * two_pai;

				// ここでコサインの計算をする.
				tmp0 = -( Math.Cos( cycle * rad ));

				// 0.0 から 1.0 が存在範囲.
				tmp1 = (( tmp0 + OFFSET ) * MUL );

				// 0 から 255 にキャストする.
				level = (byte)( Math.Round( tmp1 * 255.0 ));
				table[i] = level;
			}

			int adrs;

			// 垂直の cos 波形2D, ( 0 から 1.0 ).
			for ( int j = 0; j < h; j++ )
			{
				adrs = w * j;
				for ( int i = 0; i < w; i++ )
				{
					data[ adrs ] = table[i];
					adrs++;
				}
			}

			return true;

		}

		// 水平垂直加算コサインデータの画像を取得する.
		public bool GetDataCosWaveHorzVert( byte [] data, int width, int height, double cycle )
		{

			int w = width;
			int h = height;

			double two_pai = 2.0 * Math.PI;
			double rate;
			double rad;

			double tmp;

			double [] table_for_a = new double[ h ];
			double [] table_for_b = new double[ w ];

			const double OFFSET = 1.0;
			const double MUL = 0.5;

			// テーブルを作る.
			for ( int j = 0; j < h; j++ )
			{
				// ラジアンを算出する.
				rate = (double)(j)/(double)( h - 1 );
				rad = rate * two_pai;

				// ここでコサインの計算をする.
				tmp = -( Math.Cos( cycle * rad ));

				// 0.0 から 1.0 が格納される.
				table_for_a[j] = (( tmp + OFFSET ) * MUL );
			}

			// テーブルを作る.
			for ( int i = 0; i < w; i++ )
			{
				// ラジアンを算出する.
				rate = (double)(i)/(double)( w - 1 );
				rad = rate * two_pai;

				// ここでコサインの計算をする.
				tmp = -( Math.Cos( cycle * rad ));

				// 0.0 から 1.0 が格納される.
				table_for_b[i] = (( tmp + OFFSET ) * MUL );
			}

			double a;
			double b;
			byte level;

			int adrs;

			for ( int j = 0; j < h; j++ )
			{

				// 0.0 から 1.0 の範囲をとる.
				a = table_for_a[j];

				adrs = w * j;

				for ( int i = 0; i < w; i++ )
				{
					// 0.0 から 1.0 の範囲をとる.
					b = table_for_b[i];

					// 両方を加算すると 0.0 から 2.0 の範囲をとる.
					tmp = a + b; 

					// 0 から 255 の byte 区間にマッピングする.
					level = (byte)( Math.Round(( tmp * 0.5 ) * 255.0 ));

					// 8bits画像データとして格納する.
					data[ adrs ] = level;

					adrs++;

				}	
			}

			return true;

		}

		// 水平グラデーションデータの画像を取得する.
		public bool GetDataGradHorz( byte [] data, int width, int height )
		{

			int w = width;
			int h = height;

			byte level;
			double rate;

			int adrs;

			for ( int j = 0; j < h; j++ )
			{

				rate = (double)(j)/(double)( h - 1 );
				level = (byte)( Math.Round( rate * 255.0 ));

				adrs = w * j;

				for ( int i = 0; i < w; i++ )
				{
					data[ adrs ] = level;
					adrs++;
				}

			}

			return true;

		}

		// 垂直グラデーションデータの画像を取得する.
		public bool GetDataGradVert( byte [] data, int width, int height )
		{

			int w = width;
			int h = height;

			byte level;
			double rate;

			int skip = w;
			int adrs;

			for ( int i = 0; i < w; i++ )
			{

				rate = (double)(i)/(double)( w - 1 );
				level = (byte)( Math.Round( rate * 255.0 ));

				adrs = i;

				for ( int j = 0; j < h; j++ )
				{
					data[ adrs ] = level;
					adrs += skip;
				}

			}

			return true;

		}

		// ななめグラデーションデータの画像を取得する.
		public bool GetDataGradNaname( byte [] data, int width, int height )
		{

			int w = width;
			int h = height;

			double value_i;
			double value_j;

			double rate_x;
			double rate_y;

			byte level;

			int adrs;

			for ( int j = 0; j < h; j++ )
			{

				rate_y = (double)(j)/(double)( h - 1 );
				value_j = ( rate_y * 127.0 );

				adrs = w * j;

				for ( int i = 0; i < w; i++ )
				{

					rate_x = (double)(i)/(double)( w - 1 );
					value_i = ( rate_x * 128.0 );

					level = (byte)( Math.Round( value_i + value_j ));

					data[ adrs ] = level;
					adrs++;

				}

			}

			return true;

		}

	}

}

サンプルソースを用意しました。上記のコードのコピーペーストでうまく動かない場合にご利用ください。