go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

commit 61bcd809df050051345098e0c46884ccc52c8c97
parent 55f31ea7f7298c3aeb2a7b051784a7ff313f0d35
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Wed,  3 Jan 2024 16:30:32 +0800

lib/transpiled: add decode and fix asm panic

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>

Diffstat:
Mlib/transpiled/webp/lib.go | 80+++++++++++++++++++++++++++++++++++++++++++------------------------------------
1 file changed, 44 insertions(+), 36 deletions(-)

diff --git a/lib/transpiled/webp/lib.go b/lib/transpiled/webp/lib.go @@ -1,51 +1,59 @@ package webp import ( - "unsafe" + "image" + "io" + "git.sr.ht/~jackmordaunt/go-libwebp/lib/common" "modernc.org/libc" ) -var tls *libc.TLS - -func EncodeImpl( - in unsafe.Pointer, - w int32, - h int32, - bps int32, - q float32, - out unsafe.Pointer, -) (size uint64) { - tls = libc.NewTLS() +func DecodeImpl(buf []byte) (image.Image, error) { + disableVP8GetCPUInfo() + tls := libc.NewTLS() defer tls.Close() + return common.Decode(buf, makeDecodeImpl(tls), makeFreeImpl(tls)) +} + +func EncodeImpl(w io.Writer, m *image.RGBA, quality float32) error { + tls := libc.NewTLS() + defer tls.Close() + return common.Encode(w, m, quality, makeEncodeImpl(tls), makeFreeImpl(tls)) +} - if q >= 1.0 { - size = WebPEncodeLosslessRGBA( - tls, - uintptr(in), - w, - h, - bps, - uintptr(out), - ) - } else { - size = WebPEncodeRGBA( - tls, - uintptr(in), - w, - h, - bps, - q, - uintptr(out), - ) +func makeDecodeImpl(tls *libc.TLS) common.DecoderFunc { + return func(data uintptr, data_size uint64, width, height uintptr) uintptr { + return WebPDecodeRGBA(tls, data, data_size, width, height) } +} - return size +func makeEncodeImpl(tls *libc.TLS) common.EncodeFunc { + return func(in uintptr, w, h, bps int32, q float32, out uintptr) uint64 { + if q >= 1.0 { + return WebPEncodeLosslessRGBA(tls, in, w, h, bps, out) + } + return WebPEncodeRGBA(tls, in, w, h, bps, q, out) + } } -func FreeImpl(ptr unsafe.Pointer) { - if tls == nil { - panic("tls is nil, invalid use of transpile api") +func makeFreeImpl(tls *libc.TLS) common.FreeFunc { + return func(p uintptr) { + WebPFree(tls, p) } - WebPFree(tls, uintptr(ptr)) +} + +func disableVP8GetCPUInfo() { + // HACK: Avoid panic when decoding lossy webp data. + // + // Inline asm is used for CPU feature detection; ccgo doesn't support inline asm. + // + // libwebp uses this function pointer to check for any specialized CPU instructions. + // If not nil (which it is for well supported platforms, like amd64, and arm64), it will try + // to check CPU features using inline asm. ccgo inserts a panic for inline asm, thus using + // this will panic. + // + // To avoid this terrible fate, we must manually turn off the CPU feature detection by + // nil'ing out this function pointer. This must be done after package init since that is + // is when this value is set by the transpiled code. + VP8GetCPUInfo = 0 }