瀏覽代碼

Fix transparrency in loaded ICO

DarthSim 3 年之前
父節點
當前提交
175cb8c41b
共有 4 個文件被更改,包括 55 次插入58 次删除
  1. 0 49
      imagemeta/ico.go
  2. 1 2
      vips/bmp.go
  3. 53 6
      vips/ico.go
  4. 1 1
      vips/vips.go

+ 0 - 49
imagemeta/ico.go

@@ -1,7 +1,6 @@
 package imagemeta
 
 import (
-	"bytes"
 	"encoding/binary"
 	"io"
 
@@ -86,51 +85,3 @@ func init() {
 		func(r io.Reader) (Meta, error) { return DecodeIcoMeta(r) },
 	)
 }
-
-// FixBmpHeader fixes an incomplete header of BMP stored in ICO
-func FixBmpHeader(b []byte) ([]byte, error) {
-	buf := new(bytes.Buffer)
-
-	fileSize := uint32(14 + len(b))
-
-	buf.Grow(int(fileSize))
-
-	buf.Write(bmpMagick)
-
-	if err := binary.Write(buf, binary.LittleEndian, &fileSize); err != nil {
-		return nil, err
-	}
-
-	reserved := uint32(0)
-	if err := binary.Write(buf, binary.LittleEndian, &reserved); err != nil {
-		return nil, err
-	}
-
-	colorUsed := binary.LittleEndian.Uint32(b[32:36])
-	bitCount := binary.LittleEndian.Uint16(b[14:16])
-
-	var pixOffset uint32
-	if colorUsed == 0 && bitCount <= 8 {
-		pixOffset = 14 + 40 + 4*(1<<bitCount)
-	} else {
-		pixOffset = 14 + 40 + 4*colorUsed
-	}
-
-	if err := binary.Write(buf, binary.LittleEndian, &pixOffset); err != nil {
-		return nil, err
-	}
-
-	// Write size and width
-	buf.Write(b[:8])
-
-	// For some reason ICO stores double height
-	height := binary.LittleEndian.Uint32(b[8:12]) / 2
-	if err := binary.Write(buf, binary.LittleEndian, &height); err != nil {
-		return nil, err
-	}
-
-	// Write the rest
-	buf.Write(b[12:])
-
-	return buf.Bytes(), nil
-}

+ 1 - 2
vips/bmp.go

@@ -191,7 +191,7 @@ func (img *Image) decodeBmpRGB(r io.Reader, width, height, bands int, topDown, n
 	return nil
 }
 
-func (img *Image) loadBmp(data []byte) error {
+func (img *Image) loadBmp(data []byte, noAlpha bool) error {
 	// We only support those BMP images that are a BITMAPFILEHEADER
 	// immediately followed by a BITMAPINFOHEADER.
 	const (
@@ -282,7 +282,6 @@ func (img *Image) loadBmp(data []byte) error {
 		}
 		return img.decodeBmpRGB(r, width, height, 3, topDown, true)
 	case 32:
-		noAlpha := true
 		if infoLen >= 70 {
 			// Alpha mask is empty, so no alpha here
 			noAlpha = readUint32(b[66:70]) == 0

+ 53 - 6
vips/ico.go

@@ -32,16 +32,16 @@ func (img *Image) loadIco(data []byte, shrink int, scale float64, pages int) err
 	meta, err := imagemeta.DecodeMeta(bytes.NewReader(internalData))
 	if err != nil {
 		// Looks like it's BMP with an incomplete header
-		if d, err := imagemeta.FixBmpHeader(internalData); err == nil {
-			internalType = imagetype.BMP
-			internalData = d
-		} else {
+		d, err := icoFixBmpHeader(internalData)
+		if err != nil {
 			return err
 		}
-	} else {
-		internalType = meta.Format()
+
+		return img.loadBmp(d, false)
 	}
 
+	internalType = meta.Format()
+
 	if internalType == imagetype.ICO || !SupportsLoad(internalType) {
 		return fmt.Errorf("Can't load %s from ICO", internalType)
 	}
@@ -129,3 +129,50 @@ func (img *Image) saveAsIco() (*imagedata.ImageData, error) {
 
 	return &imgdata, nil
 }
+
+func icoFixBmpHeader(b []byte) ([]byte, error) {
+	buf := new(bytes.Buffer)
+
+	fileSize := uint32(14 + len(b))
+
+	buf.Grow(int(fileSize))
+
+	buf.WriteString("BM")
+
+	if err := binary.Write(buf, binary.LittleEndian, &fileSize); err != nil {
+		return nil, err
+	}
+
+	reserved := uint32(0)
+	if err := binary.Write(buf, binary.LittleEndian, &reserved); err != nil {
+		return nil, err
+	}
+
+	colorUsed := binary.LittleEndian.Uint32(b[32:36])
+	bitCount := binary.LittleEndian.Uint16(b[14:16])
+
+	var pixOffset uint32
+	if colorUsed == 0 && bitCount <= 8 {
+		pixOffset = 14 + 40 + 4*(1<<bitCount)
+	} else {
+		pixOffset = 14 + 40 + 4*colorUsed
+	}
+
+	if err := binary.Write(buf, binary.LittleEndian, &pixOffset); err != nil {
+		return nil, err
+	}
+
+	// Write size and width
+	buf.Write(b[:8])
+
+	// For some reason ICO stores double height
+	height := binary.LittleEndian.Uint32(b[8:12]) / 2
+	if err := binary.Write(buf, binary.LittleEndian, &height); err != nil {
+		return nil, err
+	}
+
+	// Write the rest
+	buf.Write(b[12:])
+
+	return buf.Bytes(), nil
+}

+ 1 - 1
vips/vips.go

@@ -208,7 +208,7 @@ func (img *Image) Load(imgdata *imagedata.ImageData, shrink int, scale float64,
 	}
 
 	if imgdata.Type == imagetype.BMP {
-		return img.loadBmp(imgdata.Data)
+		return img.loadBmp(imgdata.Data, true)
 	}
 
 	var tmp *C.VipsImage