一旦JPEGファイルの全体の構造に立ち戻る。構造のフローチャートはややこしいので一旦飛ばして。Annex E "Encoder and decoder control procedures"のE.2デコードの章を見ていく。
Decode image
Decoder_setupと、SOF(start of frame)マーカーが出てくるまでマーカーを読む部分("interpret markers")があるけど、これはどちらも読むマーカーの種類は同じなのでまとめてしまっても良さそうに見える。Figure B.16と話が違うような気がしないでもないけど一旦まとめてしまおう。階層の定義(DHP)がある時が考慮されてないけど、これも一旦無視する。そうするとコードはこういうことになる。Decoder#Decode
はFigure E.6のDecode_image
、Decoder#decodeMisc
は"interpret markers"に相当する。
Decoder#decodeMisc
とDecoder#decodeFrame
は後で実装する。一旦すべて返却値は無いものとする。
func (d *Decoder) decodeMisc() error { // TODO return nil } func (d *Decoder) decodeFrame() error { // TODO return nil } func (d *Decoder) readSOI() error { m, err := d.readMarker() if err != nil { return err } if m != Marker_SOI { slog.Error("readSOI()", "marker", m) return ErrUnexpectedToken } return nil } func (d *Decoder) Decode() error { if err := d.readSOI(); err != nil { return err } if err := d.decodeMisc(); err != nil { return err } if err := d.decodeFrame(); err != nil { return err } return nil }
Interpret markers
Miscにあたる部分はTable E.1に記載してある。
"merkers"というのはこのなかのいずれかのフィールドのリストらしい。ちなみにフローチャートの"Decoder_setup"の部分で読むテーブルもこの中のDRIやDACらしいので、「まとめてしまっても良さそう」と書いた理由はここにある。ここに挙がっているフィールドは全てマーカーの直後の16ビットでフィールドの長さを示してくれているので、取りあえず中身は読み飛ばしておく。これを繰り返し、Table E.1に記載されていないマーカーがきた場合は読むのをやめる。Markerの方にもそのマーカーがSOFxかどうかを判別するメソッドを足しておく。
import "log/slog" var frameMarkers = []Marker{ Marker_SOF0, Marker_SOF1, Marker_SOF2, Marker_SOF3, Marker_SOF5, Marker_SOF6, Marker_SOF7, Marker_SOF9, Marker_SOF10, Marker_SOF11, Marker_SOF13, Marker_SOF14, Marker_SOF15, } func (m Marker) isFrameMarker() bool { for _, fm := range frameMarkers { if m == fm { return true } } return false } func (d *Decoder) decodeMisc() error { for { m, err := d.readMarker() if err != nil { return err } if m.isFrameMarker() { d.unread() return nil } switch m { case Marker_DQT, Marker_DHT, Marker_DAC, Marker_DRI, Marker_COM, Marker_APP_n: l, err := d.readUint16() if err != nil { return err } slog.Info("other header", "marker", m, "length", l, ) // skip field if _, err := d.readBytes(int(l - 2)); err != nil { slog.Error("skip") return err } default: d.unread() return nil } } }
Decode frame
フレームをデコードする。フローチャートはこう。
これはこのとおりに実装する。Decoder#decodeFrameHeader
とDecoder#decodeScan
の中身は後回し。
func (d *Decoder) decodeFrameHeader() error { // TODO return nil } func (d *Decoder) decodeScan() error { // TODO return nil } func (d *Decoder) readEOI() error { m, err := d.readMarker() if err != nil { return err } if m != Marker_EOI { slog.Error("readEOI()", "marker", m) return ErrUnexpectedMarker } return nil } func (d *Decoder) decodeFrame() error { if err := d.readFrameHeader(); err != nil { return err } for { if err := d.decodeMisc(); err != nil { return err } m, err := d.readMarker() if err != nil { return err } if m != Marker_SOS { return ErrUnexpectedMarker } if err := d.decodeScan(); err != nil { return err } if err := d.readEOI(); err == ErrUnexpectedMarker { d.unread() continue } else if err != nil { return err } return nil } }
ここまでで一旦ストリームの終端まできた。