【C#】Base64url <-> Binary 相互変換

基本的に System.Convert を使えば Base64 <-> バイナリの相互変換出来ます。

Base64 → Base64URL

string base64url = base64.Replace('/','_').Replace('+','-');

Base64URL → Base64

string base64 = base64url.Replace('_','/').Replace('-','+');

Base64URL → binary

// 文字数を4の倍数にする
int surplus = base64.Length % 4; // 4でパディング
string padding = ( surplus > 0) ? new string( '=', 4 - surplus) : string.Empty; // パディングを = で埋める
// - を + に置換
// _ を / に置換
// 余白に = で埋める
byte[] data = System.Convert.FromBase64String( base64url.Replace('_','/').Replace('-','+') + padding);
return data;

binary → Base64URL

string base64 = System.Convert.ToBase64String( data);
// = を削除
// + を - に置換
// / を _ に置換
string base64url = base64.TrimEnd('=').Replace('+','-').Replace('/','_');
return base64url;

おまけ

最終的に Base64URL -> PNG が必要だったのでまとめました。
Unity などは Texture.LoadImage( png);
に突っ込めば HTTP 経由で画像をロードできます。

Base64URL → PNG

リトルエンディアン環境でしか c# を使ったことがないので、環境に合わせて変更してください。

static public byte[] signaturePNG { get{ return new byte[]{ 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; }}
static public byte[] signatureIHDR{ get{ return new byte[]{ 0x49, 0x48, 0x44, 0x52 }; }}
public static bool Base64Url2Png(
	out byte[] outPngData,
	out uint outWidth,
	out uint outHeight
)
{
	try
	{
		// Base64URL -> Binary
		int surplus = base64url.Length % 4;
		string padding = ( surplus > 0) ? new string( '=', 4 - surplus) : string.Empty;
		byte[] imageData = Convert.FromBase64String( base64url.Replace('_','/').Replace('-','+') + padding);
		// PNG チェック
		using( var memoryStream = new System.IO.MemoryStream( imageData))
		{
			if( memoryStream.Length < 32) throw new Exception(); // 異常ファイル
			using( var reader = new System.IO.BinaryReader( memoryStream))
			{
				byte[] signature = reader.ReadBytes( 8);
				if( !signature.SequenceEqual( signaturePNG)) throw new Exception(); // 異常ファイル

				byte[] tmp = reader.ReadBytes( 4);
				Array.Reverse( tmp); // Byte swapping Big endian → Little endian
				var ihdr_length = System.BitConverter.ToUInt32( tmp, 0);
				if( ihdr_length != 13) throw new Exception(); // 異常ファイル

				signature = reader.ReadBytes( 4);
				if( !signature.SequenceEqual( signatureIHDR)) throw new Exception(); // 異常ファイル

				tmp = reader.ReadBytes( 4);
				Array.Reverse( tmp);
				var ihdr_width = System.BitConverter.ToUInt32( tmp, 0);
				tmp = reader.ReadBytes( 4);
				Array.Reverse( tmp);
				var ihdr_height = System.BitConverter.ToUInt32( tmp, 0);
				var ihdr_bitDepth = reader.ReadByte();
				var ihdr_colorType = reader.ReadByte();
				var ihdr_filter = reader.ReadByte();
				var ihdr_interlace = reader.ReadByte();
				tmp = reader.ReadBytes( 4);
				Array.Reverse( tmp);
				var ihdr_crc = System.BitConverter.ToUInt32( tmp, 0);
				// 本来はcrcチェックするのが望ましい

				outWidth = ihdr_width;
				outHeight = ihdr_height;
				outPngData = imageData;
			}
		}
	}
	catch( Exception e)
	{
		// 異常ファイル
		outPngData = null;
		outWidth = 0;
		outHeight = 0;
		return false;
	}
	return true;
}

Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です