C#を利用したアプリケーション開発において、画像データを文字列として扱いたい場面は多々あります。
例えば、Web APIを通じてJSON形式で画像を送信する場合や、HTML内に直接画像を埋め込む「Data URI」を作成する場合などです。
このような際、バイナリデータである画像をテキスト形式に変換する手法としてBase64エンコードが広く利用されています。
本記事では、C#を用いて画像をBase64に変換する方法、およびその逆のデコード処理について、最新の.NET環境に基づいた最適な実装方法を詳しく解説します。
Base64エンコードの基本概念と仕組み
画像を文字列に変換する具体的なコードの前に、まずはBase64という仕組みがどのようなものか、なぜ画像転送において重要なのかを理解しておきましょう。

Base64とは何か
Base64は、バイナリデータを64種類の英数字と記号(A-Z, a-z, 0-9, +, /)のみを用いて表現するエンコード方式です。
コンピュータが扱う画像や音声などのバイナリデータは、そのままではテキストとして転送できないプロトコル(通信規約)が存在します。
例えば、古いメールサーバーや特定のAPI仕様では、制御文字が含まれるバイナリデータを正しく処理できないことがあります。
Base64を使用することで、あらゆるバイナリデータを「人間が読める文字の組み合わせ」に変換できるため、通信の安定性が向上します。
ただし、Base64に変換すると元のデータサイズよりも約33%ほどサイズが増加するという特性がある点は注意が必要です。
C#で画像を扱う際のライブラリ選定
現在のC#環境(.NET 6/7/8/9以降)では、画像処理に使用するライブラリがいくつか存在します。
かつてはSystem.Drawing(GDI+)が主流でしたが、現在はマルチプラットフォーム環境での動作を考慮し、以下のような選択肢があります。
| ライブラリ名 | 特徴 | 推奨される用途 |
|---|---|---|
System.IO | 基本的なファイル操作のみ | 単純なバイト列変換 |
ImageSharp | 完全マネージドな画像ライブラリ | クロスプラットフォーム開発 |
SkiaSharp | GoogleのSkiaベースの高速描画 | 高性能な画像生成・加工 |
System.Drawing.Common | Windows依存が強い | レガシーなWindowsアプリの移行 |
今回の解説では、最も汎用的で依存関係の少ない「バイト列(byte[])を介した変換」を中心に解説します。
これにより、どの画像ライブラリを使用していても、最終的にBase64文字列への変換が可能になります。
画像をBase64文字列にエンコードする方法
それでは、実際のC#コードを見ていきましょう。
最もシンプルな方法は、画像ファイルをFile.ReadAllBytesで読み込み、Convert.ToBase64Stringメソッドを利用することです。

基本的なエンコードの実装
以下のサンプルコードは、ローカルにある画像ファイルを読み込み、それをBase64文字列に変換してコンソールに表示するものです。
using System;
using System.IO;
class Program
{
static void Main()
{
// 変換したい画像ファイルのパス
string imagePath = "sample_image.png";
try
{
// 1. 画像ファイルをバイト配列として読み込む
byte[] imageBytes = File.ReadAllBytes(imagePath);
// 2. バイト配列をBase64文字列に変換する
string base64String = Convert.ToBase64String(imageBytes);
// 結果の表示(最初の100文字のみ表示)
Console.WriteLine("Base64エンコードに成功しました。");
Console.WriteLine("先頭100文字: " + base64String.Substring(0, 100) + "...");
}
catch (FileNotFoundException)
{
Console.WriteLine("エラー: 指定された画像ファイルが見つかりません。");
}
catch (Exception ex)
{
Console.WriteLine($"エラーが発生しました: {ex.Message}");
}
}
}
Base64エンコードに成功しました。
先頭100文字: iVBORw0KGgoAAAANSUhEUgAAAlgAAACWCAYAAAD9+S7vAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7D...
メモリ内の画像オブジェクトから変換する場合
ファイルからではなく、プログラム上で作成・加工した画像オブジェクト(例えば System.Drawing.Image)をBase64に変換する場合は、MemoryStreamを経由する必要があります。
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
public string ImageToBase64(Image image, ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// 画像をMemoryStreamに保存
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
// Base64に変換
return Convert.ToBase64String(imageBytes);
}
}
この方法では、MemoryStreamに画像を書き出す際に、JPEGやPNGといったフォーマットを明示的に指定できるのが利点です。
Base64文字列を画像にデコードする方法
次に、受信したBase64文字列を元の画像に戻す「デコード」の処理について解説します。
デコードはエンコードの逆手順をたどります。

基本的なデコードの実装
Base64文字列をバイト配列に戻すには、Convert.FromBase64Stringメソッドを使用します。
その後、バイト配列をファイルとして保存することで画像として復元できます。
using System;
using System.IO;
class Program
{
static void Main()
{
// 前述の工程で取得したBase64文字列(例として短いものを想定)
string base64String = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==";
try
{
// 1. Base64文字列をバイト配列にデコード
byte[] imageBytes = Convert.FromBase64String(base64String);
// 2. バイト配列を画像ファイルとして保存
string outputPath = "decoded_image.png";
File.WriteAllBytes(outputPath, imageBytes);
Console.WriteLine($"画像を {outputPath} として保存しました。");
}
catch (FormatException)
{
Console.WriteLine("エラー: Base64文字列の形式が正しくありません。");
}
}
}
画像を decoded_image.png として保存しました。
Data URIスキームへの対応
Web開発においては、Base64文字列の先頭にdata:image/png;base64,のような「接頭辞(プレフィックス)」が付いていることが一般的です。
この文字列が残っていると、Convert.FromBase64Stringは「無効な形式」としてエラー(FormatException)をスローします。
デコード処理を行う前に、この接頭辞を削除する処理を組み込むのが実務上の定石です。
public byte[] ClearBase64Prefix(string base64WithPrefix)
{
if (base64WithPrefix.Contains(","))
{
// カンマより後の文字列を取得する
return Convert.FromBase64String(base64WithPrefix.Split(',')[1]);
}
return Convert.FromBase64String(base64WithPrefix);
}
このように実装しておくことで、Webブラウザから送信されたデータなども柔軟に処理できるようになります。
高度な最適化:Span<T>を利用した高速な変換
.NET Core 2.1以降、および現在の.NET 8/9環境では、メモリ効率を劇的に向上させるSpan<T>やReadOnlySpan<T>を活用した新しいAPIが導入されています。
大量の画像を処理する場合や、高トラフィックなサーバーサイドアプリケーションでは、従来のConvert.ToBase64String(新しい文字列オブジェクトを常に生成する)よりも、バッファを再利用する手法が推奨されます。

System.Buffers.Text.Base64の活用
System.Buffers.Text.Base64クラスを使用すると、UTF-8形式のバイト列間でBase64エンコード・デコードを行うことができます。
これにより、文字列オブジェクトへの変換を介さずに処理を完結させることが可能になります。
using System;
using System.Buffers.Text;
using System.IO;
public void EfficientEncode(string inputPath, string outputPath)
{
byte[] source = File.ReadAllBytes(inputPath);
// Base64に変換した際の必要サイズを計算
int expectedSize = Base64.GetMaxEncodedToUtf8Length(source.Length);
byte[] buffer = new byte[expectedSize];
// Spanを使用して高速にエンコード
if (Base64.EncodeToUtf8(source, buffer, out int bytesConsumed, out int bytesWritten) == OperationStatus.Done)
{
// 結果をファイルに書き出す(この時点ではUTF-8のBase64)
using var fs = File.Create(outputPath);
fs.Write(buffer.AsSpan(0, bytesWritten));
}
}
このアプローチの最大の特徴は、「ヒープメモリの割り当てを最小限に抑えられる」点にあります。
特にクラウド環境のサーバーレス関数(Azure FunctionsやAWS Lambda)など、メモリ制限の厳しい環境では非常に有効なテクニックです。
実践的な注意点とトラブルシューティング
画像をBase64で扱う際には、いくつかの「落とし穴」があります。
これらを事前に把握しておくことで、バグの少ない堅牢なシステムを構築できます。
1. メモリ消費の増大
前述の通り、Base64は元のデータよりもサイズが約1.33倍になります。
例えば、10MBの画像はBase64にすると約13.3MBになります。
これをさらに文字列(C#のStringはUTF-16)としてメモリに保持すると、20MB以上のメモリを占有する可能性があります。
大きな画像ファイルを大量に処理する場合は、ストリーム処理を検討してください。
2. 文字化けとパディング
Base64文字列の末尾には、長さ調整のための「=」(パディング)が付与されることがあります。
このパディングが欠落したり、URLエンコードの影響で「+」が「 」(スペース)に置換されたりすると、デコードに失敗します。
| 現象 | 原因 | 対策 |
|---|---|---|
FormatException | 文字列が途切れている | 文字列の長さを確認する |
| デコード後の画像が壊れている | 特殊文字が置換された | Replace(" ", "+") などの補正を検討 |
| サイズが0バイトになる | 入力文字列が空 | 入力値のバリデーションを徹底する |
3. Web用のURLセーフなBase64
標準のBase64には + や / が含まれますが、これらはURLのクエリパラメータとして使用すると問題を引き起こすことがあります。
その場合は、+ を - に、/ を _ に置換したURL-Safe Base64を使用するのが一般的です。
まとめ
C#で画像をBase64エンコード・デコードする方法は、Convertクラスを利用する基本的なものから、Span<T>を利用した高度な最適化まで多岐にわたります。
基本的な変換であればConvert.ToBase64StringとConvert.FromBase64Stringだけで十分対応可能です。
しかし、パフォーマンスが要求されるWeb APIや、大規模なデータを扱う場合は、メモリ効率を考慮したMemoryStreamの活用や最新のBuffer系APIの検討が欠かせません。
また、Webフロントエンドとの連携時にはData URIスキームのプレフィックス除去という重要なステップがあることも忘れないようにしましょう。
これらの知識を組み合わせることで、画像データの転送を安全かつ効率的に実装できるようになります。
本記事を参考に、プロジェクトに最適な変換手法を選択してみてください。
