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.
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!
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):
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.
// 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):
*
* 
*
* ## 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
}