mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-03-17 20:17:48 +02:00
Add support of 16-bit BMP
This commit is contained in:
parent
df0cc4e19b
commit
d80a203390
@ -1,6 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
## Add
|
||||
- Add support of 16-bit BMP.
|
||||
|
||||
## [3.6.0] - 2022-06-13
|
||||
### Add
|
||||
|
91
vips/bmp.go
91
vips/bmp.go
@ -314,6 +314,52 @@ func (img *Image) decodeBmpRGB(r io.Reader, width, height, bands int, topDown, n
|
||||
return nil
|
||||
}
|
||||
|
||||
// decodeBmpRGB16 reads a 16 bit-per-pixel BMP image from r.
|
||||
// If topDown is false, the image rows will be read bottom-up.
|
||||
func (img *Image) decodeBmpRGB16(r io.Reader, width, height int, topDown, bmp565 bool) error {
|
||||
tmp, imgData, err := prepareBmpCanvas(width, height, 3)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer bmpClearOnPanic(&tmp)
|
||||
|
||||
// Each row is 4-byte aligned.
|
||||
b := make([]byte, (2*width+3)&^3)
|
||||
|
||||
y0, y1, yDelta := height-1, -1, -1
|
||||
if topDown {
|
||||
y0, y1, yDelta = 0, height, +1
|
||||
}
|
||||
|
||||
stride := width * 3
|
||||
|
||||
for y := y0; y != y1; y += yDelta {
|
||||
if _, err = io.ReadFull(r, b); err != nil {
|
||||
C.clear_image(&tmp)
|
||||
return err
|
||||
}
|
||||
|
||||
p := imgData[y*stride : (y+1)*stride]
|
||||
for i, j := 0, 0; i < len(p); i, j = i+3, j+2 {
|
||||
pixel := readUint16(b[j:])
|
||||
|
||||
if bmp565 {
|
||||
p[i+0] = uint8((pixel&0xF800)>>11) << 3
|
||||
p[i+1] = uint8((pixel&0x7E0)>>5) << 2
|
||||
} else {
|
||||
p[i+0] = uint8((pixel&0x7C00)>>10) << 3
|
||||
p[i+1] = uint8((pixel&0x3E0)>>5) << 3
|
||||
}
|
||||
p[i+2] = uint8(pixel&0x1F) << 3
|
||||
}
|
||||
}
|
||||
|
||||
C.swap_and_clear(&img.VipsImage, tmp)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
||||
// We only support those BMP images that are a BITMAPFILEHEADER
|
||||
// immediately followed by a BITMAPINFOHEADER.
|
||||
@ -369,18 +415,41 @@ func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
||||
return errBmpUnsupported
|
||||
}
|
||||
|
||||
// if compression is set to BITFIELDS, but the bitmask is set to the default bitmask
|
||||
// that would be used if compression was set to 0, we can continue as if compression was 0
|
||||
if compression == 3 && infoLen > infoHeaderLen &&
|
||||
readUint32(b[54:58]) == 0xff0000 && readUint32(b[58:62]) == 0xff00 &&
|
||||
readUint32(b[62:66]) == 0xff && readUint32(b[66:70]) == 0xff000000 {
|
||||
compression = 0
|
||||
}
|
||||
|
||||
rle := false
|
||||
if compression == 1 && bpp == 8 || compression == 2 && bpp == 4 {
|
||||
bmp565 := false
|
||||
|
||||
switch {
|
||||
case compression == 0:
|
||||
// Go ahead
|
||||
case compression == 1 && bpp == 8 || compression == 2 && bpp == 4:
|
||||
rle = true
|
||||
} else if compression != 0 {
|
||||
case compression == 3 && infoLen >= infoHeaderLen:
|
||||
if infoLen == infoHeaderLen {
|
||||
// Color mask is stored after the info header
|
||||
if _, err := io.ReadFull(r, b[54:66]); err != nil {
|
||||
if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
rmask := readUint32(b[54:58])
|
||||
gmask := readUint32(b[58:62])
|
||||
bmask := readUint32(b[62:66])
|
||||
amask := readUint32(b[66:70])
|
||||
|
||||
switch {
|
||||
case bpp == 16 && rmask == 0xF800 && gmask == 0x7E0 && bmask == 0x1F:
|
||||
bmp565 = true
|
||||
case bpp == 16 && rmask == 0x7C00 && gmask == 0x3E0 && bmask == 0x1F:
|
||||
// Go ahead, it's a regular 16 bit image
|
||||
case bpp == 32 && rmask == 0xff0000 && gmask == 0xff00 && bmask == 0xff && amask == 0xff000000:
|
||||
// Go ahead, it's a regular 32-bit image
|
||||
default:
|
||||
return errBmpUnsupported
|
||||
}
|
||||
default:
|
||||
return errBmpUnsupported
|
||||
}
|
||||
|
||||
@ -415,6 +484,8 @@ func (img *Image) loadBmp(data []byte, noAlpha bool) error {
|
||||
switch bpp {
|
||||
case 1, 2, 4, 8:
|
||||
return img.decodeBmpPaletted(r, width, height, int(bpp), palette, topDown)
|
||||
case 16:
|
||||
return img.decodeBmpRGB16(r, width, height, topDown, bmp565)
|
||||
case 24:
|
||||
return img.decodeBmpRGB(r, width, height, 3, topDown, true)
|
||||
case 32:
|
||||
|
Loading…
x
Reference in New Issue
Block a user