I want to encode image into webp in dart. I created libwebp.dll file (sources https://github.com/jacklicn/libwebp)
Now I have to use this library for encoding process:
import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'package:flutter/foundation.dart';
typedef NativeEncodeFunc =
Uint64 Function(
Pointer<Uint8> rgb,
Int32 width,
Int32 height,
Int32 stride,
Float quality_factor,
Pointer<Pointer<Uint8>> output,
);
typedef DartEncodeFunc =
int Function(
Pointer<Uint8> rgb,
int width,
int height,
int stride,
double quality_factor,
Pointer<Pointer<Uint8>> output,
);
typedef NativeFreeFunc = Void Function(Pointer<Uint8>);
typedef DartFreeFunc = void Function(Pointer<Uint8>);
class WebPFFI {
late final DynamicLibrary _lib;
late final DartEncodeFunc _encode;
late final DartFreeFunc _free;
WebPFFI() {
final path = _getLibraryPath();
try {
_lib = DynamicLibrary.open(path);
_encode = _lib
.lookup<NativeFunction<NativeEncodeFunc>>('WebPEncodeRGB')
.asFunction();
_free = _lib
.lookup<NativeFunction<NativeFreeFunc>>('WebPFree')
.asFunction();
} catch (e) {
throw Exception('Failed to load WebP library ($path): $e');
}
}
Uint8List encode(Uint8List rgb, int width, int height, int quality) {
// size check
if (width <= 0 || height <= 0) {
throw ArgumentError('Invalid dimensions: $width x $height');
}
if (quality < 0 || quality > 100) {
throw ArgumentError('Quality must be between 0 and 100');
}
final rgbPtr = malloc<Uint8>(rgb.length);
rgbPtr.asTypedList(rgb.length).setAll(0, rgb);
final outputPtr = calloc<Pointer<Uint8>>();
try {
// WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb,
// int width, int height, int stride,
// float quality_factor, uint8_t**
final resultSize = _encode(
rgbPtr,
width,
height,
width * 3, // stride -> RGB
quality.toDouble(),
outputPtr,
);
if (resultSize == 0) {
throw Exception('WebP encoding failed');
}
final result = outputPtr.value.asTypedList(resultSize);
return Uint8List.fromList(result);
} finally {
if (outputPtr.value != nullptr) {
_free(outputPtr.value);
}
calloc.free(outputPtr);
malloc.free(rgbPtr);
}
}
String _getLibraryPath() {
if (Platform.isWindows) return 'windows/libwebp.dll';
if (Platform.isLinux) return 'linux/libwebp.so';
if (Platform.isMacOS) return 'macos/libwebp.dylib';
if (Platform.isAndroid) return 'android/libwebp.soso';
if (Platform.isIOS) return 'ios/libwebp.soso';
if (kIsWeb) return 'web/libwebp.idk what should I use here';
throw UnsupportedError('_getLibraryPath not supported for WebP');
}
}
This function causes whole app crash without any exception: final resultSize = _encode( rgbPtr, width, height, width * 3, // stride -> RGB quality.toDouble(), outputPtr, );
_encode is not null, _lib is not null too. Where is a bug? How to encode image into webp?
Update:
1) dumpbin /EXPORTS libwebp.dll | findstr "WebPEncodeRGB"
30 1D 00033A60 WebPEncodeRGB
31 1E 00033AA0 WebPEncodeRGBA
2) Doesn't throw an exception:
if (_lib.providesSymbol('WebPEncodeRGB') == false) {
throw Exception('Symbol WebPEncodeRGB not found in library');
}