一旦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
}
}
ここまでで一旦ストリームの終端まできた。