网站建设单位,项目网上备案,网站内容运营方案,网络推广发帖网站用于读写BMP文件的golang版源码
源码基于源码分享-golang的二进制文件读写库 https://blog.csdn.net/zhyulo/article/details/128890546
BMP文件格式可参考位图文件解析-位图(bmp)、图标(ico)与光标(cur) https://blog.csdn.net/zhyulo/article/details/85934728
import (binarybufioerrorsfmtos
)var ofb errors.New(out of bound)type BitmapFile struct {Header BitmapFileHeaderInfo BitmapInfoHeaderQuad BitmapQuad info:调色板BitLines BitmapLines info:点阵数据
}func ReadBitmapFile(path string) (*BitmapFile, error) {buf, err : os.ReadFile(path)if err ! nil {return nil, err}var bmp BitmapFileerr binary.Unmarshal(buf, false, bmp)return bmp, err
}func NewBitmapFile(width, height int32, bitCount uint16) *BitmapFile {bmp : BitmapFile{Header: BitmapFileHeader{Type: MagicBmp{B, M}},Info: BitmapInfoHeader{Size: 40,Width: width,Height: height,Planes: 1,BitCount: bitCount,},}if height 0 {height -height}bmp.BitLines make(BitmapLines, height, height)bytePerLine : (int32(bitCount)*width 31) / 32 * 4for i : int32(0); i height; i {bmp.BitLines[i] make(BitmapLine, bytePerLine, bytePerLine)}bmp.Info.SizeImage uint32(bytePerLine * height)if bitCount 16 {bmp.Info.ClrUsed 1 bitCountbmp.Quad make(BitmapQuad, bmp.Info.ClrUsed, bmp.Info.ClrUsed)}bmp.Header.OffBits 14 bmp.Info.Size uint32(len(bmp.Quad))*4bmp.Header.Size bmp.Header.OffBits bmp.Info.SizeImagereturn bmp
}func (v *BitmapFile) SetQuad(f func(index int) RgbQuad) {for i : 0; i len(v.Quad); i {v.Quad[i] f(i)}
}func (v *BitmapFile) ReadLine(y int) ([]int, error) {height : v.Info.Heightif height 0 {height -height}if y 0 || y int(height) {return nil, ofb}val : make([]int, v.Info.Width, v.Info.Height)err : binary.NewDecoder(v.BitLines[y], 0).Decode(val, true, int(v.Info.BitCount))return val, err
}func (v *BitmapFile) WriteLine(y int, val any) error {height : v.Info.Heightif height 0 {height -height}if y 0 || y int(height) {return ofb}w : lineWriter{buf: v.BitLines[y]}enc : binary.NewEncoder(w)defer enc.Write(nil)return enc.Encode(val, true, int(v.Info.BitCount))
}func (v *BitmapFile) Save(path string) error {f, err : os.Create(path)if err ! nil {return err}defer f.Close()buf : bufio.NewWriter(f)defer buf.Flush()enc : binary.NewEncoder(buf)defer enc.Write(nil)return enc.Encode(v, false, 0)
}type BitmapFileHeader struct {Type MagicBmp info:文件标识Size uint32 info:文件大小Reserved1 uint16Reserved2 uint16OffBits uint32 info:点阵数据偏移
}type MagicBmp [2]bytefunc (v *MagicBmp) UnmarshalBinary(dec *binary.Decoder, isBig bool, bit int) error {err : dec.Decode(v[:], isBig, bit)if err ! nil {return err}if string(v[:]) ! BM {return errors.New(file isnt bitmap format)}return nil
}type BitmapInfoHeader BitmapInfo
type BitmapInfo struct {Size uint32 info:信息头大小Width int32 info:宽度(像素)Height int32 info:高度(像素)Planes uint16 info:颜色平面数BitCount uint16 info:比特/像素Compression uint32 info:压缩类型SizeImage uint32 info:点阵数据大小XPelsPerMeter int32 info:水平分辨率(像素/米)YPelsPerMeter int32 info:垂直分辨率(像素/米)ClrUsed uint32 info:调色板颜色数ClrImportant uint32 info:关键颜色数ClrMask ColorMask info:颜色掩码
}func (v *BitmapInfoHeader) UnmarshalBinary(dec *binary.Decoder, isBig bool, bit int) error {dec.SetArg(v)return dec.Decode((*BitmapInfo)(v), isBig, bit)
}func (v *BitmapInfoHeader) MarshalBinary(enc *binary.Encoder, isBig bool, bit int) error {enc.SetArg(v)return enc.Encode((*BitmapInfo)(v), isBig, bit)
}type ColorMask [3]uint32func (v *ColorMask) UnmarshalBinary(dec *binary.Decoder, isBig bool, bit int) error {bmp, ok : dec.Arg().(*BitmapInfoHeader)if !ok || bmp nil {return errors.New(decode arg not set)}if bmp.Size 40 {return nil} else if bmp.Size ! 52 {return fmt.Errorf(unsupport BitmapInfoHeader size: %d, bmp.Size)}return dec.Decode(v[:], isBig, bit)
}func (v *ColorMask) MarshalBinary(enc *binary.Encoder, isBig bool, bit int) error {bmp, ok : enc.Arg().(*BitmapInfoHeader)if !ok || bmp nil {return errors.New(encode arg not set)}if bmp.Size 40 {return nil} else if bmp.Size ! 52 {return fmt.Errorf(unsupport BitmapInfoHeader size: %d, bmp.Size)}return enc.Encode(v[:], isBig, bit)
}type BitmapQuad []RgbQuad
type RgbQuad struct {Blue byteGreen byteRed byteReserved byte
}func (v *BitmapQuad) UnmarshalBinary(dec *binary.Decoder, isBig bool, bit int) error {bmp, ok : dec.Arg().(*BitmapInfoHeader)if !ok || bmp nil {return errors.New(decode arg not set)}if bmp.BitCount 16 {return nil}num : bmp.ClrUsedif num 0 {num 1 bmp.BitCount}*v make(BitmapQuad, num, num)return dec.Decode((*v)[:], isBig, bit)
}type BitmapLines []BitmapLine
type BitmapLine []bytefunc (v *BitmapLines) UnmarshalBinary(dec *binary.Decoder, isBig bool, bit int) error {bmp, ok : dec.Arg().(*BitmapInfoHeader)if !ok || bmp nil {return errors.New(decode arg not set)}bytePerLine : int((int32(bmp.BitCount)*bmp.Width 31) / 32 * 4)lineNum : int(bmp.Height)if lineNum 0 {lineNum -lineNum}*v make([]BitmapLine, lineNum)for i : 0; i lineNum; i {newDec : dec.SubDecoder(bytePerLine)err : newDec.Decode((*v)[i], isBig, bit)if err ! nil {return err}err dec.Seek(newDec.Pos())if err ! nil {return err}}return nil
}type lineWriter struct {buf []byteoft int
}func (w *lineWriter) Write(p []byte) (n int, err error) {n len(p)if w.oftn len(w.buf) {n len(w.buf) - w.ofterr ofb}copy(w.buf[w.oft:], p)w.oft nreturn
}