mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-27 10:41:58 +02:00
Move caching implementation to Python
Less code, more performant since the cache is used from Python. And we can make the Go code a pure image format conversion filter.
This commit is contained in:
97
tools/utils/images/convert.go
Normal file
97
tools/utils/images/convert.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package images
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/utils"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
func encode_rgba(output io.Writer, img image.Image) (err error) {
|
||||
var final_img *image.NRGBA
|
||||
switch img.(type) {
|
||||
case *image.NRGBA:
|
||||
final_img = img.(*image.NRGBA)
|
||||
default:
|
||||
b := img.Bounds()
|
||||
final_img = image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||
ctx := Context{}
|
||||
ctx.PasteCenter(final_img, img, nil)
|
||||
}
|
||||
b := final_img.Bounds()
|
||||
header := make([]byte, 8)
|
||||
var width = utils.Abs(b.Dx())
|
||||
var height = utils.Abs(b.Dy())
|
||||
binary.LittleEndian.PutUint32(header, uint32(width))
|
||||
binary.LittleEndian.PutUint32(header[4:], uint32(height))
|
||||
readers := []io.Reader{bytes.NewReader(header)}
|
||||
stride := 4 * width
|
||||
|
||||
if final_img.Stride == stride {
|
||||
readers = append(readers, bytes.NewReader(final_img.Pix))
|
||||
} else {
|
||||
p := final_img.Pix
|
||||
for y := 0; y < b.Dy(); y++ {
|
||||
readers = append(readers, bytes.NewReader(p[:min(stride, len(p))]))
|
||||
p = p[final_img.Stride:]
|
||||
}
|
||||
}
|
||||
_, err = io.Copy(output, io.MultiReader(readers...))
|
||||
return
|
||||
}
|
||||
|
||||
func convert_image(input io.ReadSeeker, output io.Writer, format string) (err error) {
|
||||
image_data, err := OpenNativeImageFromReader(input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(image_data.Frames) == 0 {
|
||||
return fmt.Errorf("Image has no frames")
|
||||
}
|
||||
img := image_data.Frames[0].Img
|
||||
switch strings.ToUpper(format) {
|
||||
case "RGBA":
|
||||
return encode_rgba(output, img)
|
||||
case "JPEG", "JPG":
|
||||
return Encode(output, img, "image/jpeg")
|
||||
case "PNG":
|
||||
return Encode(output, img, "image/png")
|
||||
case "GIF":
|
||||
return Encode(output, img, "image/gif")
|
||||
case "BMP":
|
||||
return Encode(output, img, "image/bmp")
|
||||
case "TIFF":
|
||||
return Encode(output, img, "image/tiff")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ConvertEntryPoint(root *cli.Command) {
|
||||
root.AddSubCommand(&cli.Command{
|
||||
Name: "__convert_image__",
|
||||
Hidden: true,
|
||||
OnlyArgsAllowed: true,
|
||||
Run: func(cmd *cli.Command, args []string) (rc int, err error) {
|
||||
format := "RGBA"
|
||||
if len(args) > 0 {
|
||||
format = args[0]
|
||||
}
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024*1024))
|
||||
if _, err = io.Copy(buf, os.Stdin); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
if err = convert_image(bytes.NewReader(buf.Bytes()), os.Stdout, format); err != nil {
|
||||
rc = 1
|
||||
}
|
||||
return
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user