commit 8b9f86c3cf35e5319469a98f6a6a0a707757aadd
parent 61bcd809df050051345098e0c46884ccc52c8c97
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Wed, 3 Jan 2024 16:31:37 +0800
lib/dynamic: add decode and fix lossy panic with cgo
Due a bug in purego, we cannot use float parameters while cgo is enabled on linux.
When cgo is enabled, we force the use of lossless encoding.
Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Diffstat:
5 files changed, 55 insertions(+), 54 deletions(-)
diff --git a/lib/dynamic/webp/encode_cgo.go b/lib/dynamic/webp/encode_cgo.go
@@ -0,0 +1,16 @@
+//go:build linux && cgo
+
+package webp
+
+import (
+ "image"
+ "io"
+
+ "git.sr.ht/~jackmordaunt/go-libwebp/lib/common"
+)
+
+// HACK: always use lossless when cgo is activated on linux. cgo on linux provokes
+// a bug in purego when using float arguments.
+func encodeImpl(w io.Writer, m *image.RGBA, quality float32) error {
+ return common.Encode(w, m, quality, wrappedLossless, WebPFree)
+}
diff --git a/lib/dynamic/webp/encode_default.go b/lib/dynamic/webp/encode_default.go
@@ -0,0 +1,17 @@
+//go:build !(linux && cgo)
+
+package webp
+
+import (
+ "image"
+ "io"
+
+ "git.sr.ht/~jackmordaunt/go-libwebp/lib/common"
+)
+
+func encodeImpl(w io.Writer, m *image.RGBA, quality float32) error {
+ if quality >= 1.0 {
+ return common.Encode(w, m, quality, wrappedLossless, WebPFree)
+ }
+ return common.Encode(w, m, quality, WebPEncodeRGBA, WebPFree)
+}
diff --git a/lib/dynamic/webp/lib.go b/lib/dynamic/webp/lib.go
@@ -2,17 +2,20 @@ package webp
import (
"fmt"
- "unsafe"
+ "image"
+ "io"
+ "git.sr.ht/~jackmordaunt/go-libwebp/lib/common"
"github.com/ebitengine/purego"
)
var (
_libwebp uintptr
- _WebPEncodeLosslessRGBA func(uintptr, uintptr, uintptr, uintptr, uintptr) uintptr
- _WebPEncodeRGBA func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) uintptr
- _WebPFree func(uintptr)
+ WebPEncodeLosslessRGBA func(in uintptr, width int32, height int32, bps int32, out uintptr) (size uint64)
+ WebPEncodeRGBA func(in uintptr, width int32, height int32, bps int32, quality float32, out uintptr) (size uint64)
+ WebPDecodeRGBA func(data uintptr, size uint64, width uintptr, height uintptr) uintptr
+ WebPFree func(ptr uintptr)
)
func loadLibrary() (uintptr, error) {
@@ -33,55 +36,23 @@ func Init() (err error) {
return err
}
- _WebPEncodeLosslessRGBA = func() (fn func(uintptr, uintptr, uintptr, uintptr, uintptr) uintptr) {
- purego.RegisterLibFunc(&fn, _libwebp, "WebPEncodeLosslessRGBA")
- return
- }()
-
- _WebPEncodeRGBA = func() (fn func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) uintptr) {
- purego.RegisterLibFunc(&fn, _libwebp, "WebPEncodeRGBA")
- return
- }()
-
- _WebPFree = func() (fn func(uintptr)) {
- purego.RegisterLibFunc(&fn, _libwebp, "WebPFree")
- return
- }()
+ purego.RegisterLibFunc(&WebPEncodeLosslessRGBA, _libwebp, "WebPEncodeLosslessRGBA")
+ purego.RegisterLibFunc(&WebPEncodeRGBA, _libwebp, "WebPEncodeRGBA")
+ purego.RegisterLibFunc(&WebPDecodeRGBA, _libwebp, "WebPDecodeRGBA")
+ purego.RegisterLibFunc(&WebPFree, _libwebp, "WebPFree")
return nil
}
-func EncodeImpl(
- in unsafe.Pointer,
- w int32,
- h int32,
- bps int32,
- q float32,
- out unsafe.Pointer,
-) uint64 {
- Init()
- var sz uintptr
- if q >= 1.0 {
- sz = _WebPEncodeLosslessRGBA(
- uintptr(in),
- uintptr(w),
- uintptr(h),
- uintptr(bps),
- uintptr(out),
- )
- } else {
- sz = _WebPEncodeRGBA(
- uintptr(in),
- uintptr(w),
- uintptr(h),
- uintptr(bps),
- uintptr(q),
- uintptr(out),
- )
- }
- return uint64(sz)
+func DecodeImpl(buf []byte) (image.Image, error) {
+ return common.Decode(buf, WebPDecodeRGBA, WebPFree)
+}
+
+func EncodeImpl(w io.Writer, m *image.RGBA, quality float32) error {
+ return encodeImpl(w, m, quality)
}
-func FreeImpl(ptr unsafe.Pointer) {
- _WebPFree(uintptr(ptr))
+// wrappedLossless drops the quality param and does a lossless encode.
+func wrappedLossless(in uintptr, w int32, h int32, bps int32, _ float32, out uintptr) uint64 {
+ return WebPEncodeLosslessRGBA(in, w, h, bps, out)
}
diff --git a/lib/dynamic/webp/lib_darwin_amd64.go b/lib/dynamic/webp/lib_darwin_amd64.go
@@ -8,9 +8,6 @@ import (
const libraryName = "libwebp.dylib"
-//go:embed blobs/libwebp.dylib
-var libraryData []byte
-
func dlopen(name string) (uintptr, error) {
- return purego.Dlopen(libraryName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
+ return purego.Dlopen(libraryName, purego.RTLD_LAZY|purego.RTLD_GLOBAL)
}
diff --git a/lib/dynamic/webp/lib_linux_amd64.go b/lib/dynamic/webp/lib_linux_amd64.go
@@ -9,5 +9,5 @@ import (
const libraryName = "libwebp.so"
func dlopen(name string) (uintptr, error) {
- return purego.Dlopen(libraryName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
+ return purego.Dlopen(libraryName, purego.RTLD_LAZY|purego.RTLD_GLOBAL)
}