golang.org/x/image/bmp
| Language | Go |
|---|---|
| License | BSD 3-Clause |
| Repository | github.com/golang/image (mirror of go.googlesource.com/image) |
| Documentation | pkg.go.dev/golang.org/x/image/bmp |
| Depends on | nothing (pure Go) |
| Read / write | yes, uncompressed 1, 2, 4, 8, 24 and 32-bit with 40, 108 or 124-byte headers; no RLE, no 16-bit / yes, 8, 24 and 32-bit |
golang.org/x/image/bmp is part of the x/image module, the Go project’s supplementary image packages. It has the same API as the standard library codecs: Decode, DecodeConfig and Encode, and importing it registers BMP with image.Decode.
The decoder supports the common BMP files: palette images (1 to 8 bits), 24-bit and 32-bit, top-down or bottom-up, with BITMAPINFOHEADER, V4 or V5 headers. It returns bmp.ErrUnsupported for RLE compression, 16-bit pixels, bit fields with non-standard masks and OS/2 headers. The encoder picks the output from the image type: *image.Gray and *image.Paletted give 8-bit palette files, opaque RGBA images give 24-bit, and images with transparency give 32-bit.
Installation#
go get golang.org/x/image/bmp
Basic usage: read and write a BMP#
package main
import (
"fmt"
"image"
"image/draw"
"log"
"os"
"golang.org/x/image/bmp"
)
func main() {
f, err := os.Open("in.bmp")
if err != nil {
log.Fatal(err)
}
defer f.Close()
img, err := bmp.Decode(f)
if err != nil {
log.Fatal(err) // bmp.ErrUnsupported for RLE or 16-bit files
}
b := img.Bounds()
fmt.Printf("%d x %d, %T\n", b.Dx(), b.Dy(), img)
// mirror horizontally
out := image.NewRGBA(b)
draw.Draw(out, b, img, b.Min, draw.Src)
for y := 0; y < b.Dy(); y++ {
for x := 0; x < b.Dx()/2; x++ {
l, r := out.RGBAAt(x, y), out.RGBAAt(b.Dx()-1-x, y)
out.SetRGBA(x, y, r)
out.SetRGBA(b.Dx()-1-x, y, l)
}
}
w, err := os.Create("out.bmp")
if err != nil {
log.Fatal(err)
}
defer w.Close()
if err := bmp.Encode(w, out); err != nil {
log.Fatal(err)
}
}
How to get BMP width and height without decoding#
f, err := os.Open("in.bmp")
if err != nil {
log.Fatal(err)
}
defer f.Close()
cfg, err := bmp.DecodeConfig(f)
if err != nil {
log.Fatal(err)
}
fmt.Println(cfg.Width, "x", cfg.Height)
How to convert BMP to PNG#
import (
"image/png"
"os"
"golang.org/x/image/bmp"
)
func bmpToPNG(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
img, err := bmp.Decode(in)
if err != nil {
return err
}
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
return png.Encode(out, img)
}
How to write an 8-bit grayscale BMP#
An *image.Gray is written as an 8-bit BMP with a 256-entry gray palette, a third of the size of a 24-bit file:
gray := image.NewGray(image.Rect(0, 0, 256, 64))
for y := 0; y < 64; y++ {
for x := 0; x < 256; x++ {
gray.SetGray(x, y, color.Gray{Y: uint8(x)})
}
}
err := bmp.Encode(w, gray)
How to open BMP, PNG or JPEG with one function#
import (
"image"
_ "image/jpeg"
_ "image/png"
_ "golang.org/x/image/bmp"
)
img, format, err := image.Decode(f) // format is "bmp", "png" or "jpeg"
Tips#
- To read RLE or 16-bit BMP files, convert them first (e.g. with ImageMagick) or use a cgo binding of a C library.
- The encoder always writes bottom-up rows and a 40-byte header.
x/imagealso hastiff,webp(decode only) anddrawwith high-quality scalers (draw.CatmullRom.Scale).