【画像処理】画像ビューア(ペイント・GIMP)でみる画像ファイル形式の違い


画像ビューア(ペイント・GIMP)でみる画像ファイル形式の違い
前回の記事→「[画像処理のための環境構築(Python)](https://qiita.com/spc_ehara/items/c71aed04881d8b0acbc9)」


[そもそも画像とは(JPG,PNG,GIF,BMP,SVG)](https://qiita.com/spc_ehara/private/fe05049f5a6bd67c48f3) で説明したように、各ファイル形式にはメリット・デメリットがあります。
そこで今回は、前回説明した以外の違いを検証するために、ペイントとGIMPを使ってファイル形式ごとの`メモリ使用量`と`読み書き速度`を比較していきます。
使用する画像は、5000×5000、500×500 の単色画像で、ファイル形式は、jpg, png, bmpの3つを使います。

|1.1 入力画像|1.2 入力画像|
|:-:|:-:|
|![](https://user-images.githubusercontent.com/74283288/110294828-b7c8a700-8033-11eb-9dc3-76e714330876.png)5000×5000|![](https://user-images.githubusercontent.com/74283288/110294823-b6977a00-8033-11eb-852e-b41b08d5e280.png) 500×500|


# ファイル形式ごとのメモリ使用量

ここでは、同じ画像サイズでファイル形式の異なる3枚の画像のメモリ使用量を比較検証していきます。
使用するアプリケーションはペイントとGIMPです。
検証方法は各アプリケーション起動後に、jpg, png, bmpの順番に画像を一定間隔で読み込んで、削除するといった手順で行い、その時のメモリ変化量を画像が使用しているメモリ使用量と定義しました。また、メモリ使用量の確認はパフォーマンスモニターを使用しています。


### ペイント

#### 1.1 入力画像(5000×5000)
![](https://user-images.githubusercontent.com/74283288/110294858-beefb500-8033-11eb-8b3b-9984f9ca0303.gif)
ここでは大きくメモリ使用量が上がっている部分で画像が読み込まれています。

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|アプリケーション起動時(KB)|20,324|20,905|20,946|
|読み込み時(KB)|295,837|296,239|296,738|
|正味使用量(KB)|275,513|275,334|275,792|

各ファイル形式の正味使用量を見てみると、大きな偏ったメモリ使用は見られず、どれもほとんど変わらないメモリ使用量と言えます。

#### 1.2 入力画像(500×500)
![](https://user-images.githubusercontent.com/74283288/110294860-bf884b80-8033-11eb-9f8b-76fd291f7a2e.gif)
ここでは大きくメモリ使用量が上がっている部分は、ファイルを開く際にアプリケーションが使っているメモリです。
画像で使用するメモリは最大メモリ使用時より一段下がったところです。また、もう一段下がったところがアプリケーションそのもののメモリ使用量になります。

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|アプリケーション起動時(KB)|19,767|20,594|20,328|
|読み込み時(KB)|22,511|22,724|22,623|
|正味使用量(KB)|2,744|2,130|2,295|

こちらも同様に、各ファイル形式の正味使用量に大きく偏ったメモリ使用は見られず、ほとんど変わらないメモリ使用量と言えます。

### GIMP
アプリケーション間で画像が占有するメモリ量の偏りがあるかを確認するため、GIMPでも同じように検証していきます。

#### 1.1 入力画像(5000×5000)
![](https://user-images.githubusercontent.com/74283288/110294854-be571e80-8033-11eb-825f-1fb0393818d9.gif)
ここでは大きくメモリ使用量が上がっている部分で画像が読み込まれています。

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|アプリケーション起動時(KB)|346,148|346,120|346,963|
|読み込み時(KB)|635,322|636,284|636,162|
|正味使用量(KB)|289,174|290,164|289,199|

各ファイル形式の正味使用量に大きく偏ったメモリ使用は見られず、どれもほとんど変わらないメモリ使用量と言えます。
ただし、ペイント使用時のメモリ使用量と比べてみると、正味使用量は多少多くなる傾向があると言えます。

#### 1.2 入力画像(500×500)
![](https://user-images.githubusercontent.com/74283288/110294859-beefb500-8033-11eb-80d5-6fb7ab6eb758.gif)
ここでは大きくメモリ使用量が上がっている部分で画像が読み込まれています。

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|アプリケーション起動時(KB)|346,763|346,783|347,353|
|読み込み時(KB)|429,416|430,157|430,190|
|正味使用量(KB)|82,653|83,374|82,837|

こちらも同様に、各ファイル形式の正味使用量に大きく偏ったメモリ使用は見られず、どれもほとんど変わらないメモリ使用量と言えます。
しかし、ペイント使用時のメモリ使用量と比べてみると正味使用量が大幅に増えています。これは「1.1 入力画像(5000×5000)」の場合でも同じでしたが、画像の読み込みに付随したGIMP特有の機能が同時に立ち上がっていると考えられます。


上記の検証結果から、アプリケーション間の占有するメモリの量に差はあるものの、同じ画像サイズであればファイル形式によるメモリ使用量の違いはほとんどないことがわかります。ビューアなどで画像を読み込む際に画像はメモリ空間に展開され、どんなファイル形式でもBMPかそれに準ずる形式になります。つまり、画像が占有するメモリ量はファイル形式に関係なく、(ファイルサイズではなく)画像サイズによって決まります。

# ファイル形式ごとの読み書き速度

ここでは、同じ画像サイズでファイル形式の異なる3枚の画像の読み書き速度を比較検証していきます。使用する画像は、実行時間の差が大きく、結果がわかりやすいという点で「1.1 入力画像(5000×5000)」のみを使用します。
使用するアプリケーションはペイントとGIMPです。
検証方法は各アプリケーション起動後に、特定のファイル形式の画像を読み込み、リネームして保存するという手順を10回繰り返し、その合計実行時間を読み書き速度と定義しました。また、ペイントとGIMPの操作と実行時間計測にはpowershellとUIAutomationを使用しています。


### ペイント
#### 1.1 入力画像(5000×5000)

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|合計読み込み時間(msec)|8086.4|4542.6|4592.5|
|合計書き込み時間(msec)|284.6|170.8|0|
|合計実行時間(msec)|8371.0|4713.4|4592.5|

各ファイル形式の合計実行時間を見てみると、jpg, png, bmpの順で時間がかかっているのがわかると思います。特に、jpgは他の2つに比べて顕著に読み込みに時間がかかっています。また、pngとbmpでも合計実行時間に121msecの差があります。

### GIMP
#### 1.1 入力画像(5000×5000)

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|合計読み込み時間(msec)|23435.2|23631.5|23241.8|
|合計書き込み時間(msec)|12237.3|11501.4|11043.3|
|合計実行時間(msec)|35672.5|35132.9|34285.1|

ここでもファイル形式によって合計実行時間に差が出ているのがわかると思います。

### 画像の読み書き速度に影響する要素
ここで、画像の読み書き速度に影響する要素について考えてみます。
今回の検証は、システム構成図１の構成で、シーケンシャルリードが225.885 MB/s、シーケンシャルライトが204.441 MB/sという環境で行いました。

|システム構成図１|
|:-:|
|![](https://user-images.githubusercontent.com/74283288/111102981-b3027680-8590-11eb-9ba7-9648d2f1f93e.png)|

上記の構成において、ファイル形式ごとの読み書き速度に影響するものとしては、ファイルサイズとエンコード・デコードが考えられます。
ファイルサイズが大きいほど、ファイル読み出し、書き込み時に時間がかかります。また、画像が圧縮されていればファイル読み出し、書き込み時にエンコード・デコードが必要となります。この速度が遅いほど、読み込み・書き込みに時間がかかります。

#### 画像ファイルへのアクセス方法
画像の読み書き込みは基本的にシーケンシャルアクセスですが、これを実際に確認するためにプロセスモニターを使用して、検証を行いました。検証は、GIMPから1.2 入力画像(500×500)の読み込みを行い、そのアクセス方法を確認しました。

|Process Monitor Log|
|:-:|
|![](https://user-images.githubusercontent.com/74283288/111257884-486c3c00-865f-11eb-8273-7eb18268b3cf.png)|

1行目のOffset:0から2行目のOffset:122までは画像ファイルのヘッダ部を読み込んでいます。試しにバイナリエディタで同じ画像を読み込んでみると、bfOffBits(ファイル先頭から画像データまでのオフセットを表す)が「0x7A 0x00 0x00 0x00」(リトルエンディアン)で、122byteなのがわかります。
さらに3行目から、「Offset+lengthが次の行のOffsetになる」という規則性で処理が行われていることから、シーケンシャルアクセスで処理が行われていることが確認できます。


そこで、読み込み時間と書き込み時間の構成を以下のような式で表すことができます。
読み込み時間 = (シーケンシャルリードタイム) + (デコード) + (その他・オーバーヘッド)
書き込み時間 = (シーケンシャルライトタイム) + (エンコード) + (その他・オーバーヘッド)


#### ファイル形式ごとの読み書き1回あたりシーケンシャルアクセス時間比較
##### 1.1 入力画像(5000×5000)

||jpg|png|bmp|
|:-:|:-:|:-:|:-:|
|ファイルサイズ(KB)|287|82.7|71,500|
|シーケンシャルリードタイム(msec)|1.2|0.3|316.5|
|シーケンシャルライトタイム(msec)|1.4|0.4|349.7|
|合計シーケンシャルアクセス(msec)|2.6|0.7|666.2|

jpg, pngは全体に対してさほど時間はかかっていませんが、bmpのファイルサイズはほかに比べて圧倒的に大きいため、読み書き込み全体に影響するほどの時間がかかっています。
しかし、最終的な合計実行時間ではbmpが一番早いという結果が出ています。つまり、シーケンシャルアクセスが十分に早ければ、大きいファイルサイズを読み込む時間よりもエンコード・デコードにかかる時間のほうが長くなります。
よって、jpg, pngはシーケンシャルアクセスが短いもののエンコード・デコードに時間がかかり、bmpはエンコード・デコードがないので、シーケンシャルアクセスでかかった時間を取り戻すことができた結果として、合計実行時間ではbmpが一番早いのです。


上記の検証結果から、アプリケーション間の読み書き速度に差はあるものの、bmp, png, jpgの順番で読み書き速度が速いことがわかりました。
bmpは他のファイル形式に比べてシーケンシャルアクセスに時間がかかるもののエンコード・デコードがないので、結果として速度が速くなると言えます。また、シーケンシャルアクセス時間が早いほど、この傾向は顕著に出るでしょう。


# さいごに
今回は、「画像ビューワー(ペイント・GIMP)でみる画像ファイル形式の違い」について解説しました。

それでは引き続きよろしくお願いいたします。

目次は以下の記事からご覧になれます。

https://qiita.com/spc_ehara/items/e425b6dcc0398299c40d#%E7%9B%AE%E6%AC%A1