Google Apps Script (GAS) で SVG を PNG/JPG に変換する方法

GASで動的なグラフや地図をSVGとして生成したものの、それを画像として保存したり共有したりする方法が見つからず、困ったことはありませんか?

GASはGoogleのサーバー上で動作する「ヘッドレス」な環境であるため、ベクトルデータをラスタライズ(画像化)するためのレンダリングエンジンを標準で持っていません。しかし、「ユーザーのブラウザをレンダリングエンジンとして借りる」というアプローチでこの問題を解決できます。

この方法を使えば、スプレッドシート等のデータからSVGを自在に生成・加工し、PNG形式に変換して保存できます。

CloudConvertのような外部サービスに頼ることなく、Googleスライドへの画像挿入を自動化できるのが最大の強みです。大量に使用しても追加コストはかかりませんし、何より機密データを外部のサーバーに送る必要がないため、プライバシーやセキュリティの観点からも安全です。

仕組み

1. GAS(サーバー側): SVG文字列を生成・編集する。

2. HTML(クライアント側): HtmlService でダイアログを開き、ブラウザの Canvas API を使ってSVGを描画する。

3. Canvas(クライアント側): 描画内容を Base64 形式のPNGデータに変換する。

4. GAS(サーバー側): 送り返されたデータをデコードし、Googleドライブに保存する。

実装方法

1. Code.gs (サーバーサイド)

データフローとファイルの保存を行います。

/**
* Main function to trigger the conversion
*/
function startConversion() {
const svgString = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><circle cx="100" cy="100" r="80" fill="red" /></svg>';
const fileName = "converted_image.png";

const template = HtmlService.createTemplateFromFile('converter');
template.svgData = svgString;
template.fileName = fileName;

const html = template.evaluate().setWidth(400).setHeight(300);
SpreadsheetApp.getUi().showModalDialog(html, 'Converting SVG to PNG...');
}

/**
* Saves the Base64 data received from the client
*/
function saveImage(base64Data, fileName) {
const decoded = Utilities.base64Decode(base64Data.split(',')[1]);
const blob = Utilities.newBlob(decoded, 'image/png', fileName);
DriveApp.createFile(blob);
return "Success";
}

2. converter.html (クライアントサイド)

同じプロジェクト内にこのファイルを作成してください。描画エンジンとして機能します。

<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" style="display:none;"></canvas>
<script>
window.onload = function() {
// Data passed from GAS
const svgString = `<?!= svgData ?>`;
const fileName = `<?!= fileName ?>`;

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();

// Important: Ensure the SVG has the correct namespace
let blob = new Blob([svgString], {type: 'image/svg+xml;charset=utf-8'});
let url = URL.createObjectURL(blob);

img.onload = function() {
canvas.width = img.width || 1200; // Set high res
canvas.height = img.height || 1200;
ctx.fillStyle = "white"; // Optional: background color
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);

const pngData = canvas.toDataURL('image/png');
google.script.run
.withSuccessHandler(() => google.script.host.close())
.saveImage(pngData, fileName);
};
img.src = url;
};
</script>
</body>
</html>

実装のポイントと注意点

1. 名前空間 (xmlns) の付与

SVGタグには必ず xmlns=”http://www.w3.org/2000/svg” が含まれている必要があります。これが欠けていると、ブラウザはSVGを「画像」として認識できず、変換に失敗します。

2. フォントの読み込み待機

Google Fontsなどを使用している場合、Canvasに描画する瞬間にフォントの読み込みが完了していないと、デフォルトフォントで書き出されてしまいます。document.fonts.ready などを利用して、フォントが準備できてから描画を開始するのがコツです。

3. 日本語文字化け対策

SVG内に日本語が含まれる場合、単純な文字列操作だとエンコードエラーが起きることがあります。クライアント側でBase64化する際は、UTF-8に対応したエンコード処理を挟むのが安全です。

まとめ

外部の有料変換APIを使わなくても、GASの HtmlService とブラウザの標準機能(Canvas API)を組み合わせるだけで、高精度な画像変換が可能です。「サーバーでできないなら、クライアントにやらせる」という発想が、GAS開発の幅を大きく広げてくれます。