.NET で画像イメージを JPEG に変換する方法

.NET で画像イメージ (Bitmap のインスタンス) を JPEG データのバイトデータにメモリ内で変換するには、以下のようにするとよい。

public static byte[] SaveAsJpeg(Bitmap bmp, int quality)
{
	EncoderParameters eps = new EncoderParameters(1);
	EncoderParameter ep = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
	eps.Param[0] = ep;

	ImageCodecInfo info = getEncoderInfo("image/jpeg");

	MemoryStream ms = new MemoryStream();
	bmp.Save(ms, info, eps);

	return ms.ToArray();
}

static ImageCodecInfo getEncoderInfo(string type)
{
	ImageCodecInfo[] encs = ImageCodecInfo.GetImageEncoders();
	foreach (ImageCodecInfo enc in encs)
	{
		if (enc.MimeType == type)
		{
			return enc;
		}
	}
	return null;
}


なお、「quality」は JPEG の画質を意味する整数で、1 から 100 のうち任意の数を指定する。

.NET でクレジットカードの番号チェックを行う方法

クレジットカードの番号はチェックサム桁が入っているため、入力された番号に入力ミスがないかどうかは、センターにオンラインで問い合わせることなく、オフラインで知ることができる。
具体的には以下のようなコードでチェックできる。確かどこかにあった JavaScript 用のアルゴリズムを参考にして C# で書いてみたものである。

public static bool CheckCCNumber(string digitsOnly)
{
	int sum = 0;
	int digit = 0;
	int addend = 0;
	bool timesTwo = false;

	for (int i = digitsOnly.Length - 1; i >= 0; i--)
	{
		digit = int.Parse(digitsOnly[i]);
		if (timesTwo)
		{
			addend = digit * 2;
			if (addend > 9)
			{
				addend -= 9;
			}
		}
		else
		{
			addend = digit;
		}

		sum += addend;
		timesTwo = !timesTwo;
	}

	int modules = sum % 10;
	return (modules == 0);
}


なお、クレジットカード会社がどの会社であるのかということは、カード番号の先頭の数字を見れば判別できる。現在は以下のように判別できる。

先頭の数字 カード会社
4 Visa
5 Master Card
34 American Express
35 JCB

.NET の静的コンストラクタ

.NET のクラスには、静的コンストラクタというものがある。
これは .NET で、そのクラスが初めて使用される直前 (より厳密には、そのクラスの型がインスタンス化される直前) に自動的に呼び出される初期化用の関数である。
複数のスレッドが単一のクラスをはじめて使用しようとする場合も、この静的コンストラクタは 1 度しか呼ばれないように保証される (はず)。
クラス内の静的なフィールドを、定数以外で、安全に初期化するタイミングとして最適。これを知らなかったころは、すごい変なコードを自前で書いて実装していた。


なお、静的コンストラクタが例外を発生させた場合はどうなるのかということが興味深いが、どうやら、例外が発生した後もそのクラス自体は普通に使えるようである。ただし例外が発生した場所以降の静的コンストラクタの初期化処理は行われないので、そのクラスの静的フィールドの内部状態は未初期化のまま放置されてしまうということになる。


例として、以下のようなプログラムを書くと、
外部から TestClass.TestString を最初に参照しようとすると、直前に自動的に静的コンストラクタである static TestClasss() が呼び出され、初期化された後の TestClass.TestString の値が返される。

static class TestClass
{
	public static string TestString;

	static TestClass()
	{
		TestClass.TestString = "こんちは!";
	}
}

class Program
{
	static void Main(string[] args)
	{
		System.Console.WriteLine(TestClass.TestString);
	}
}