diff --git a/README.md b/README.md index 53f7959..74d8cd4 100644 --- a/README.md +++ b/README.md @@ -174,6 +174,15 @@ const webImage = await WebImages.loadFromURLAsync('https://picsum.photos/seed/ const upsideDown = await webImage.rotateAsync(180) ``` +#### Mirroring + +An `Image` can be mirrored horizontally (left <-> right) entirely in-memory, without ever writing to- or reading from- a file: + +```ts +const webImage = await WebImages.loadFromURLAsync('https://picsum.photos/seed/123/400') +const mirrored = await webImage.mirrorHorizontallyAsync() +``` + #### Render into another Image An `Image` can be rendered into another `Image` entirely in-memory. This creates a third image (the result): diff --git a/bun.lock b/bun.lock index 2a4099c..f2dbeb9 100644 --- a/bun.lock +++ b/bun.lock @@ -21,16 +21,16 @@ }, "example": { "name": "NitroImageExample", - "version": "0.11.0", + "version": "0.11.1", "dependencies": { "@react-navigation/bottom-tabs": "^7.4.6", "@react-navigation/native": "^7.1.17", "react": "19.1.0", "react-native": "0.81.0", "react-native-fast-image": "^8.6.3", - "react-native-nitro-image": "../packages/react-native-nitro-image", + "react-native-nitro-image": "workspace:*", "react-native-nitro-modules": "0.33.9", - "react-native-nitro-web-image": "../packages/react-native-nitro-web-image", + "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.6.0", "react-native-screens": "^4.14.1", }, @@ -50,7 +50,7 @@ }, "packages/react-native-nitro-image": { "name": "react-native-nitro-image", - "version": "0.11.0", + "version": "0.11.1", "devDependencies": { "@types/react": "^19.0.6", "nitrogen": "0.33.9", @@ -67,7 +67,7 @@ }, "packages/react-native-nitro-web-image": { "name": "react-native-nitro-web-image", - "version": "0.11.0", + "version": "0.11.1", "devDependencies": { "@types/react": "^19.0.6", "nitrogen": "0.33.9", @@ -1771,10 +1771,6 @@ "@ts-morph/common/minimatch": ["minimatch@10.1.2", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.1" } }, "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw=="], - "NitroImageExample/react-native-nitro-image": ["react-native-nitro-image@file:packages/react-native-nitro-image", { "devDependencies": { "@types/react": "^19.0.6", "nitrogen": "0.33.9", "react": "19.1.0", "react-native": "0.81.0", "react-native-nitro-modules": "0.33.9", "typescript": "5.8.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }], - - "NitroImageExample/react-native-nitro-web-image": ["react-native-nitro-web-image@file:packages/react-native-nitro-web-image", { "devDependencies": { "@types/react": "^19.0.6", "nitrogen": "0.33.9", "react": "19.1.0", "react-native": "0.81.0", "react-native-nitro-modules": "0.33.9", "typescript": "5.8.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-image": "*", "react-native-nitro-modules": "*" } }], - "accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], @@ -2113,8 +2109,6 @@ "@simple-libs/stream-utils/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], - "NitroImageExample/react-native-nitro-web-image/react-native-nitro-image": ["react-native-nitro-image@file:packages/react-native-nitro-image", { "devDependencies": { "@types/react": "^19.0.6", "nitrogen": "0.33.9", "react": "19.1.0", "react-native": "0.81.0", "react-native-nitro-modules": "0.33.9", "typescript": "5.8.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }], - "accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "ansi-fragments/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="], diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 064f862..6a9234d 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2493,9 +2493,9 @@ DEPENDENCIES: - fmt (from `../../node_modules/react-native/third-party-podspecs/fmt.podspec`) - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - NitroImage (from `../node_modules/react-native-nitro-image`) + - NitroImage (from `../../node_modules/react-native-nitro-image`) - NitroModules (from `../../node_modules/react-native-nitro-modules`) - - NitroWebImage (from `../node_modules/react-native-nitro-web-image`) + - NitroWebImage (from `../../node_modules/react-native-nitro-web-image`) - RCT-Folly (from `../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTDeprecation (from `../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - RCTRequired (from `../../node_modules/react-native/Libraries/Required`) @@ -2591,11 +2591,11 @@ EXTERNAL SOURCES: :podspec: "../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2025-07-07-RNv0.81.0-e0fc67142ec0763c6b6153ca2bf96df815539782 NitroImage: - :path: "../node_modules/react-native-nitro-image" + :path: "../../node_modules/react-native-nitro-image" NitroModules: :path: "../../node_modules/react-native-nitro-modules" NitroWebImage: - :path: "../node_modules/react-native-nitro-web-image" + :path: "../../node_modules/react-native-nitro-web-image" RCT-Folly: :podspec: "../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" RCTDeprecation: diff --git a/example/package.json b/example/package.json index f0b4883..49cdb5e 100644 --- a/example/package.json +++ b/example/package.json @@ -16,8 +16,8 @@ "react": "19.1.0", "react-native": "0.81.0", "react-native-fast-image": "^8.6.3", - "react-native-nitro-image": "../packages/react-native-nitro-image", - "react-native-nitro-web-image": "../packages/react-native-nitro-web-image", + "react-native-nitro-image": "workspace:*", + "react-native-nitro-web-image": "workspace:*", "react-native-nitro-modules": "0.33.9", "react-native-safe-area-context": "^5.6.0", "react-native-screens": "^4.14.1" diff --git a/package.json b/package.json index b0b3c67..f2dcae4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,5 @@ { "name": "react-native-nitro-image-monorepo", - "packageManager": "bun@1.3.9", "private": true, "version": "0.11.1", "repository": "https://github.com/mrousavy/react-native-nitro-image.git", diff --git a/packages/react-native-nitro-image/android/src/main/java/com/margelo/nitro/image/HybridImage.kt b/packages/react-native-nitro-image/android/src/main/java/com/margelo/nitro/image/HybridImage.kt index 89e7c93..975b546 100644 --- a/packages/react-native-nitro-image/android/src/main/java/com/margelo/nitro/image/HybridImage.kt +++ b/packages/react-native-nitro-image/android/src/main/java/com/margelo/nitro/image/HybridImage.kt @@ -134,6 +134,18 @@ class HybridImage: HybridImageSpec { return Promise.async { crop(startX, startY, endX, endY) } } + override fun mirrorHorizontally(): HybridImageSpec { + val matrix = Matrix().apply { + preScale(-1f, 1f) + } + val mirrored = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, false) + return HybridImage(mirrored) + } + + override fun mirrorHorizontallyAsync(): Promise { + return Promise.async { mirrorHorizontally() } + } + override fun saveToFileAsync( path: String, format: ImageFormat, diff --git a/packages/react-native-nitro-image/ios/NativeImage.swift b/packages/react-native-nitro-image/ios/NativeImage.swift index 92b454d..bf50d1e 100644 --- a/packages/react-native-nitro-image/ios/NativeImage.swift +++ b/packages/react-native-nitro-image/ios/NativeImage.swift @@ -36,7 +36,7 @@ public extension NativeImage { func toRawPixelData(allowGpu _: Bool?) throws -> RawPixelData { return try uiImage.toRawPixelData() } - func toRawPixelDataAsync(allowGpu: Bool?) throws -> Promise { + func toRawPixelDataAsync(allowGpu: Bool?) -> Promise { return Promise.async { return try self.toRawPixelData(allowGpu: allowGpu) } @@ -46,12 +46,12 @@ public extension NativeImage { return try uiImage.toEncodedImageData(format: format, quality: quality ?? 100) } - func toEncodedImageDataAsync(format: ImageFormat, quality: Double?) throws -> Promise { + func toEncodedImageDataAsync(format: ImageFormat, quality: Double?) -> Promise { return Promise.async { return try self.toEncodedImageData(format: format, quality: quality) } } - + func rotate(degrees: Double, allowFastFlagRotation: Bool?) -> any HybridImageSpec { if allowFastFlagRotation == true, degrees.truncatingRemainder(dividingBy: 90) == 0, @@ -105,7 +105,7 @@ public extension NativeImage { return HybridImage(uiImage: resizedImage) } - func resizeAsync(width: Double, height: Double) throws -> Promise { + func resizeAsync(width: Double, height: Double) -> Promise { return Promise.async { return try self.resize(width: width, height: height) } @@ -133,12 +133,23 @@ public extension NativeImage { return HybridImage(uiImage: croppedUiImage) } - func cropAsync(startX: Double, startY: Double, endX: Double, endY: Double) throws -> Promise { + func cropAsync(startX: Double, startY: Double, endX: Double, endY: Double) -> Promise { return Promise.async { return try self.crop(startX: startX, startY: startY, endX: endX, endY: endY) } } + func mirrorHorizontally() -> any HybridImageSpec { + let mirrored = uiImage.withHorizontallyFlippedOrientation() + return HybridImage(uiImage: mirrored) + } + + func mirrorHorizontallyAsync() -> Promise { + return Promise.async { + return mirrorHorizontally() + } + } + private func saveImage(to path: String, format: ImageFormat, quality: Double) throws { let data = try uiImage.getData(in: format, quality: quality) guard let url = URL(string: path) else { @@ -147,13 +158,13 @@ public extension NativeImage { try data.write(to: url) } - func saveToFileAsync(path: String, format: ImageFormat, quality: Double?) throws -> Promise { + func saveToFileAsync(path: String, format: ImageFormat, quality: Double?) -> Promise { return Promise.async(.utility) { try self.saveImage(to: path, format: format, quality: quality ?? 100.0) } } - func saveToTemporaryFileAsync(format: ImageFormat, quality: Double?) throws -> Promise { + func saveToTemporaryFileAsync(format: ImageFormat, quality: Double?) -> Promise { return Promise.async(.utility) { let tempDirectory = FileManager.default.temporaryDirectory let fileName = UUID().uuidString @@ -170,12 +181,12 @@ public extension NativeImage { return try ArrayBuffer.copy(data: thumbHash) } - func toThumbHashAsync() throws -> Promise { + func toThumbHashAsync() -> Promise { return Promise.async { return try self.toThumbHash() } } - + func renderInto(image newImage: any HybridImageSpec, x: Double, y: Double, width: Double, height: Double) throws -> any HybridImageSpec { guard let newImage = newImage as? NativeImage else { throw RuntimeError.error(withMessage: "The given image (\(newImage)) is not a `NativeImage`!") @@ -186,7 +197,7 @@ public extension NativeImage { let renderedImage = renderer.image { context in // 2. Render our own image (copy) self.uiImage.draw(at: .zero) - + // 3. Render the new image into our copy let rect = CGRect(x: x, y: y, width: width, height: height) newImage.uiImage.draw(in: rect) @@ -194,8 +205,8 @@ public extension NativeImage { // 4. Wrap the resulting UIImage in a HybridImage return HybridImage(uiImage: renderedImage) } - - func renderIntoAsync(image newImage: any HybridImageSpec, x: Double, y: Double, width: Double, height: Double) throws -> Promise { + + func renderIntoAsync(image newImage: any HybridImageSpec, x: Double, y: Double, width: Double, height: Double) -> Promise { return Promise.async { return try self.renderInto(image: newImage, x: x, y: y, width: width, height: height) } diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.cpp b/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.cpp index 68ce41d..2afdd85 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.cpp +++ b/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.cpp @@ -190,6 +190,27 @@ namespace margelo::nitro::image { return __promise; }(); } + std::shared_ptr JHybridImageSpec::mirrorHorizontally() { + static const auto method = javaClassStatic()->getMethod()>("mirrorHorizontally"); + auto __result = method(_javaPart); + return __result->cthis()->shared_cast(); + } + std::shared_ptr>> JHybridImageSpec::mirrorHorizontallyAsync() { + static const auto method = javaClassStatic()->getMethod()>("mirrorHorizontallyAsync"); + auto __result = method(_javaPart); + return [&]() { + auto __promise = Promise>::create(); + __result->cthis()->addOnResolvedListener([=](const jni::alias_ref& __boxedResult) { + auto __result = jni::static_ref_cast(__boxedResult); + __promise->resolve(__result->cthis()->shared_cast()); + }); + __result->cthis()->addOnRejectedListener([=](const jni::alias_ref& __throwable) { + jni::JniException __jniError(__throwable); + __promise->reject(std::make_exception_ptr(__jniError)); + }); + return __promise; + }(); + } std::shared_ptr> JHybridImageSpec::saveToFileAsync(const std::string& path, ImageFormat format, std::optional quality) { static const auto method = javaClassStatic()->getMethod(jni::alias_ref /* path */, jni::alias_ref /* format */, jni::alias_ref /* quality */)>("saveToFileAsync"); auto __result = method(_javaPart, jni::make_jstring(path), JImageFormat::fromCpp(format), quality.has_value() ? jni::JDouble::valueOf(quality.value()) : nullptr); diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.hpp b/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.hpp index 095794c..e51a7a6 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.hpp +++ b/packages/react-native-nitro-image/nitrogen/generated/android/c++/JHybridImageSpec.hpp @@ -66,6 +66,8 @@ namespace margelo::nitro::image { std::shared_ptr>> rotateAsync(double degrees, std::optional allowFastFlagRotation) override; std::shared_ptr crop(double startX, double startY, double endX, double endY) override; std::shared_ptr>> cropAsync(double startX, double startY, double endX, double endY) override; + std::shared_ptr mirrorHorizontally() override; + std::shared_ptr>> mirrorHorizontallyAsync() override; std::shared_ptr> saveToFileAsync(const std::string& path, ImageFormat format, std::optional quality) override; std::shared_ptr> saveToTemporaryFileAsync(ImageFormat format, std::optional quality) override; std::shared_ptr toThumbHash() override; diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/HybridImageSpec.kt b/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/HybridImageSpec.kt index c5ae296..ba08015 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/HybridImageSpec.kt +++ b/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/HybridImageSpec.kt @@ -93,6 +93,14 @@ abstract class HybridImageSpec: HybridObject() { @Keep abstract fun cropAsync(startX: Double, startY: Double, endX: Double, endY: Double): Promise + @DoNotStrip + @Keep + abstract fun mirrorHorizontally(): HybridImageSpec + + @DoNotStrip + @Keep + abstract fun mirrorHorizontallyAsync(): Promise + @DoNotStrip @Keep abstract fun saveToFileAsync(path: String, format: ImageFormat, quality: Double?): Promise diff --git a/packages/react-native-nitro-image/nitrogen/generated/ios/c++/HybridImageSpecSwift.hpp b/packages/react-native-nitro-image/nitrogen/generated/ios/c++/HybridImageSpecSwift.hpp index 2eae671..665ca25 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/ios/c++/HybridImageSpecSwift.hpp +++ b/packages/react-native-nitro-image/nitrogen/generated/ios/c++/HybridImageSpecSwift.hpp @@ -172,6 +172,22 @@ namespace margelo::nitro::image { auto __value = std::move(__result.value()); return __value; } + inline std::shared_ptr mirrorHorizontally() override { + auto __result = _swiftPart.mirrorHorizontally(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } + inline std::shared_ptr>> mirrorHorizontallyAsync() override { + auto __result = _swiftPart.mirrorHorizontallyAsync(); + if (__result.hasError()) [[unlikely]] { + std::rethrow_exception(__result.error()); + } + auto __value = std::move(__result.value()); + return __value; + } inline std::shared_ptr> saveToFileAsync(const std::string& path, ImageFormat format, std::optional quality) override { auto __result = _swiftPart.saveToFileAsync(path, static_cast(format), quality); if (__result.hasError()) [[unlikely]] { diff --git a/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec.swift b/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec.swift index ac62d35..68c06f1 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec.swift +++ b/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec.swift @@ -24,6 +24,8 @@ public protocol HybridImageSpec_protocol: HybridObject { func rotateAsync(degrees: Double, allowFastFlagRotation: Bool?) throws -> Promise<(any HybridImageSpec)> func crop(startX: Double, startY: Double, endX: Double, endY: Double) throws -> (any HybridImageSpec) func cropAsync(startX: Double, startY: Double, endX: Double, endY: Double) throws -> Promise<(any HybridImageSpec)> + func mirrorHorizontally() throws -> (any HybridImageSpec) + func mirrorHorizontallyAsync() throws -> Promise<(any HybridImageSpec)> func saveToFileAsync(path: String, format: ImageFormat, quality: Double?) throws -> Promise func saveToTemporaryFileAsync(format: ImageFormat, quality: Double?) throws -> Promise func toThumbHash() throws -> ArrayBuffer diff --git a/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec_cxx.swift b/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec_cxx.swift index 7cefc12..363ce37 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec_cxx.swift +++ b/packages/react-native-nitro-image/nitrogen/generated/ios/swift/HybridImageSpec_cxx.swift @@ -351,6 +351,43 @@ open class HybridImageSpec_cxx { } } + @inline(__always) + public final func mirrorHorizontally() -> bridge.Result_std__shared_ptr_HybridImageSpec__ { + do { + let __result = try self.__implementation.mirrorHorizontally() + let __resultCpp = { () -> bridge.std__shared_ptr_HybridImageSpec_ in + let __cxxWrapped = __result.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }() + return bridge.create_Result_std__shared_ptr_HybridImageSpec__(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_HybridImageSpec__(__exceptionPtr) + } + } + + @inline(__always) + public final func mirrorHorizontallyAsync() -> bridge.Result_std__shared_ptr_Promise_std__shared_ptr_HybridImageSpec____ { + do { + let __result = try self.__implementation.mirrorHorizontallyAsync() + let __resultCpp = { () -> bridge.std__shared_ptr_Promise_std__shared_ptr_HybridImageSpec___ in + let __promise = bridge.create_std__shared_ptr_Promise_std__shared_ptr_HybridImageSpec___() + let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_std__shared_ptr_HybridImageSpec___(__promise) + __result + .then({ __result in __promiseHolder.resolve({ () -> bridge.std__shared_ptr_HybridImageSpec_ in + let __cxxWrapped = __result.getCxxWrapper() + return __cxxWrapped.getCxxPart() + }()) }) + .catch({ __error in __promiseHolder.reject(__error.toCpp()) }) + return __promise + }() + return bridge.create_Result_std__shared_ptr_Promise_std__shared_ptr_HybridImageSpec____(__resultCpp) + } catch (let __error) { + let __exceptionPtr = __error.toCpp() + return bridge.create_Result_std__shared_ptr_Promise_std__shared_ptr_HybridImageSpec____(__exceptionPtr) + } + } + @inline(__always) public final func saveToFileAsync(path: std.string, format: Int32, quality: bridge.std__optional_double_) -> bridge.Result_std__shared_ptr_Promise_void___ { do { diff --git a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.cpp b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.cpp index a46f6d6..8a8f95e 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.cpp +++ b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.cpp @@ -26,6 +26,8 @@ namespace margelo::nitro::image { prototype.registerHybridMethod("rotateAsync", &HybridImageSpec::rotateAsync); prototype.registerHybridMethod("crop", &HybridImageSpec::crop); prototype.registerHybridMethod("cropAsync", &HybridImageSpec::cropAsync); + prototype.registerHybridMethod("mirrorHorizontally", &HybridImageSpec::mirrorHorizontally); + prototype.registerHybridMethod("mirrorHorizontallyAsync", &HybridImageSpec::mirrorHorizontallyAsync); prototype.registerHybridMethod("saveToFileAsync", &HybridImageSpec::saveToFileAsync); prototype.registerHybridMethod("saveToTemporaryFileAsync", &HybridImageSpec::saveToTemporaryFileAsync); prototype.registerHybridMethod("toThumbHash", &HybridImageSpec::toThumbHash); diff --git a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.hpp b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.hpp index e5cec5f..954f77d 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.hpp +++ b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/HybridImageSpec.hpp @@ -74,6 +74,8 @@ namespace margelo::nitro::image { virtual std::shared_ptr>> rotateAsync(double degrees, std::optional allowFastFlagRotation) = 0; virtual std::shared_ptr crop(double startX, double startY, double endX, double endY) = 0; virtual std::shared_ptr>> cropAsync(double startX, double startY, double endX, double endY) = 0; + virtual std::shared_ptr mirrorHorizontally() = 0; + virtual std::shared_ptr>> mirrorHorizontallyAsync() = 0; virtual std::shared_ptr> saveToFileAsync(const std::string& path, ImageFormat format, std::optional quality) = 0; virtual std::shared_ptr> saveToTemporaryFileAsync(ImageFormat format, std::optional quality) = 0; virtual std::shared_ptr toThumbHash() = 0; diff --git a/packages/react-native-nitro-image/src/specs/Image.nitro.ts b/packages/react-native-nitro-image/src/specs/Image.nitro.ts index 5433e98..e3cc971 100644 --- a/packages/react-native-nitro-image/src/specs/Image.nitro.ts +++ b/packages/react-native-nitro-image/src/specs/Image.nitro.ts @@ -155,6 +155,12 @@ export interface Image endY: number, ): Promise + /** + * Mirrors this Image horizontally. Left is now right, right is now left. + */ + mirrorHorizontally(): Image + mirrorHorizontallyAsync(): Promise + /** * Saves this image in the given {@linkcode ImageFormat} to the given {@linkcode path}. * @note If the requested {@linkcode format} is {@linkcode ImageFormat | 'jpg'}, you can use