diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9625e10..7c56964 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index fdcc671..d97f17e 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '11.0' +# platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d161b21..973bd64 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -15,8 +15,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: blurhash_ffi: 4831b96320d4273876c9a2fd3f7d50b8a3a53509 - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 -PODFILE CHECKSUM: 70d9d25280d0dd177a5f637cdb0f0b0b12c6a189 +PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 -COCOAPODS: 1.12.1 +COCOAPODS: 1.15.2 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index df8adb5..2843ebb 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -219,7 +219,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 331C8080294A63A400263BE5 = { @@ -457,7 +457,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -584,7 +584,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -633,7 +633,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 87131a0..8e3ca5d 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ (); final listener = ImageStreamListener((imageInfo, _) async { - final ByteData? bytes = - await imageInfo.image.toByteData(format: ui.ImageByteFormat.rawRgba); + final ByteData? bytes = await imageInfo.image + .toByteData(format: ui.ImageByteFormat.rawRgba); if (bytes == null) { completer.completeError(BlurhashFFIException( 'Could not decode Image from Image provider', @@ -186,15 +186,10 @@ class BlurhashFFI { return; } final Uint8List list = bytes.buffer.asUint8List(); - final rgbBytes = Uint8List(list.length ~/ 4 * 3); - for (var i = 0, j = 0; i < list.length; i += 4, j += 3) { - rgbBytes[j] = list[i]; - rgbBytes[j + 1] = list[i + 1]; - rgbBytes[j + 2] = list[i + 2]; - } + if (!completer.isCompleted) { completer.complete(BlurHashImageInfo(imageInfo.image.height, - imageInfo.image.width, imageInfo.image.width * 3, rgbBytes)); + imageInfo.image.width, imageInfo.image.width * 4, list)); } }, onError: (dynamic exception, StackTrace? stackTrace) { completer.completeError(exception, stackTrace); @@ -356,7 +351,6 @@ class BlurhashFFI { data.pixelsPointer, data.rowStride, ); - data.free(); final String resultString = result.cast().toDartString(); final _EncodeResponse response = _EncodeResponse(data.id, resultString); @@ -365,7 +359,6 @@ class BlurhashFFI { } else if (data is _DecodeRequest) { final Pointer result = _bindings.decode(data.blurHashPointer, data.width, data.height, data.punch, data.channels); - data.free(); final Uint8List resultImage = result.asTypedList( data.width * data.height * data.channels, // preffer way but works only from dart 3.1.0, and requre to change generated bindings @@ -402,7 +395,7 @@ class BlurhashFFI { final stackTrace = StackTrace.current; throw BlurhashFFIException( 'ERORR: ${Isolate.current.debugName}', stackTrace, e); - } + } } final ReceivePort helperReceivePort = ReceivePort()..listen(onSend); @@ -423,7 +416,11 @@ class BlurhashFFIException extends Error { [this.level = Level.SEVERE]); } -class _DecodeToArrayRequest { +mixin Freeable { + void free(); +} + +class _DecodeToArrayRequest with Freeable{ final int id; final String blurHash; final int width; @@ -444,6 +441,7 @@ class _DecodeToArrayRequest { return _bhptr!.cast(); } + @override void free() { if (_bhptr != null) { malloc.free(_bhptr!); @@ -452,7 +450,7 @@ class _DecodeToArrayRequest { } } -class _DecodeRequest { +class _DecodeRequest with Freeable{ final int id; final String blurHash; final int width; @@ -471,7 +469,7 @@ class _DecodeRequest { } return _bhptr!.cast(); } - + @override void free() { if (_bhptr != null) { malloc.free(_bhptr!); @@ -480,7 +478,7 @@ class _DecodeRequest { } } -class _EncodeRequest { +class _EncodeRequest with Freeable{ final int id; final Uint8List pixels; final int width; @@ -501,6 +499,7 @@ class _EncodeRequest { return pixelsPtr!; } + @override void free() { if (pixelsPtr != null) { calloc.free(pixelsPtr!); diff --git a/lib/blurhash_ffi_bindings_generated.dart b/lib/blurhash_ffi_bindings_generated.dart index 81194fb..07c3231 100644 --- a/lib/blurhash_ffi_bindings_generated.dart +++ b/lib/blurhash_ffi_bindings_generated.dart @@ -34,7 +34,7 @@ class BlurhashFfiBindings { /// `yComponents` - The number of components in the Y direction. Must be between 1 and 9. 3 to 5 is usually a good range for this. /// `width` - The width in pixels of the supplied image. /// `height` - The height in pixels of the supplied image. - /// `rgb` - A pointer to the pixel data. This is supplied in RGB order, with 3 bytes per pixels. + /// `rgb` - A pointer to the pixel data. This is supplied in RGBA format, with 4 bytes per pixels. /// `bytesPerRow` - The number of bytes per row of the RGB pixel data. ffi.Pointer blurHashForPixels( int xComponents, @@ -166,22 +166,4 @@ class BlurhashFfiBindings { 'freePixelArray'); late final _freePixelArray = _freePixelArrayPtr.asFunction)>(); - - /// freeBlurhash : Frees the blurhash string - /// Parameters : - /// blurhash : Blurhash string pointer which will be freed. - /// Returns : void (None) - void freeString( - ffi.Pointer blurhash, - ) { - return _freeString( - blurhash, - ); - } - - late final _freeStringPtr = - _lookup)>>( - 'freeString'); - late final _freeString = - _freeStringPtr.asFunction)>(); } diff --git a/src/blurhash_ffi.c b/src/blurhash_ffi.c index 8cbf1a4..4ccce6a 100644 --- a/src/blurhash_ffi.c +++ b/src/blurhash_ffi.c @@ -48,6 +48,8 @@ const char *blurHashForPixels(int xComponents, int yComponents, int width, int h } } + free(rgb); + float *dc = &factors[0]; float *ac = dc + 3; int acCount = xComponents * yComponents - 1; @@ -88,12 +90,14 @@ static float *multiplyBasisFunction(int xComponent, int yComponent, int width, i float r = 0, g = 0, b = 0; float normalisation = (xComponent == 0 && yComponent == 0) ? 1 : 2; + int channels = (int)bytesPerRow / width; + for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { float basis = cosf(M_PI * xComponent * x / width) * cosf(M_PI * yComponent * y / height); - r += basis * sRGBToLinear(rgb[3 * x + 0 + y * bytesPerRow]); - g += basis * sRGBToLinear(rgb[3 * x + 1 + y * bytesPerRow]); - b += basis * sRGBToLinear(rgb[3 * x + 2 + y * bytesPerRow]); + r += basis * sRGBToLinear(rgb[channels * x + 0 + y * bytesPerRow]); + g += basis * sRGBToLinear(rgb[channels * x + 1 + y * bytesPerRow]); + b += basis * sRGBToLinear(rgb[channels * x + 2 + y * bytesPerRow]); } } diff --git a/src/blurhash_ffi.h b/src/blurhash_ffi.h index 64a38e8..26957a8 100644 --- a/src/blurhash_ffi.h +++ b/src/blurhash_ffi.h @@ -28,7 +28,7 @@ `yComponents` - The number of components in the Y direction. Must be between 1 and 9. 3 to 5 is usually a good range for this. `width` - The width in pixels of the supplied image. `height` - The height in pixels of the supplied image. - `rgb` - A pointer to the pixel data. This is supplied in RGB order, with 3 bytes per pixels. + `rgb` - A pointer to the pixel data. This is supplied in RGBA format, with 4 bytes per pixels. `bytesPerRow` - The number of bytes per row of the RGB pixel data. */