commit 5253a955293dc9686cd7fdeb068573e8e610b063
parent 6cad32149c38524a6a24a9dd2b08fb64d95eb7fa
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Tue, 1 Feb 2022 19:08:19 +0800
webp: copy pixel data to unmanaged memory
The code was being unsafe by relying on the pixel buffer
to remain stable. This is not guaranteed by the Go compiler.
Therefore, we copy the data to unmanaged memory instead.
Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Diffstat:
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/webp/encode.go b/webp/encode.go
@@ -51,25 +51,31 @@ func (enc *Encoder) Encode(w io.Writer, m image.Image) error {
if enc.Quality <= 0.0 || enc.Quality > 1 {
enc.Quality = 1.0
}
- rgbaImage := image.NewRGBA(m.Bounds())
- rect := m.Bounds()
- for y := rect.Min.Y; y < rect.Max.Y; y++ {
- for x := rect.Min.X; x < rect.Max.X; x++ {
- rgbaImage.Set(x, y, m.At(x, y))
+ rgba := image.NewRGBA(m.Bounds())
+ b := m.Bounds()
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ rgba.Set(x, y, m.At(x, y))
}
}
+ return enc.encode(w, rgba)
+}
+
+func (enc *Encoder) encode(w io.Writer, m *image.RGBA) error {
var (
// out buffer to contain webp data.
out *byte = nil
)
tls := libc.NewTLS()
defer tls.Close()
+ buf, free := unmanage(tls, m.Pix)
+ defer free()
size := lib.Encode(
tls,
- uintptr(unsafe.Pointer(&rgbaImage.Pix[0])),
- int32(rect.Dx()),
- int32(rect.Dy()),
- int32(rgbaImage.Stride),
+ buf,
+ int32(m.Bounds().Dx()),
+ int32(m.Bounds().Dy()),
+ int32(m.Stride),
// Function pointers are generated by taking a pointer to
// a struct who's first field is that function.
*(*uintptr)(unsafe.Pointer(
@@ -103,3 +109,12 @@ func boolToInt32(b bool) int32 {
}
return 0
}
+
+// unmanage takes a Go byte slice and returns a copy of it backed by
+// unmanaged memory, alongside a function that will free it.
+func unmanage(tls *libc.TLS, src []byte) (handle uintptr, free func()) {
+ buf := libc.Xcalloc(tls, uint64(len(src)), 1)
+ view := libc.GoBytes(buf, len(src))
+ copy(view, src)
+ return buf, func() { libc.Xfree(tls, buf) }
+}