.bmp file format: Go parsing library

The BMP file format, also known as bitmap image file or device independent bitmap (DIB) file format or simply a bitmap, is a raster graphics image file format used to store bitmap digital images, independently of the display device (such as a graphics adapter), especially on Microsoft Windows and OS/2 operating systems.

Samples

Great collection of various BMP sample files: BMP Suite Image List (by Jason Summers)

If only there was such a comprehensive sample suite for every file format! It's like a dream for every developer of any binary file format parser. It contains a lot of different types and variations of BMP files, even the tricky ones, where it's not clear from the specification how to deal with them (marked there as "questionable").

If you make a program which will be able to read all the "good" and "questionable" BMP files and won't crash on the "bad" ones, it will definitely have one of the most extensive support of BMP files in the universe!

BITMAPV2INFOHEADER and BITMAPV3INFOHEADER

A beneficial discussion on Adobe forum (archived): Invalid BMP Format with Alpha channel

In 2010, someone noticed that Photoshop generated BMP with an odd type of header. There wasn't any documentation available for this header at the time (and still isn't). However, Chris Cox (former Adobe employee) claimed that they hadn't invented any type of proprietary header and everything they were writing was taken directly from the Microsoft documentation.

It showed up that the unknown header was called BITMAPV3INFOHEADER. Although Microsoft has apparently requested and verified the use of the header, the documentation on MSDN has probably got lost and they have probably forgotten about this type of header.

This is the only source I could find about these structures, so we could't rely on it so much, but I think supporting them as a read-only format won't harm anything. Due to the fact that it isn't documented anywhere else, most applications don't support it.

All Windows headers at once (including mentioned BITMAPV2INFOHEADER and BITMAPV3INFOHEADER):

Bitmap headers overview

Specs

This page hosts a formal specification of .bmp file format using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Go source code to parse .bmp file format

bmp.go

// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.

import (
	"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
	"bytes"
	"io"
	"golang.org/x/text/encoding/charmap"
)


/**
 * The **BMP file format**, also known as **bitmap image file** or **device independent
 * bitmap (DIB) file format** or simply a **bitmap**, is a raster graphics image file
 * format used to store bitmap digital images, independently of the display
 * device (such as a graphics adapter), especially on Microsoft Windows
 * and OS/2 operating systems.
 * 
 * ## Samples
 * 
 * Great collection of various BMP sample files:
 * [**BMP Suite Image List**](
 *   http://entropymine.com/jason/bmpsuite/bmpsuite/html/bmpsuite.html
 * ) (by Jason Summers)
 * 
 * If only there was such a comprehensive sample suite for every file format! It's like
 * a dream for every developer of any binary file format parser. It contains a lot of
 * different types and variations of BMP files, even the tricky ones, where it's not clear
 * from the specification how to deal with them (marked there as "**q**uestionable").
 * 
 * If you make a program which will be able to read all the "**g**ood" and "**q**uestionable"
 * BMP files and won't crash on the "**b**ad" ones, it will definitely have one of the most
 * extensive support of BMP files in the universe!
 * 
 * ## BITMAPV2INFOHEADER and BITMAPV3INFOHEADER
 * 
 * A beneficial discussion on Adobe forum (archived):
 * [**Invalid BMP Format with Alpha channel**](
 *   https://web.archive.org/web/20150127132443/https://forums.adobe.com/message/3272950
 * )
 * 
 * In 2010, someone noticed that Photoshop generated BMP with an odd type of header. There wasn't
 * any documentation available for this header at the time (and still isn't).
 * However, Chris Cox (former Adobe employee) claimed that they hadn't invented any type
 * of proprietary header and everything they were writing was taken directly
 * from the Microsoft documentation.
 * 
 * It showed up that the unknown header was called BITMAPV3INFOHEADER.
 * Although Microsoft has apparently requested and verified the use of the header,
 * the documentation on MSDN has probably got lost and they have probably
 * forgotten about this type of header.
 * 
 * This is the only source I could find about these structures, so we could't rely
 * on it so much, but I think supporting them as a read-only format won't harm anything.
 * Due to the fact that it isn't documented anywhere else, most applications don't support it.
 * 
 * All Windows headers at once (including mentioned BITMAPV2INFOHEADER and BITMAPV3INFOHEADER):
 * 
 * ![Bitmap headers overview](
 *   https://web.archive.org/web/20190527043845/https://forums.adobe.com/servlet/JiveServlet/showImage/2-3273299-47801/BMP_Headers.png
 * )
 * 
 * ## Specs
 *  * [Bitmap Storage (Windows Dev Center)](
 *      https://learn.microsoft.com/en-us/windows/win32/gdi/bitmap-storage
 *    )
 *     * BITMAPFILEHEADER
 *     * BITMAPINFOHEADER
 *     * BITMAPV4HEADER
 *     * BITMAPV5HEADER
 *  * [OS/2 Bitmap File Format](
 *       https://www.fileformat.info/format/os2bmp/egff.htm
 *    )
 *     * BITMAPFILEHEADER (OS2BMPFILEHEADER)
 *     * BITMAPCOREHEADER (OS21XBITMAPHEADER)
 *     * OS22XBITMAPHEADER
 *  * [Microsoft Windows Bitmap](
 *       http://netghost.narod.ru/gff/graphics/summary/micbmp.htm
 *    )
 *     * BITMAPFILEHEADER (WINBMPFILEHEADER)
 *     * BITMAPCOREHEADER (WIN2XBITMAPHEADER)
 *     * BITMAPINFOHEADER (WINNTBITMAPHEADER)
 *     * BITMAPV4HEADER (WIN4XBITMAPHEADER)
 */

type Bmp_ColorSpace int
const (
	Bmp_ColorSpace__CalibratedRgb Bmp_ColorSpace = 0
	Bmp_ColorSpace__ProfileLinked Bmp_ColorSpace = 1279872587
	Bmp_ColorSpace__ProfileEmbedded Bmp_ColorSpace = 1296188740
	Bmp_ColorSpace__Windows Bmp_ColorSpace = 1466527264
	Bmp_ColorSpace__SRgb Bmp_ColorSpace = 1934772034
)
var values_Bmp_ColorSpace = map[Bmp_ColorSpace]struct{}{0: {}, 1279872587: {}, 1296188740: {}, 1466527264: {}, 1934772034: {}}
func (v Bmp_ColorSpace) isDefined() bool {
	_, ok := values_Bmp_ColorSpace[v]
	return ok
}

type Bmp_Compressions int
const (
	Bmp_Compressions__Rgb Bmp_Compressions = 0
	Bmp_Compressions__Rle8 Bmp_Compressions = 1
	Bmp_Compressions__Rle4 Bmp_Compressions = 2
	Bmp_Compressions__Bitfields Bmp_Compressions = 3
	Bmp_Compressions__Jpeg Bmp_Compressions = 4
	Bmp_Compressions__Png Bmp_Compressions = 5
	Bmp_Compressions__AlphaBitfields Bmp_Compressions = 6
)
var values_Bmp_Compressions = map[Bmp_Compressions]struct{}{0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}}
func (v Bmp_Compressions) isDefined() bool {
	_, ok := values_Bmp_Compressions[v]
	return ok
}

type Bmp_HeaderType int
const (
	Bmp_HeaderType__BitmapCoreHeader Bmp_HeaderType = 12
	Bmp_HeaderType__BitmapInfoHeader Bmp_HeaderType = 40
	Bmp_HeaderType__BitmapV2InfoHeader Bmp_HeaderType = 52
	Bmp_HeaderType__BitmapV3InfoHeader Bmp_HeaderType = 56
	Bmp_HeaderType__Os22xBitmapHeader Bmp_HeaderType = 64
	Bmp_HeaderType__BitmapV4Header Bmp_HeaderType = 108
	Bmp_HeaderType__BitmapV5Header Bmp_HeaderType = 124
)
var values_Bmp_HeaderType = map[Bmp_HeaderType]struct{}{12: {}, 40: {}, 52: {}, 56: {}, 64: {}, 108: {}, 124: {}}
func (v Bmp_HeaderType) isDefined() bool {
	_, ok := values_Bmp_HeaderType[v]
	return ok
}

type Bmp_Intent int
const (
	Bmp_Intent__Business Bmp_Intent = 1
	Bmp_Intent__Graphics Bmp_Intent = 2
	Bmp_Intent__Images Bmp_Intent = 4
	Bmp_Intent__AbsColorimetric Bmp_Intent = 8
)
var values_Bmp_Intent = map[Bmp_Intent]struct{}{1: {}, 2: {}, 4: {}, 8: {}}
func (v Bmp_Intent) isDefined() bool {
	_, ok := values_Bmp_Intent[v]
	return ok
}

type Bmp_Os2Compressions int
const (
	Bmp_Os2Compressions__Rgb Bmp_Os2Compressions = 0
	Bmp_Os2Compressions__Rle8 Bmp_Os2Compressions = 1
	Bmp_Os2Compressions__Rle4 Bmp_Os2Compressions = 2
	Bmp_Os2Compressions__Huffman1d Bmp_Os2Compressions = 3
	Bmp_Os2Compressions__Rle24 Bmp_Os2Compressions = 4
)
var values_Bmp_Os2Compressions = map[Bmp_Os2Compressions]struct{}{0: {}, 1: {}, 2: {}, 3: {}, 4: {}}
func (v Bmp_Os2Compressions) isDefined() bool {
	_, ok := values_Bmp_Os2Compressions[v]
	return ok
}

type Bmp_Os2Rendering int
const (
	Bmp_Os2Rendering__NoHalftoning Bmp_Os2Rendering = 0
	Bmp_Os2Rendering__ErrorDiffusion Bmp_Os2Rendering = 1
	Bmp_Os2Rendering__Panda Bmp_Os2Rendering = 2
	Bmp_Os2Rendering__SuperCircle Bmp_Os2Rendering = 3
)
var values_Bmp_Os2Rendering = map[Bmp_Os2Rendering]struct{}{0: {}, 1: {}, 2: {}, 3: {}}
func (v Bmp_Os2Rendering) isDefined() bool {
	_, ok := values_Bmp_Os2Rendering[v]
	return ok
}
type Bmp struct {
	FileHdr *Bmp_FileHeader
	DibInfo *Bmp_BitmapInfo
	Bitmap *Bmp_Bitmap
	_io *kaitai.Stream
	_root *Bmp
	_parent kaitai.Struct
	_raw_DibInfo []byte
	_raw_Bitmap []byte
}
func NewBmp() *Bmp {
	return &Bmp{
	}
}

func (this Bmp) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp) Read(io *kaitai.Stream, parent kaitai.Struct, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp1 := NewBmp_FileHeader()
	err = tmp1.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.FileHdr = tmp1
	tmp2, err := this._io.ReadBytes(int(this.FileHdr.OfsBitmap - 14))
	if err != nil {
		return err
	}
	tmp2 = tmp2
	this._raw_DibInfo = tmp2
	_io__raw_DibInfo := kaitai.NewStream(bytes.NewReader(this._raw_DibInfo))
	tmp3 := NewBmp_BitmapInfo()
	err = tmp3.Read(_io__raw_DibInfo, this, this._root)
	if err != nil {
		return err
	}
	this.DibInfo = tmp3
	tmp4, err := this._io.ReadBytesFull()
	if err != nil {
		return err
	}
	tmp4 = tmp4
	this._raw_Bitmap = tmp4
	_io__raw_Bitmap := kaitai.NewStream(bytes.NewReader(this._raw_Bitmap))
	tmp5 := NewBmp_Bitmap()
	err = tmp5.Read(_io__raw_Bitmap, this, this._root)
	if err != nil {
		return err
	}
	this.Bitmap = tmp5
	return err
}

/**
 * Replace with an opaque type if you care about the pixels. You can look at
 * an example of a JavaScript implementation:
 * <https://github.com/generalmimon/bmptool/blob/master/src/Bitmap.js>
 * 
 * There is a proposal for adding bitmap data type to Kaitai Struct:
 * <https://github.com/kaitai-io/kaitai_struct/issues/188>
 */
type Bmp_Bitmap struct {
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp
}
func NewBmp_Bitmap() *Bmp_Bitmap {
	return &Bmp_Bitmap{
	}
}

func (this Bmp_Bitmap) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_Bitmap) Read(io *kaitai.Stream, parent *Bmp, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	return err
}

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapcoreheader">Source</a>
 * @see <a href="https://www.fileformat.info/format/os2bmp/egff.htm#OS2BMP-DMYID.3.1">Source</a>
 */
type Bmp_BitmapHeader struct {
	ImageWidth uint32
	ImageHeightRaw int32
	NumPlanes uint16
	BitsPerPixel uint16
	BitmapInfoExt *Bmp_BitmapInfoExtension
	ColorMask *Bmp_ColorMask
	Os22xBitmapExt *Bmp_Os22xBitmapExtension
	BitmapV4Ext *Bmp_BitmapV4Extension
	BitmapV5Ext *Bmp_BitmapV5Extension
	LenHeader uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapInfo
	_f_bottomUp bool
	bottomUp bool
	_f_extendsBitmapInfo bool
	extendsBitmapInfo bool
	_f_extendsBitmapV4 bool
	extendsBitmapV4 bool
	_f_extendsBitmapV5 bool
	extendsBitmapV5 bool
	_f_extendsOs22xBitmap bool
	extendsOs22xBitmap bool
	_f_imageHeight bool
	imageHeight int
	_f_isColorMaskHere bool
	isColorMaskHere bool
	_f_isCoreHeader bool
	isCoreHeader bool
	_f_usesFixedPalette bool
	usesFixedPalette bool
}
func NewBmp_BitmapHeader(lenHeader uint32) *Bmp_BitmapHeader {
	return &Bmp_BitmapHeader{
		LenHeader: lenHeader,
	}
}

func (this Bmp_BitmapHeader) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_BitmapHeader) Read(io *kaitai.Stream, parent *Bmp_BitmapInfo, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp6, err := this.IsCoreHeader()
	if err != nil {
		return err
	}
	switch (tmp6) {
	case false:
		tmp7, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.ImageWidth = uint32(tmp7)
	case true:
		tmp8, err := this._io.ReadU2le()
		if err != nil {
			return err
		}
		this.ImageWidth = uint32(tmp8)
	}
	tmp9, err := this.IsCoreHeader()
	if err != nil {
		return err
	}
	switch (tmp9) {
	case false:
		tmp10, err := this._io.ReadS4le()
		if err != nil {
			return err
		}
		this.ImageHeightRaw = int32(tmp10)
	case true:
		tmp11, err := this._io.ReadS2le()
		if err != nil {
			return err
		}
		this.ImageHeightRaw = int32(tmp11)
	}
	tmp12, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.NumPlanes = uint16(tmp12)
	tmp13, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.BitsPerPixel = uint16(tmp13)
	tmp14, err := this.ExtendsBitmapInfo()
	if err != nil {
		return err
	}
	if (tmp14) {
		tmp15 := NewBmp_BitmapInfoExtension()
		err = tmp15.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.BitmapInfoExt = tmp15
	}
	tmp16, err := this.IsColorMaskHere()
	if err != nil {
		return err
	}
	if (tmp16) {
		tmp17 := NewBmp_ColorMask(this.LenHeader != Bmp_HeaderType__BitmapV2InfoHeader)
		err = tmp17.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.ColorMask = tmp17
	}
	tmp18, err := this.ExtendsOs22xBitmap()
	if err != nil {
		return err
	}
	if (tmp18) {
		tmp19 := NewBmp_Os22xBitmapExtension()
		err = tmp19.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Os22xBitmapExt = tmp19
	}
	tmp20, err := this.ExtendsBitmapV4()
	if err != nil {
		return err
	}
	if (tmp20) {
		tmp21 := NewBmp_BitmapV4Extension()
		err = tmp21.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.BitmapV4Ext = tmp21
	}
	tmp22, err := this.ExtendsBitmapV5()
	if err != nil {
		return err
	}
	if (tmp22) {
		tmp23 := NewBmp_BitmapV5Extension()
		err = tmp23.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.BitmapV5Ext = tmp23
	}
	return err
}
func (this *Bmp_BitmapHeader) BottomUp() (v bool, err error) {
	if (this._f_bottomUp) {
		return this.bottomUp, nil
	}
	this._f_bottomUp = true
	this.bottomUp = bool(this.ImageHeightRaw > 0)
	return this.bottomUp, nil
}
func (this *Bmp_BitmapHeader) ExtendsBitmapInfo() (v bool, err error) {
	if (this._f_extendsBitmapInfo) {
		return this.extendsBitmapInfo, nil
	}
	this._f_extendsBitmapInfo = true
	this.extendsBitmapInfo = bool(this.LenHeader >= Bmp_HeaderType__BitmapInfoHeader)
	return this.extendsBitmapInfo, nil
}
func (this *Bmp_BitmapHeader) ExtendsBitmapV4() (v bool, err error) {
	if (this._f_extendsBitmapV4) {
		return this.extendsBitmapV4, nil
	}
	this._f_extendsBitmapV4 = true
	this.extendsBitmapV4 = bool(this.LenHeader >= Bmp_HeaderType__BitmapV4Header)
	return this.extendsBitmapV4, nil
}
func (this *Bmp_BitmapHeader) ExtendsBitmapV5() (v bool, err error) {
	if (this._f_extendsBitmapV5) {
		return this.extendsBitmapV5, nil
	}
	this._f_extendsBitmapV5 = true
	this.extendsBitmapV5 = bool(this.LenHeader >= Bmp_HeaderType__BitmapV5Header)
	return this.extendsBitmapV5, nil
}
func (this *Bmp_BitmapHeader) ExtendsOs22xBitmap() (v bool, err error) {
	if (this._f_extendsOs22xBitmap) {
		return this.extendsOs22xBitmap, nil
	}
	this._f_extendsOs22xBitmap = true
	this.extendsOs22xBitmap = bool(this.LenHeader == Bmp_HeaderType__Os22xBitmapHeader)
	return this.extendsOs22xBitmap, nil
}
func (this *Bmp_BitmapHeader) ImageHeight() (v int, err error) {
	if (this._f_imageHeight) {
		return this.imageHeight, nil
	}
	this._f_imageHeight = true
	var tmp24 int;
	if (this.ImageHeightRaw < 0) {
		tmp24 = -(this.ImageHeightRaw)
	} else {
		tmp24 = this.ImageHeightRaw
	}
	this.imageHeight = int(tmp24)
	return this.imageHeight, nil
}
func (this *Bmp_BitmapHeader) IsColorMaskHere() (v bool, err error) {
	if (this._f_isColorMaskHere) {
		return this.isColorMaskHere, nil
	}
	this._f_isColorMaskHere = true
	tmp25, err := this.ExtendsBitmapV4()
	if err != nil {
		return false, err
	}
	this.isColorMaskHere = bool( ((this.LenHeader == Bmp_HeaderType__BitmapV2InfoHeader) || (this.LenHeader == Bmp_HeaderType__BitmapV3InfoHeader) || (tmp25)) )
	return this.isColorMaskHere, nil
}
func (this *Bmp_BitmapHeader) IsCoreHeader() (v bool, err error) {
	if (this._f_isCoreHeader) {
		return this.isCoreHeader, nil
	}
	this._f_isCoreHeader = true
	this.isCoreHeader = bool(this.LenHeader == Bmp_HeaderType__BitmapCoreHeader)
	return this.isCoreHeader, nil
}
func (this *Bmp_BitmapHeader) UsesFixedPalette() (v bool, err error) {
	if (this._f_usesFixedPalette) {
		return this.usesFixedPalette, nil
	}
	this._f_usesFixedPalette = true
	tmp26, err := this.ExtendsBitmapInfo()
	if err != nil {
		return false, err
	}
	tmp27, err := this.ExtendsOs22xBitmap()
	if err != nil {
		return false, err
	}
	this.usesFixedPalette = bool( ((!( ((this.BitsPerPixel == 16) || (this.BitsPerPixel == 24) || (this.BitsPerPixel == 32)) )) && (!( ((tmp26) && (!(tmp27)) && ( ((this.BitmapInfoExt.Compression == Bmp_Compressions__Jpeg) || (this.BitmapInfoExt.Compression == Bmp_Compressions__Png)) )) ))) )
	return this.usesFixedPalette, nil
}

/**
 * Image width, px
 */

/**
 * Image height, px (positive => bottom-up image, negative => top-down image)
 */

/**
 * Number of planes for target device, must be 1
 */

/**
 * Number of bits per pixel that image buffer uses (1, 4, 8, 16, 24 or 32)
 */

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfo">Source</a>
 */
type Bmp_BitmapInfo struct {
	LenHeader uint32
	Header *Bmp_BitmapHeader
	ColorMask *Bmp_ColorMask
	ColorTable *Bmp_ColorTable
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp
	_raw_Header []byte
	_raw_ColorTable []byte
	_f_colorMaskAlpha bool
	colorMaskAlpha uint32
	_f_colorMaskBlue bool
	colorMaskBlue uint32
	_f_colorMaskGiven bool
	colorMaskGiven *Bmp_ColorMask
	_f_colorMaskGreen bool
	colorMaskGreen int
	_f_colorMaskRed bool
	colorMaskRed int
	_f_isColorMaskGiven bool
	isColorMaskGiven bool
	_f_isColorMaskHere bool
	isColorMaskHere bool
}
func NewBmp_BitmapInfo() *Bmp_BitmapInfo {
	return &Bmp_BitmapInfo{
	}
}

func (this Bmp_BitmapInfo) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_BitmapInfo) Read(io *kaitai.Stream, parent *Bmp, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp28, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenHeader = uint32(tmp28)
	tmp29, err := this._io.ReadBytes(int(this.LenHeader - 4))
	if err != nil {
		return err
	}
	tmp29 = tmp29
	this._raw_Header = tmp29
	_io__raw_Header := kaitai.NewStream(bytes.NewReader(this._raw_Header))
	tmp30 := NewBmp_BitmapHeader(this.LenHeader)
	err = tmp30.Read(_io__raw_Header, this, this._root)
	if err != nil {
		return err
	}
	this.Header = tmp30
	tmp31, err := this.IsColorMaskHere()
	if err != nil {
		return err
	}
	if (tmp31) {
		tmp32 := NewBmp_ColorMask(this.Header.BitmapInfoExt.Compression == Bmp_Compressions__AlphaBitfields)
		err = tmp32.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.ColorMask = tmp32
	}
	tmp33, err := this._io.EOF()
	if err != nil {
		return err
	}
	if (!(tmp33)) {
		tmp34, err := this._io.ReadBytesFull()
		if err != nil {
			return err
		}
		tmp34 = tmp34
		this._raw_ColorTable = tmp34
		_io__raw_ColorTable := kaitai.NewStream(bytes.NewReader(this._raw_ColorTable))
		tmp35, err := this.Header.IsCoreHeader()
		if err != nil {
			return err
		}
		var tmp36 uint32;
		tmp37, err := this.Header.ExtendsBitmapInfo()
		if err != nil {
			return err
		}
		if (tmp37) {
			tmp36 = this.Header.BitmapInfoExt.NumColorsUsed
		} else {
			tmp36 = 0
		}
		tmp38 := NewBmp_ColorTable(!(tmp35), tmp36)
		err = tmp38.Read(_io__raw_ColorTable, this, this._root)
		if err != nil {
			return err
		}
		this.ColorTable = tmp38
	}
	return err
}
func (this *Bmp_BitmapInfo) ColorMaskAlpha() (v uint32, err error) {
	if (this._f_colorMaskAlpha) {
		return this.colorMaskAlpha, nil
	}
	this._f_colorMaskAlpha = true
	var tmp39 uint32;
	tmp40, err := this.IsColorMaskGiven()
	if err != nil {
		return 0, err
	}
	tmp41, err := this.ColorMaskGiven()
	if err != nil {
		return 0, err
	}
	if ( ((tmp40) && (tmp41.HasAlphaMask)) ) {
		tmp42, err := this.ColorMaskGiven()
		if err != nil {
			return 0, err
		}
		tmp39 = tmp42.AlphaMask
	} else {
		tmp39 = 0
	}
	this.colorMaskAlpha = uint32(tmp39)
	return this.colorMaskAlpha, nil
}
func (this *Bmp_BitmapInfo) ColorMaskBlue() (v uint32, err error) {
	if (this._f_colorMaskBlue) {
		return this.colorMaskBlue, nil
	}
	this._f_colorMaskBlue = true
	var tmp43 uint32;
	tmp44, err := this.IsColorMaskGiven()
	if err != nil {
		return 0, err
	}
	if (tmp44) {
		tmp45, err := this.ColorMaskGiven()
		if err != nil {
			return 0, err
		}
		tmp43 = tmp45.BlueMask
	} else {
		var tmp46 int8;
		if (this.Header.BitsPerPixel == 16) {
			tmp46 = 31
		} else {
			var tmp47 uint8;
			if ( ((this.Header.BitsPerPixel == 24) || (this.Header.BitsPerPixel == 32)) ) {
				tmp47 = 255
			} else {
				tmp47 = 0
			}
			tmp46 = tmp47
		}
		tmp43 = tmp46
	}
	this.colorMaskBlue = uint32(tmp43)
	return this.colorMaskBlue, nil
}
func (this *Bmp_BitmapInfo) ColorMaskGiven() (v *Bmp_ColorMask, err error) {
	if (this._f_colorMaskGiven) {
		return this.colorMaskGiven, nil
	}
	this._f_colorMaskGiven = true
	tmp48, err := this.IsColorMaskGiven()
	if err != nil {
		return nil, err
	}
	if (tmp48) {
		var tmp49 *Bmp_ColorMask;
		tmp50, err := this.IsColorMaskHere()
		if err != nil {
			return nil, err
		}
		if (tmp50) {
			tmp49 = this.ColorMask
		} else {
			tmp49 = this.Header.ColorMask
		}
		this.colorMaskGiven = tmp49
	}
	return this.colorMaskGiven, nil
}
func (this *Bmp_BitmapInfo) ColorMaskGreen() (v int, err error) {
	if (this._f_colorMaskGreen) {
		return this.colorMaskGreen, nil
	}
	this._f_colorMaskGreen = true
	var tmp51 uint32;
	tmp52, err := this.IsColorMaskGiven()
	if err != nil {
		return 0, err
	}
	if (tmp52) {
		tmp53, err := this.ColorMaskGiven()
		if err != nil {
			return 0, err
		}
		tmp51 = tmp53.GreenMask
	} else {
		var tmp54 int;
		if (this.Header.BitsPerPixel == 16) {
			tmp54 = 992
		} else {
			var tmp55 int;
			if ( ((this.Header.BitsPerPixel == 24) || (this.Header.BitsPerPixel == 32)) ) {
				tmp55 = 65280
			} else {
				tmp55 = 0
			}
			tmp54 = tmp55
		}
		tmp51 = tmp54
	}
	this.colorMaskGreen = int(tmp51)
	return this.colorMaskGreen, nil
}
func (this *Bmp_BitmapInfo) ColorMaskRed() (v int, err error) {
	if (this._f_colorMaskRed) {
		return this.colorMaskRed, nil
	}
	this._f_colorMaskRed = true
	var tmp56 uint32;
	tmp57, err := this.IsColorMaskGiven()
	if err != nil {
		return 0, err
	}
	if (tmp57) {
		tmp58, err := this.ColorMaskGiven()
		if err != nil {
			return 0, err
		}
		tmp56 = tmp58.RedMask
	} else {
		var tmp59 int;
		if (this.Header.BitsPerPixel == 16) {
			tmp59 = 31744
		} else {
			var tmp60 int;
			if ( ((this.Header.BitsPerPixel == 24) || (this.Header.BitsPerPixel == 32)) ) {
				tmp60 = 16711680
			} else {
				tmp60 = 0
			}
			tmp59 = tmp60
		}
		tmp56 = tmp59
	}
	this.colorMaskRed = int(tmp56)
	return this.colorMaskRed, nil
}
func (this *Bmp_BitmapInfo) IsColorMaskGiven() (v bool, err error) {
	if (this._f_isColorMaskGiven) {
		return this.isColorMaskGiven, nil
	}
	this._f_isColorMaskGiven = true
	tmp61, err := this.Header.ExtendsBitmapInfo()
	if err != nil {
		return false, err
	}
	tmp62, err := this.IsColorMaskHere()
	if err != nil {
		return false, err
	}
	tmp63, err := this.Header.IsColorMaskHere()
	if err != nil {
		return false, err
	}
	this.isColorMaskGiven = bool( ((tmp61) && ( ((this.Header.BitmapInfoExt.Compression == Bmp_Compressions__Bitfields) || (this.Header.BitmapInfoExt.Compression == Bmp_Compressions__AlphaBitfields)) ) && ( ((tmp62) || (tmp63)) )) )
	return this.isColorMaskGiven, nil
}
func (this *Bmp_BitmapInfo) IsColorMaskHere() (v bool, err error) {
	if (this._f_isColorMaskHere) {
		return this.isColorMaskHere, nil
	}
	this._f_isColorMaskHere = true
	tmp64, err := this._io.EOF()
	if err != nil {
		return false, err
	}
	this.isColorMaskHere = bool( ((!(tmp64)) && (this.Header.LenHeader == Bmp_HeaderType__BitmapInfoHeader) && ( ((this.Header.BitmapInfoExt.Compression == Bmp_Compressions__Bitfields) || (this.Header.BitmapInfoExt.Compression == Bmp_Compressions__AlphaBitfields)) )) )
	return this.isColorMaskHere, nil
}

/**
 * Valid only for BITMAPINFOHEADER, in all headers extending it the masks are contained in the header itself.
 */

/**
 * @see <a href="https://learn.microsoft.com/en-us/previous-versions/dd183376(v=vs.85)">Source</a>
 */
type Bmp_BitmapInfoExtension struct {
	Compression Bmp_Compressions
	Os2Compression Bmp_Os2Compressions
	LenImage uint32
	XResolution uint32
	YResolution uint32
	NumColorsUsed uint32
	NumColorsImportant uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapHeader
}
func NewBmp_BitmapInfoExtension() *Bmp_BitmapInfoExtension {
	return &Bmp_BitmapInfoExtension{
	}
}

func (this Bmp_BitmapInfoExtension) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_BitmapInfoExtension) Read(io *kaitai.Stream, parent *Bmp_BitmapHeader, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp65, err := this._parent.ExtendsOs22xBitmap()
	if err != nil {
		return err
	}
	if (!(tmp65)) {
		tmp66, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.Compression = Bmp_Compressions(tmp66)
	}
	tmp67, err := this._parent.ExtendsOs22xBitmap()
	if err != nil {
		return err
	}
	if (tmp67) {
		tmp68, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.Os2Compression = Bmp_Os2Compressions(tmp68)
	}
	tmp69, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenImage = uint32(tmp69)
	tmp70, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.XResolution = uint32(tmp70)
	tmp71, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.YResolution = uint32(tmp71)
	tmp72, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.NumColorsUsed = uint32(tmp72)
	tmp73, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.NumColorsImportant = uint32(tmp73)
	return err
}

/**
 * If biCompression is BI_JPEG or BI_PNG, indicates the size of the JPEG or PNG image buffer.
 * This may be set to zero for BI_RGB bitmaps.
 */

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv4header">Source</a>
 */
type Bmp_BitmapV4Extension struct {
	ColorSpaceType Bmp_ColorSpace
	EndpointRed *Bmp_CieXyz
	EndpointGreen *Bmp_CieXyz
	EndpointBlue *Bmp_CieXyz
	GammaRed *Bmp_FixedPoint16Dot16
	GammaBlue *Bmp_FixedPoint16Dot16
	GammaGreen *Bmp_FixedPoint16Dot16
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapHeader
}
func NewBmp_BitmapV4Extension() *Bmp_BitmapV4Extension {
	return &Bmp_BitmapV4Extension{
	}
}

func (this Bmp_BitmapV4Extension) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_BitmapV4Extension) Read(io *kaitai.Stream, parent *Bmp_BitmapHeader, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp74, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.ColorSpaceType = Bmp_ColorSpace(tmp74)
	tmp75 := NewBmp_CieXyz()
	err = tmp75.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.EndpointRed = tmp75
	tmp76 := NewBmp_CieXyz()
	err = tmp76.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.EndpointGreen = tmp76
	tmp77 := NewBmp_CieXyz()
	err = tmp77.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.EndpointBlue = tmp77
	tmp78 := NewBmp_FixedPoint16Dot16()
	err = tmp78.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.GammaRed = tmp78
	tmp79 := NewBmp_FixedPoint16Dot16()
	err = tmp79.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.GammaBlue = tmp79
	tmp80 := NewBmp_FixedPoint16Dot16()
	err = tmp80.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.GammaGreen = tmp80
	return err
}

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header">Source</a>
 */
type Bmp_BitmapV5Extension struct {
	Intent Bmp_Intent
	OfsProfile uint32
	LenProfile uint32
	Reserved uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapHeader
	_f_hasProfile bool
	hasProfile bool
	_f_profileData bool
	profileData interface{}
}
func NewBmp_BitmapV5Extension() *Bmp_BitmapV5Extension {
	return &Bmp_BitmapV5Extension{
	}
}

func (this Bmp_BitmapV5Extension) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_BitmapV5Extension) Read(io *kaitai.Stream, parent *Bmp_BitmapHeader, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp81, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Intent = Bmp_Intent(tmp81)
	tmp82, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.OfsProfile = uint32(tmp82)
	tmp83, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenProfile = uint32(tmp83)
	tmp84, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Reserved = uint32(tmp84)
	return err
}
func (this *Bmp_BitmapV5Extension) HasProfile() (v bool, err error) {
	if (this._f_hasProfile) {
		return this.hasProfile, nil
	}
	this._f_hasProfile = true
	this.hasProfile = bool( ((this._parent.BitmapV4Ext.ColorSpaceType == Bmp_ColorSpace__ProfileLinked) || (this._parent.BitmapV4Ext.ColorSpaceType == Bmp_ColorSpace__ProfileEmbedded)) )
	return this.hasProfile, nil
}

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/wcs/using-structures-in-wcs-1-0">"If the profile is embedded, profile data is the actual profile, and if it is linked, the profile data is the null-terminated file name of the profile. This cannot be a Unicode string. It must be composed exclusively of characters from the Windows character set (code page 1252)."</a>
 */
func (this *Bmp_BitmapV5Extension) ProfileData() (v interface{}, err error) {
	if (this._f_profileData) {
		return this.profileData, nil
	}
	this._f_profileData = true
	tmp85, err := this.HasProfile()
	if err != nil {
		return nil, err
	}
	if (tmp85) {
		thisIo := this._root._io
		_pos, err := thisIo.Pos()
		if err != nil {
			return nil, err
		}
		_, err = thisIo.Seek(int64(14 + this.OfsProfile), io.SeekStart)
		if err != nil {
			return nil, err
		}
		switch (this._parent.BitmapV4Ext.ColorSpaceType == Bmp_ColorSpace__ProfileLinked) {
		case true:
			tmp86, err := thisIo.ReadBytes(int(this.LenProfile))
			if err != nil {
				return nil, err
			}
			tmp86 = kaitai.BytesTerminate(tmp86, 0, false)
			tmp87, err := kaitai.BytesToStr(tmp86, charmap.Windows1252.NewDecoder())
			if err != nil {
				return nil, err
			}
			this.profileData = tmp87
		default:
			tmp88, err := thisIo.ReadBytes(int(this.LenProfile))
			if err != nil {
				return nil, err
			}
			tmp88 = tmp88
			this._raw_profileData = tmp88
		}
		_, err = thisIo.Seek(_pos, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	return this.profileData, nil
}

/**
 * The offset, in bytes, from the beginning of the BITMAPV5HEADER structure to the start of the profile data.
 */

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-ciexyz">Source</a>
 */
type Bmp_CieXyz struct {
	X *Bmp_FixedPoint2Dot30
	Y *Bmp_FixedPoint2Dot30
	Z *Bmp_FixedPoint2Dot30
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapV4Extension
}
func NewBmp_CieXyz() *Bmp_CieXyz {
	return &Bmp_CieXyz{
	}
}

func (this Bmp_CieXyz) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_CieXyz) Read(io *kaitai.Stream, parent *Bmp_BitmapV4Extension, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp89 := NewBmp_FixedPoint2Dot30()
	err = tmp89.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.X = tmp89
	tmp90 := NewBmp_FixedPoint2Dot30()
	err = tmp90.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Y = tmp90
	tmp91 := NewBmp_FixedPoint2Dot30()
	err = tmp91.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Z = tmp91
	return err
}
type Bmp_ColorMask struct {
	RedMask uint32
	GreenMask uint32
	BlueMask uint32
	AlphaMask uint32
	HasAlphaMask bool
	_io *kaitai.Stream
	_root *Bmp
	_parent kaitai.Struct
}
func NewBmp_ColorMask(hasAlphaMask bool) *Bmp_ColorMask {
	return &Bmp_ColorMask{
		HasAlphaMask: hasAlphaMask,
	}
}

func (this Bmp_ColorMask) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_ColorMask) Read(io *kaitai.Stream, parent kaitai.Struct, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp92, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.RedMask = uint32(tmp92)
	tmp93, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.GreenMask = uint32(tmp93)
	tmp94, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.BlueMask = uint32(tmp94)
	if (this.HasAlphaMask) {
		tmp95, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.AlphaMask = uint32(tmp95)
	}
	return err
}
type Bmp_ColorTable struct {
	Colors []*Bmp_RgbRecord
	HasReservedField bool
	NumColors uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapInfo
	_f_numColorsPresent bool
	numColorsPresent int
}
func NewBmp_ColorTable(hasReservedField bool, numColors uint32) *Bmp_ColorTable {
	return &Bmp_ColorTable{
		HasReservedField: hasReservedField,
		NumColors: numColors,
	}
}

func (this Bmp_ColorTable) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_ColorTable) Read(io *kaitai.Stream, parent *Bmp_BitmapInfo, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	var tmp96 uint32;
	tmp97, err := this.NumColorsPresent()
	if err != nil {
		return err
	}
	if ( ((this.NumColors > 0) && (this.NumColors < tmp97)) ) {
		tmp96 = this.NumColors
	} else {
		tmp98, err := this.NumColorsPresent()
		if err != nil {
			return err
		}
		tmp96 = tmp98
	}
	for i := 0; i < int(tmp96); i++ {
		_ = i
		tmp99 := NewBmp_RgbRecord(this.HasReservedField)
		err = tmp99.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Colors = append(this.Colors, tmp99)
	}
	return err
}
func (this *Bmp_ColorTable) NumColorsPresent() (v int, err error) {
	if (this._f_numColorsPresent) {
		return this.numColorsPresent, nil
	}
	this._f_numColorsPresent = true
	tmp100, err := this._io.Size()
	if err != nil {
		return 0, err
	}
	var tmp101 int8;
	if (this.HasReservedField) {
		tmp101 = 4
	} else {
		tmp101 = 3
	}
	this.numColorsPresent = int(tmp100 / tmp101)
	return this.numColorsPresent, nil
}

/**
 * @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader">Source</a>
 */
type Bmp_FileHeader struct {
	FileType []byte
	LenFile uint32
	Reserved1 uint16
	Reserved2 uint16
	OfsBitmap int32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp
}
func NewBmp_FileHeader() *Bmp_FileHeader {
	return &Bmp_FileHeader{
	}
}

func (this Bmp_FileHeader) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_FileHeader) Read(io *kaitai.Stream, parent *Bmp, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp102, err := this._io.ReadBytes(int(2))
	if err != nil {
		return err
	}
	tmp102 = tmp102
	this.FileType = tmp102
	if !(bytes.Equal(this.FileType, []uint8{66, 77})) {
		return kaitai.NewValidationNotEqualError([]uint8{66, 77}, this.FileType, this._io, "/types/file_header/seq/0")
	}
	tmp103, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenFile = uint32(tmp103)
	tmp104, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Reserved1 = uint16(tmp104)
	tmp105, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Reserved2 = uint16(tmp105)
	tmp106, err := this._io.ReadS4le()
	if err != nil {
		return err
	}
	this.OfsBitmap = int32(tmp106)
	return err
}

/**
 * not reliable, mostly ignored by BMP decoders
 */

/**
 * Offset to actual raw pixel data of the image
 */
type Bmp_FixedPoint16Dot16 struct {
	Raw uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapV4Extension
	_f_value bool
	value float64
}
func NewBmp_FixedPoint16Dot16() *Bmp_FixedPoint16Dot16 {
	return &Bmp_FixedPoint16Dot16{
	}
}

func (this Bmp_FixedPoint16Dot16) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_FixedPoint16Dot16) Read(io *kaitai.Stream, parent *Bmp_BitmapV4Extension, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp107, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Raw = uint32(tmp107)
	return err
}
func (this *Bmp_FixedPoint16Dot16) Value() (v float64, err error) {
	if (this._f_value) {
		return this.value, nil
	}
	this._f_value = true
	this.value = float64((this.Raw + 0.0) / (1 << 16))
	return this.value, nil
}
type Bmp_FixedPoint2Dot30 struct {
	Raw uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_CieXyz
	_f_value bool
	value float64
}
func NewBmp_FixedPoint2Dot30() *Bmp_FixedPoint2Dot30 {
	return &Bmp_FixedPoint2Dot30{
	}
}

func (this Bmp_FixedPoint2Dot30) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_FixedPoint2Dot30) Read(io *kaitai.Stream, parent *Bmp_CieXyz, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp108, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Raw = uint32(tmp108)
	return err
}
func (this *Bmp_FixedPoint2Dot30) Value() (v float64, err error) {
	if (this._f_value) {
		return this.value, nil
	}
	this._f_value = true
	this.value = float64((this.Raw + 0.0) / (1 << 30))
	return this.value, nil
}

/**
 * @see <a href="https://www.fileformat.info/format/os2bmp/egff.htm#OS2BMP-DMYID.3.2">Source</a>
 */
type Bmp_Os22xBitmapExtension struct {
	Units uint16
	Reserved uint16
	Recording uint16
	Rendering Bmp_Os2Rendering
	Size1 uint32
	Size2 uint32
	ColorEncoding uint32
	Identifier uint32
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_BitmapHeader
}
func NewBmp_Os22xBitmapExtension() *Bmp_Os22xBitmapExtension {
	return &Bmp_Os22xBitmapExtension{
	}
}

func (this Bmp_Os22xBitmapExtension) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_Os22xBitmapExtension) Read(io *kaitai.Stream, parent *Bmp_BitmapHeader, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp109, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Units = uint16(tmp109)
	tmp110, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Reserved = uint16(tmp110)
	tmp111, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Recording = uint16(tmp111)
	tmp112, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Rendering = Bmp_Os2Rendering(tmp112)
	tmp113, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Size1 = uint32(tmp113)
	tmp114, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Size2 = uint32(tmp114)
	tmp115, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.ColorEncoding = uint32(tmp115)
	tmp116, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.Identifier = uint32(tmp116)
	return err
}

/**
 * Specifies how the bitmap scan lines are stored.
 * The only valid value for this field is 0, indicating that the bitmap is
 * stored from left to right and from the bottom up.
 */

/**
 * Specifies the halftoning algorithm used on the bitmap data.
 */

/**
 * rendering == os2_rendering::error_diffusion
 *   => error damping as a percentage in the range 0 through 100
 * rendering == os2_rendering::panda or rendering == os2_rendering::super_circle
 *   => X dimension of the pattern used in pixels
 */

/**
 * rendering == os2_rendering::error_diffusion
 *   => not used
 * rendering == os2_rendering::panda or rendering == os2_rendering::super_circle
 *   => Y dimension of the pattern used in pixels
 */

/**
 * Specifies the color model used to describe the bitmap data.
 * The only valid value is 0, indicating the RGB encoding scheme.
 */

/**
 * Application-specific value
 */
type Bmp_RgbRecord struct {
	Blue uint8
	Green uint8
	Red uint8
	Reserved uint8
	HasReservedField bool
	_io *kaitai.Stream
	_root *Bmp
	_parent *Bmp_ColorTable
}
func NewBmp_RgbRecord(hasReservedField bool) *Bmp_RgbRecord {
	return &Bmp_RgbRecord{
		HasReservedField: hasReservedField,
	}
}

func (this Bmp_RgbRecord) IO_() *kaitai.Stream {
	return this._io
}

func (this *Bmp_RgbRecord) Read(io *kaitai.Stream, parent *Bmp_ColorTable, root *Bmp) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp117, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Blue = tmp117
	tmp118, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Green = tmp118
	tmp119, err := this._io.ReadU1()
	if err != nil {
		return err
	}
	this.Red = tmp119
	if (this.HasReservedField) {
		tmp120, err := this._io.ReadU1()
		if err != nil {
			return err
		}
		this.Reserved = tmp120
	}
	return err
}