mirror of
https://gitee.com/energye/energy.git
synced 2024-12-06 05:38:17 +08:00
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
|
package winicon
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"bytes"
|
||
|
"encoding/binary"
|
||
|
"fmt"
|
||
|
"image"
|
||
|
"image/png"
|
||
|
"io"
|
||
|
|
||
|
"github.com/energye/energy/v2/pkgs/winicon/internal/winicon"
|
||
|
"golang.org/x/image/draw"
|
||
|
)
|
||
|
|
||
|
// GenerateIcon reads image data from the given reader and generates
|
||
|
// a .ico file that is written to the given writer. The .ico file will include
|
||
|
// a number of icons at the sizes given.
|
||
|
func GenerateIcon(r io.Reader, w io.Writer, sizes []int) error {
|
||
|
header := &winicon.IconFileHeader{
|
||
|
ImageType: 1,
|
||
|
ImageCount: uint16(len(sizes)),
|
||
|
}
|
||
|
|
||
|
iconheaders := make([]winicon.IconHeader, len(sizes))
|
||
|
|
||
|
var imageData bytes.Buffer
|
||
|
|
||
|
// Decode to internal image
|
||
|
imagedata, _, err := image.Decode(r)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Loop over sizes desired
|
||
|
for index, size := range sizes {
|
||
|
|
||
|
// Check target size
|
||
|
if size == 0 {
|
||
|
return fmt.Errorf("a size of 0 is not valid")
|
||
|
}
|
||
|
|
||
|
// Scale image
|
||
|
rect := image.Rect(0, 0, size, size)
|
||
|
rawdata := image.NewRGBA(rect)
|
||
|
scale := draw.CatmullRom
|
||
|
scale.Scale(rawdata, rect, imagedata, imagedata.Bounds(), draw.Over, nil)
|
||
|
|
||
|
// Convert back to PNG
|
||
|
icondata := new(bytes.Buffer)
|
||
|
writer := bufio.NewWriter(icondata)
|
||
|
err = png.Encode(writer, rawdata)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
err = writer.Flush()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Save image data
|
||
|
imageData.Write(icondata.Bytes())
|
||
|
|
||
|
// Save header information
|
||
|
if size >= 256 {
|
||
|
size = 0
|
||
|
}
|
||
|
iconheaders[index].Width = (uint8)(size)
|
||
|
iconheaders[index].Height = (uint8)(size)
|
||
|
iconheaders[index].BitsPerPixel = 32
|
||
|
iconheaders[index].Size = uint32(len(icondata.Bytes()))
|
||
|
}
|
||
|
|
||
|
// Update the offsets. Start by skipping header+icon headers
|
||
|
var currentOffset uint32 = (uint32)(6 + (16 * len(iconheaders)))
|
||
|
|
||
|
for index := range iconheaders {
|
||
|
iconheaders[index].Offset = currentOffset
|
||
|
currentOffset += iconheaders[index].Size
|
||
|
}
|
||
|
|
||
|
// Write out the header
|
||
|
err = binary.Write(w, binary.LittleEndian, header)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// Write out the icon headers
|
||
|
for _, iconheader := range iconheaders {
|
||
|
err = binary.Write(w, binary.LittleEndian, iconheader)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Write out the image data
|
||
|
_, err = w.Write(imageData.Bytes())
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|