jpgについて その2

前回からの続き

前回は主要アルゴリズムについてのお話でしたので、今回は実際の処理手順について綴っていこうかと思います。


が・・・その前にそもそも画像がどのように表現されているかの前提のお話をしたほうがイメージしやすいかと思いますのでそちらから。

# 画像の表現について

例えばこのような200px × 200pxの青色の画像があったとします。

![スクリーンショット 2018-12-11 6.11.13.png](https://qiita-image-store.s3.amazonaws.com/0/321378/6fe46c3b-c449-0d0b-1168-c5f479aa4746.png)


この画像の要素を分解すると

![スクリーンショット 2018-12-11 6.13.12.png](https://qiita-image-store.s3.amazonaws.com/0/321378/11f3cb7d-8cbd-f224-325c-b3ccf3f5b802.png)

![スクリーンショット 2018-12-11 6.13.26.png](https://qiita-image-store.s3.amazonaws.com/0/321378/6300c11a-1e60-f2c4-5ab4-77fa318bb770.png)

![スクリーンショット 2018-12-11 6.13.40.png](https://qiita-image-store.s3.amazonaws.com/0/321378/e8c1e711-9409-2f5c-412c-9960351310c9.png)


とRGBの3つのレイヤーに分けられます。
この200px × 200pxの青色の画像は

![スクリーンショット 2018-12-11 6.14.02.png](https://qiita-image-store.s3.amazonaws.com/0/321378/39fe8081-ba7e-1c85-00f0-85fac28fac68.png)

200px × 200px のRGBの3枚のレイヤーを重ねることによって表現されていることになります。

RGB値で見た場合、この200px × 200pxの青色の画像の構成要素は 200 × 200 × 3 = 120000個 の RGB値の集合です。
昨今めっきり見なくなったbmpの形式では、生のRGB値をきっかり全部のレイヤー分保持しています。適宜bmpで用意してもらったファイルをバイナリエディタで開いてみると分かりやすいかと思います。
(画像のヘッダー情報+120000個のRGB値の羅列が見て取ることができます。リトルエンディアンの形式で保持されているのと、BGRの順で並んでいるので分かりづらいところですが・・・また、このような保持形式のため、ファイルサイズが120000byte(RGB値1つ=1byte×120000+ファイルヘッダー)の近似値になります。※24ビットビットマップの場合)

この前提の元、jpgの処理手順について述べていきます。

# jpg処理の前提
 * 最小の処理単位は8×8(最小の格納単位は16×16)
 * ↑これがjpgがエッジに弱いことやブロックノイズが発生する要因

# jpgの圧縮処理手順
 * RGB→YCbCr変換
 * 2次元DCT
 * 量子化
 * シリアライズ
 * ハフマンテーブルによる符号化(DC成分/AC成分)

# RGB→YCbCr変換
RGB値を特定の行列をかけて、YCbCrに変換します。

![スクリーンショット 2018-12-11 7.14.48.png](https://qiita-image-store.s3.amazonaws.com/0/321378/e2dd6ce2-5b03-6694-bb56-8101a957a35d.png)

![スクリーンショット 2018-12-11 7.15.28.png](https://qiita-image-store.s3.amazonaws.com/0/321378/f098f16d-c0f6-fb4b-8ed5-737a0dd0aedb.png)


なぜこんなことをするのか？圧縮率が上がるからです。(｀・ω・´)ｼｬｷｰﾝ

# 2次元DCT
 * 2次元平面に対する離散コサイン変換
 * 離散信号を周波数領域に変換する1つの方法
 * Y・Cb・Crの各レイヤーに対して実施
 * 人の目にもよく分かる低周波成分が左上に
 * 人の目には違いがよく分からない高周波成分が右下に

前回も触れましたが一応おさらい

![スクリーンショット 2018-12-11 7.18.52.png](https://qiita-image-store.s3.amazonaws.com/0/321378/3c334cb8-6709-eaed-21fc-4c6ef8dc9482.png)

なぜこんなことをするのか？圧縮率が上がるからです。(｀・ω・´)ｼｬｷｰﾝ

# 量子化
データ圧縮における量子化とは値の精度を落としてより少ない（粗い）区間に分け直すこと(wikipediaより抜粋)を指します。

![スクリーンショット 2018-12-11 7.20.40.png](https://qiita-image-store.s3.amazonaws.com/0/321378/1851ac48-0e9c-4066-7104-dd1452164bf0.png)

また、jpgのヘッダーには以下のような量子化用のテーブルがそれぞれ格納されています。
このデータを用いてデコーダーはデータのデコードを行います。
(jpgの保存時に設定する場合がある「品質」はこの量子化テーブルに対する倍率を表します)

![スクリーンショット 2018-12-11 7.21.10.png](https://qiita-image-store.s3.amazonaws.com/0/321378/58a39ed1-0d21-89ff-aca8-cb4c5e066264.png)

この量子化テーブルについてはほぼ上述のものが適用されています。
実際の画像に対する圧縮処理において、上述のテーブルがほとんどの場合において高い圧縮率を誇ることが経験則的に立証されているからだそうです。

![スクリーンショット 2018-12-11 7.25.54.png](https://qiita-image-store.s3.amazonaws.com/0/321378/ca1d5e3a-6c3c-6062-6fe5-70fd0b8c1b89.png)

![スクリーンショット 2018-12-11 7.26.03.png](https://qiita-image-store.s3.amazonaws.com/0/321378/5832d2ca-22f2-758e-86ef-697708c1536a.png)

なぜこんなことをするのか？圧縮率が上がるからです。(｀・ω・´)ｼｬｷｰﾝ

# シリアライズ
2次元のデータ列に対して処理をしてますので、バイナリとしてデータ格納するために一定のアルゴリズムでシリアライズする必要があります。
ただシリアライズするだけなら前述の処理は必要ありません。
前回の記事で説明した主要アルゴリズムの一つ、ゼロランレングスが最も効果を発揮するようにシリアライズする必要があります。

ここで用いるのがジグザクスキャンです。

![スクリーンショット 2018-12-11 7.31.54.png](https://qiita-image-store.s3.amazonaws.com/0/321378/4ab07a1c-2efe-6fc0-a7bc-1c330560e624.png)

![スクリーンショット 2018-12-11 7.35.52.png](https://qiita-image-store.s3.amazonaws.com/0/321378/0c7aa016-2bf0-1f40-a5b4-b0530c46b146.png)

なぜこんなことをするのか？圧縮率が上がるからです。(｀・ω・´)ｼｬｷｰﾝ

# ハフマンテーブルによる符号化(DC成分/AC成分)
ここからjpgのバイナリの深淵、ハフマンテーブルを用いた符号化について説明していきたいと思います。

といきたいところですが・・・記事の量が多くなってきましたね・・・
今回の分はここまでということで。
ハフマンテーブルによる符号化と実際のファイルへの格納方法についてはまた次回ということで\_(:3」∠)\_
(気が向いたら)つづく