テストで使える!複数の画像を一括生成するツール

@ハクト 2025-06-19 15:29:29に投稿

画像の上にテキストを表示し複数の画像を一括生成できるシンプルなツールを作成しました。

最大300枚まで連番画像を生成でき、テスト用途やサンプル画像作成に利用できます。

画像一括生成ツール

ファイル構成

batch-image-generator/
├── index.html              # HTMLマークアップ
├── style.css              # CSSスタイル・レスポンシブデザイン
├── js/
   ├── app.js             # アプリケーション制御
   ├── colorPicker.js     # 色選択・プリセット管理
   ├── canvasRenderer.js  # Canvas描画エンジン
   ├── imageGenerator.js  # 画像生成・バッチ処理
   └── downloadManager.js # ZIP生成・ダウンロード制御
└── README.md              # プロジェクト説明

技術仕様

  • HTML5, CSS3, Vanilla JavaScript

  • HTML5 Canvas API(高品質テキスト描画)

  • JSZip v3.10.1(ZIP圧縮・アーカイブ)

  • Bootstrap 5.3.0(レスポンシブUIフレームワーク)

使い方

基本操作

  • テキスト入力: 画像に描画したいテキストを入力欄に指定

  • 枚数設定: 1枚から最大300枚まで一括生成(連番対応)

  • サイズ調整: 16px~2000pxの範囲で幅・高さを自由設定

  • プリセット選択: ファビコンからフルHDまで13種類のサイズプリセット

  • 色設定: 文字色・背景色をカラーピッカーで調整

  • 色プリセット: 黒白・グレー系・カラー(青・赤・緑)の統一トーン

  • 生成実行: 「画像を生成」ボタンで一括処理開始

  • 個別編集: 生成後に各画像のテキストを個別変更可能

  • ダウンロード: ZIP一括保存または右クリック個別保存

効率的な設定パターン

テスト用途向け

  • サイズ: 512×512px(標準テストサイズ)

  • : 青背景・白文字(高コントラスト)

  • 枚数: 10~50枚(適度なボリューム)

プロトタイプ用

  • サイズ: 300×300px(サムネイル適正)

  • : 白背景・黒文字(印刷対応)

  • 連番: 1から開始の順次生成

実装のポイント解説

1. 段階的生成システム

大量画像生成時のメモリ負荷軽減とブラウザ安定性確保

JavaScript実装:

/**
 * パフォーマンス最適化された段階的生成
 * 20枚超過時は10枚ずつ分割生成でメモリ負荷軽減
 */
async generateImagesProgressively(settings, container) {
    const batchSize = 10;
    const totalBatches = Math.ceil(settings.count / batchSize);
    
    for (let i = 0; i < totalBatches; i++) {
        const start = i * batchSize;
        const end = Math.min(start + batchSize, settings.count);
        
        // バッチ処理実行
        this.generateBatch(settings, container, start, end);
        
        // UI更新のためのマイクロタスク実行
        await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    // 一括ダウンロードボタン有効化
    document.getElementById('downloadAllBtn').disabled = false;
}

/**
 * 単一バッチの画像生成処理
 */
generateBatch(settings, container, start, end) {
    for (let i = start; i < end; i++) {
        const imageNumber = settings.startNumber + i;
        const displayText = `${settings.baseText}${imageNumber}`;
        
        // Canvas要素作成と描画
        const canvas = this.canvasRenderer.createCanvas(
            settings.width, 
            settings.height
        );
        
        this.canvasRenderer.drawText(
            canvas, 
            displayText, 
            settings.fontSize,
            settings.textColor, 
            settings.bgColor
        );
        
        // DOM追加と編集機能設定
        this.addImageToContainer(container, canvas, displayText, i);
    }
}

2. Canvas描画処理

アンチエイリアシング対応のテキスト描画

JavaScript実装:

/**
 * Canvas描画クラス
 * テキスト描画とアンチエイリアシング制御
 */
class CanvasRenderer {
    /**
     * Canvas要素作成
     */
    createCanvas(width, height) {
        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        
        // 高品質描画設定
        const ctx = canvas.getContext('2d');
        ctx.imageSmoothingEnabled = true;
        ctx.textRenderingOptimization = 'optimizeQuality';
        
        return canvas;
    }
    
    /**
     * テキスト描画
     */
    drawText(canvas, text, fontSize, textColor, bgColor) {
        const ctx = canvas.getContext('2d');
        
        // フォント設定
        ctx.font = `${fontSize}px Arial, sans-serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        // 背景描画
        ctx.fillStyle = bgColor;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        // テキスト描画(中央配置)
        ctx.fillStyle = textColor;
        ctx.fillText(text, canvas.width / 2, canvas.height / 2);
    }
}

3. 効率的ZIP生成システム

JSZipライブラリを使用した最適化されたアーカイブ処理

JavaScript実装:

/**
 * ダウンロード管理クラス
 * ZIP生成と一括ダウンロード機能
 */
class DownloadManager {
    /**
     * 全画像のZIP生成とダウンロード
     */
    async downloadAllImages() {
        const images = document.querySelectorAll('.generated-images canvas');
        
        if (images.length === 0) {
            alert('生成された画像がありません。');
            return;
        }
        
        try {
            // ZIP生成開始
            const zip = new JSZip();
            
            // 各画像をZIPに追加
            images.forEach((canvas, index) => {
                const filename = `image_${String(index + 1).padStart(3, '0')}.png`;
                const dataUrl = canvas.toDataURL('image/png');
                const base64Data = dataUrl.split(',')[1];
                
                zip.file(filename, base64Data, { base64: true });
            });
            
            // ZIP生成とダウンロード実行
            const blob = await zip.generateAsync({ 
                type: 'blob',
                compression: 'DEFLATE',
                compressionOptions: { level: 6 }
            });
            
            // ダウンロード処理
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            link.download = `batch_images_${new Date().getTime()}.zip`;
            link.click();
            
            // メモリクリーンアップ
            URL.revokeObjectURL(url);
            
        } catch (error) {
            console.error('ZIP生成エラー:', error);
            alert('ZIP生成中にエラーが発生しました。');
        }
    }
}

4. プリセットシステム

素早い設定切り替えのためのサイズ・色プリセット機能

JavaScript実装:

/**
 * プリセット機能の初期化
 * サイズプリセットと色プリセットの設定
 */
initializePresets() {
    // サイズプリセット処理
    const sizePresetSelect = document.getElementById('sizePresetSelect');
    sizePresetSelect.addEventListener('change', (e) => {
        const preset = e.target.value;
        
        if (preset === 'custom') return;
        
        const [width, height] = preset.split('x').map(Number);
        document.getElementById('widthInput').value = width;
        document.getElementById('heightInput').value = height;
    });
    
    // 色プリセット処理
    const colorPresetSelect = document.getElementById('colorPresetSelect');
    colorPresetSelect.addEventListener('change', (e) => {
        const preset = e.target.value;
        
        if (preset === 'custom') return;
        
        // 統一トーンの色プリセット
        const presets = {
            'black-white': { bg: '#000000', text: '#ffffff' },
            'white-black': { bg: '#ffffff', text: '#000000' },
            'gray-black': { bg: '#f0f0f0', text: '#000000' },
            'dark-gray-white': { bg: '#555555', text: '#ffffff' },
            'blue-white': { bg: '#3e4970', text: '#ffffff' },
            'red-white': { bg: '#703e49', text: '#ffffff' },
            'green-white': { bg: '#3e7049', text: '#ffffff' }
        };
        
        if (presets[preset]) {
            const { bg, text } = presets[preset];
            this.colorPicker.setBackgroundColor(bg);
            this.colorPicker.setTextColor(text);
            this.updateExistingImages();
        }
    });
}

5. UI応答性の確保

/**
 * マイクロタスクによるUI更新確保
 * 大量処理中もブラウザの応答性維持
 */
async generateImagesProgressively(settings, container) {
    for (let i = 0; i < totalBatches; i++) {
        // バッチ処理
        this.generateBatch(settings, container, start, end);
        
        // 重要: UI更新のための待機時間
        await new Promise(resolve => setTimeout(resolve, 100));
    }
}

技術的特徴

  • 最大300枚生成: 段階的処理による大量生成対応

  • 16-2000pxサイズ: フレキシブルなサイズ設定

  • 13種類プリセット: ファビコンからフルHDまで対応

  • 統一トーン色彩: 色プリセット

  • リアルタイム編集: 生成後の個別テキスト変更

  • ZIP一括保存: 効率的なアーカイブダウンロード

  • レスポンシブ対応: モバイルデバイス最適化

まとめ

以前テストで複数の画像を追加し追加し、それぞれの画像が正しくでアップロードされDBに保存されているか、何パターンも確認する必要があったので、その時に作成しました。

テスト用途、サンプル画像作成、プロトタイプ開発など、さまざまなシーンで手軽に活用してみてください。

@ハクト

サービス作り・デザイン好き。70年代生まれのWEBエンジニア。WEBパーツをCSSでカスタマイズしてコピペできるサービスを運営中「Pa-tu」。実装したWEBパーツやツールを利用してWEB情報やライフハックを発信してます。

Twitter