|
@@ -1,6 +1,7 @@
|
|
|
package imagemeta
|
|
|
|
|
|
import (
|
|
|
+ "bytes"
|
|
|
"encoding/binary"
|
|
|
"io"
|
|
|
)
|
|
@@ -83,3 +84,51 @@ 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
|
|
|
+}
|