🎨

好きなファイルサイズでダミー画像を作りたい

2023/12/28に公開

前置き

ソフトウェアやサービスのテストでは、特定のファイルサイズのダミー画像を用意しなければならないケースがあります。
検索エンジンで「ダミー画像 ファイルサイズ指定」などと検索すると幾つかの記事がヒットしますが、多くの方法では画像が開けなくなってしまったり、ファイルサイズの上限があったり、メタデータの削除やロスレス圧縮でファイルサイズが戻ってしまったりするなど、問題があります。
今回は、任意のサイズで実際に開くことができロスレス圧縮にも耐える画像を作成するスクリプトを作成します。

作ってみる

1. 画像を作成する

まず、指定されたファイルサイズで画像を作成する関数を作成します。

1. 画像のサイズを計算する

指定されたファイルサイズ(MB)から、どのサイズ(px)の画像を作成すれば良いか計算します。

# メガバイトをバイトに変換
target_size_bytes = target_size_mb * 1024 * 1024
# 1ピクセル3バイトとして、必要なピクセル数を計算
num_pixels = target_size_bytes // 3
# 1辺のピクセル数を計算
dimension = int(np.sqrt(num_pixels))

2. 画像を作成する

NumPyを使用してランダムなピクセル値を持つ画像データを生成、Pillowを使用して画像オブジェクトに変換し、保存します。

# 画像を作成
image = Image.fromarray(np.random.randint(0, 256, (dimension, dimension, 3), dtype=np.uint8))
# 画像を保存
image.save(file_path)

ここまでを関数にまとめると以下のようになります。
保存先のパスとファイルサイズから画像を作成し、正常に完了したら保存先のパスを返す関数です。

def create_large_image(file_path, target_size_mb):
    target_size_bytes = target_size_mb * 1024 * 1024
    num_pixels = target_size_bytes // 3
    dimension = int(np.sqrt(num_pixels))
    image = Image.fromarray(np.random.randint(0, 256, (dimension, dimension, 3), dtype=np.uint8))
    image.save(file_path)
    return file_path

2. 複数枚の画像に対応する

基本的にダミー画像は一度に複数枚(ハッシュ値の異なるものを)使用するため、複数枚の作成に対応する関数を作成します。

def create_multiple_large_images(base_path, target_size_mb, num_images):
    # 保存先のパスを入れておくリスト
    created_image_paths = []
    # 指定された枚数の画像を作成
    for i in range(num_images):
        # ファイル名は連番
        file_path = f"{base_path}{i}.png"
        # 上で作成した関数を呼び出す
        create_large_image(file_path, target_size_mb)
        # 保存先のパスをリストに追加
        created_image_paths.append(file_path)
    # リストを返す
    return created_image_paths

3. コマンドライン引数に対応する

コマンドライン引数からファイルサイズや枚数を指定できるようにします。

# コマンドライン引数をパース
parser = argparse.ArgumentParser(description='Generate large random images.')
parser.add_argument('-b', '--base_path', type=str, required=True, help='Base path for image generation')
parser.add_argument('-s', '--size', type=int, required=True, help='Target size of the images in MB')
parser.add_argument('-n', '--num', type=int, required=True, help='Number of images to generate')
args = parser.parse_args()

# コマンドライン引数から値を取得
base_path = args.base_path
target_size_mb = args.size
num_images = args.num

4. まとめる

作成した関数をまとめると以下のようになります。

import os
import argparse
from PIL import Image
import numpy as np

def create_large_image(file_path, target_size_mb):
    target_size_bytes = target_size_mb * 1024 * 1024
    num_pixels = target_size_bytes // 3
    dimension = int(np.sqrt(num_pixels))
    image = Image.fromarray(np.random.randint(0, 256, (dimension, dimension, 3), dtype=np.uint8))
    image.save(file_path)
    return file_path

def create_multiple_large_images(base_path, target_size_mb, num_images):
    created_image_paths = []
    for i in range(num_images):
        # Generate an image
        file_path = f"{base_path}{i}.png"
        create_large_image(file_path, target_size_mb)
        created_image_paths.append(file_path)
    return created_image_paths

parser = argparse.ArgumentParser(description='Generate large random images.')
parser.add_argument('-b', '--base_path', type=str, required=True, help='Base path for image generation')
parser.add_argument('-s', '--size', type=int, required=True, help='Target size of the images in MB')
parser.add_argument('-n', '--num', type=int, required=True, help='Number of images to generate')
args = parser.parse_args()

base_path = args.base_path
target_size_mb = args.size
num_images = args.num

created_image_paths = create_multiple_large_images(base_path, target_size_mb, num_images)

実行してみる

1. 実行環境

実行には以下の環境が必要です。
一般的に使用されているパッケージのため、多くの場合は既にインストールされているかと思います。
バージョンに依存するような特殊な処理はしていないため、バージョン指定は入れていませんが、実行時にエラーが出た場合はお知らせください。

  • Python3
  • NumPy
  • Pillow

2. 実行

# スクリプトをダウンロード
wget https://raw.githubusercontent.com/Srgr0/test-image-generator/main/generate.py

# オプションの指定について
## -b: 画像の保存先のパス (以下ではカレントディレクトリ=今いる場所)
## -s: 画像のファイルサイズ(MB) (以下では10MB)
## -n: 画像の枚数 (以下では100枚)

# スクリプトを実行
python ./generate.py -b ./ -s 10 -n 100

3. 確認

保存先のディレクトリを開き、ファイルが保存されていることを確認してみてください。
なおファイルサイズについては、実行環境(主にOS)によって多少の差が出ることがあります。

終わりに

今回作成したスクリプトは以下のリポジトリで公開しています。

スクリプトで使用しているNumPyとPillowは、画像処理において非常に強力なパッケージです。
NumPyについては機械学習においても必須のパッケージとなっているため、是非学習してみてください。

質問等は以下のコメント欄、またはリポジトリのIssueまでお願いします。

GitHubで編集を提案

Discussion