diff --git a/.vscode/launch.json b/.vscode/launch.json index 4ff0ea3..0ac3b2c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -19,6 +19,26 @@ "preLaunchTask": "swift: Build Release vips-tool", "target": "vips-tool", "configuration": "release" + }, + { + "type": "swift", + "request": "launch", + "args": [], + "cwd": "${workspaceFolder:swift-vips-generator}", + "name": "Debug vips-generator", + "target": "vips-generator", + "configuration": "debug", + "preLaunchTask": "swift: Build Debug vips-generator" + }, + { + "type": "swift", + "request": "launch", + "args": [], + "cwd": "${workspaceFolder:swift-vips-generator}", + "name": "Release vips-generator", + "target": "vips-generator", + "configuration": "release", + "preLaunchTask": "swift: Build Release vips-generator" } ] } \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 026780a..15c965b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,8 +37,8 @@ swift run vips-tool # Build for release swift build -c release -# Generate Swift wrappers from libvips operations (requires PyVIPS) -python3 tools/generate-swift-wrappers.py +# Run the code generator manually (optional - runs automatically during build) +swift run vips-generator --verbose ``` Depending on the environment, swift might be installed in `$HOME/.local/share/swiftly/bin/swift`. @@ -72,13 +72,18 @@ The Swift wrapper mirrors libvips' modular structure in `Sources/VIPS/`: - **Conversion/**: Image format and geometric conversions (resize, rotate, flip, etc.) - **Create/**: Image creation and generation functions - **Draw/**: Drawing operations and compositing -- **Generated/**: Auto-generated Swift wrappers for libvips operations (updated via `tools/generate-swift-wrappers.py`) - **Convolution/**: Convolution and filtering operations - **Histogram/**: Histogram analysis operations - **Morphology/**: Morphological image processing operations - **Resample/**: Image resampling and interpolation - **CvipsShim/**: C interop layer for functionality not directly accessible from Swift (uses C macros and GObject methods) +Additional modules outside `Sources/VIPS/`: + +- **VIPSIntrospection/**: Swift library for introspecting libvips operations at runtime +- **VIPSGenerator/**: Swift-based code generator that produces Swift wrappers from libvips introspection +- **Plugins/VIPSGeneratorPlugin/**: SwiftPM build tool plugin that runs the generator during build + ## Key Development Patterns - Uses swift naming conventions for method names and types. But follows closely the libvips names for easier searchability. @@ -96,14 +101,16 @@ The Swift wrapper mirrors libvips' modular structure in `Sources/VIPS/`: ## Code Generation -The project uses automated code generation to create Swift wrappers: +The project uses a pure Swift code generator integrated as a SwiftPM build plugin: -- **Generator**: `tools/generate-swift-wrappers.py` uses PyVIPS to introspect libvips operations -- **Generated Files**: Located in `Sources/VIPS/Generated/` directory, organized by operation category -- **Requirements**: Requires `pip install pyvips` to run the generator -- **Usage**: Run `python3 tools/generate-swift-wrappers.py` to regenerate wrappers +- **Build Plugin**: `VIPSGeneratorPlugin` automatically runs during `swift build` when outputs are missing +- **Generator**: `vips-generator` executable uses `VIPSIntrospection` to query libvips operations at runtime +- **Generated Files**: Created in the plugin work directory during build, organized by operation category +- **Manual Usage**: Run `swift run vips-generator --verbose` to regenerate (or `--dry-run` to preview) - **Convention**: Generated code follows Swift naming conventions while preserving libvips operation names for searchability +The generator introspects libvips directly at build time, ensuring wrappers match the installed libvips version. + ## Testing Framework - **Framework**: Uses Swift Testing (not XCTest) for modern Swift testing infrastructure @@ -129,6 +136,7 @@ Check `docs/operations_todo.md` for current implementation roadmap. Arithmetic o ## Swift 6 Compatibility +- **Tools Version**: Requires Swift 6.2+ (`swift-tools-version:6.2`) - **Language Mode**: Built with Swift 6 language mode enabled (`swiftLanguageModes: [.v6]`) -- **Concurrency**: Ready for strict concurrency checking -- **Dependencies**: Uses swift-log for logging functionality \ No newline at end of file +- **Concurrency**: Ready for strict concurrency checking with experimental features enabled +- **Dependencies**: Uses swift-log for logging and swift-subprocess for process execution \ No newline at end of file diff --git a/Package.resolved b/Package.resolved index 8cd1204..5b69f8b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "6f8ebbe21765f99ff2c93099048cf3bc17c7dfe4042efb7acc64bfd4f7d06ba0", + "originHash" : "ea6b1fc10e865c33131bb28c7dc8b36c972441e3a4d6e46f86311e458d4b279a", "pins" : [ { "identity" : "swift-log", @@ -9,6 +9,24 @@ "revision" : "ce592ae52f982c847a4efc0dd881cc9eb32d29f2", "version" : "1.6.4" } + }, + { + "identity" : "swift-subprocess", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-subprocess.git", + "state" : { + "revision" : "44922dfe46380cd354ca4b0208e717a3e92b13dd", + "version" : "0.2.1" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system", + "state" : { + "revision" : "395a77f0aa927f0ff73941d7ac35f2b46d47c9db", + "version" : "1.6.3" + } } ], "version" : 3 diff --git a/Package.swift b/Package.swift index 34fe01a..fe55675 100644 --- a/Package.swift +++ b/Package.swift @@ -9,12 +9,15 @@ let package = Package( products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. .library(name: "VIPS", targets: ["VIPS"]), + .library(name: "VIPSIntrospection", targets: ["VIPSIntrospection"]), + .executable(name: "vips-generator", targets: ["vips-generator"]), ], traits: [ "FoundationSupport", ], dependencies: [ - .package(url: "https://github.com/apple/swift-log.git", from: "1.6.0") + .package(url: "https://github.com/apple/swift-log.git", from: "1.6.0"), + .package(url: "https://github.com/swiftlang/swift-subprocess.git", from: "0.2.1"), ], targets: [ .systemLibrary(name: "Cvips", @@ -24,6 +27,12 @@ let package = Package( dependencies: [ "Cvips" ]), + // Build tool plugin that generates Swift wrappers from libvips introspection + .plugin( + name: "VIPSGeneratorPlugin", + capability: .buildTool(), + dependencies: ["vips-generator"] + ), .target( name: "VIPS", dependencies: [ @@ -35,7 +44,23 @@ let package = Package( .enableUpcomingFeature("NonisolatedNonsendingByDefault"), .enableUpcomingFeature("InferIsolatedConformances"), .enableExperimentalFeature("Lifetimes") + ], + plugins: [ + .plugin(name: "VIPSGeneratorPlugin") ]), + .target( + name: "VIPSIntrospection", + dependencies: [ + "Cvips", + "CvipsShim" + ]), + .executableTarget(name: "vips-generator", + dependencies: [ + "VIPSIntrospection", + .product(name: "Subprocess", package: "swift-subprocess") + ], + path: "Sources/VIPSGenerator" + ), .executableTarget(name: "vips-tool", dependencies: ["VIPS", "Cvips"] ), diff --git a/Pipfile b/Pipfile deleted file mode 100644 index d61ea53..0000000 --- a/Pipfile +++ /dev/null @@ -1,11 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] - -[dev-packages] - -[requires] -python_version = "3.13" diff --git a/Plugins/VIPSGeneratorPlugin/plugin.swift b/Plugins/VIPSGeneratorPlugin/plugin.swift new file mode 100644 index 0000000..ca0d885 --- /dev/null +++ b/Plugins/VIPSGeneratorPlugin/plugin.swift @@ -0,0 +1,84 @@ +// +// plugin.swift +// VIPSGeneratorPlugin +// +// Build tool plugin that generates Swift wrappers for libvips operations +// + +import Foundation +import PackagePlugin + +@main +struct VIPSGeneratorPlugin: BuildToolPlugin { + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { + // Only apply to the VIPS target + guard target.name == "VIPS" else { + return [] + } + + // Get the generator tool + let generator = try context.tool(named: "vips-generator") + + // Output directory for generated files (using URL-based API) + let outputDir = context.pluginWorkDirectoryURL.appending(path: "Generated") + + // Discover output files by running the generator with --list-outputs + let outputFiles = try discoverOutputFiles( + generator: generator.url, + outputDir: outputDir + ) + + // Use a build command - runs when outputs are missing or inputs changed + // Since there are no file inputs (we introspect libvips at runtime), + // this will run when outputs are missing (first build after clone) + return [ + .buildCommand( + displayName: "Generating VIPS Swift wrappers", + executable: generator.url, + arguments: [ + "--output-dir", outputDir.path(), + "--verbose" + ], + inputFiles: [], + outputFiles: outputFiles + ) + ] + } + + /// Discover output files by running the generator with --list-outputs + private func discoverOutputFiles(generator: URL, outputDir: URL) throws -> [URL] { + let process = Process() + process.executableURL = generator + process.arguments = ["--list-outputs", "--output-dir", outputDir.path()] + + let pipe = Pipe() + process.standardOutput = pipe + process.standardError = Pipe() // Suppress stderr + + try process.run() + process.waitUntilExit() + + guard process.terminationStatus == 0 else { + throw PluginError.generatorFailed(status: process.terminationStatus) + } + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + guard let output = String(data: data, encoding: .utf8) else { + throw PluginError.invalidGeneratorOutput + } + + // Parse output - one file path per line + let filePaths = output + .split(separator: "\n") + .map { String($0).trimmingCharacters(in: .whitespaces) } + .filter { !$0.isEmpty } + .map { URL(fileURLWithPath: $0) } + + return filePaths + } +} + +enum PluginError: Error { + case generatorFailed(status: Int32) + case invalidGeneratorOutput +} diff --git a/README.md b/README.md index d5c4201..2d7596e 100644 --- a/README.md +++ b/README.md @@ -290,7 +290,7 @@ swift build -c release ## Requirements -- Swift 6.0+ +- Swift 6.2+ - libvips 8.12+ installed on system - Linux or macOS @@ -299,12 +299,13 @@ swift build -c release SwiftVIPS mirrors libvips' modular structure: - **`Core/`**: Initialization, memory management, fundamental types -- **`Arithmetic/`**: Mathematical operations and operator overloading +- **`Arithmetic/`**: Mathematical operations and operator overloading - **`Conversion/`**: Image transformations and geometric operations - **`Foreign/`**: File format support (organized by format) -- **`Generated/`**: Auto-generated bindings for libvips operations - **`CvipsShim/`**: C interoperability layer +Code generation uses a SwiftPM build plugin that automatically generates Swift wrappers from libvips introspection at build time. + ## Performance SwiftVIPS inherits libvips' performance characteristics: diff --git a/Sources/CvipsShim/CvipsShim.c b/Sources/CvipsShim/CvipsShim.c index 0fcdacf..ca37b22 100644 --- a/Sources/CvipsShim/CvipsShim.c +++ b/Sources/CvipsShim/CvipsShim.c @@ -167,4 +167,142 @@ gboolean shim_vips_source_decode_status(VipsSource *source) { gboolean shim_vips_source_is_pipe(VipsSource *source) { return source->is_pipe; +} + +// Callback for collecting operation types recursively +static void* collect_operation_type(GType type, void* a, void* b) { + GArray* types = (GArray*)a; + const char* nickname = vips_nickname_find(type); + + if (nickname) { + g_array_append_val(types, type); + } + + // Recursively walk children to get all operations in the hierarchy + vips_type_map(type, collect_operation_type, types, NULL); + + return NULL; +} + +// Get all operation types +GType* shim_get_all_operation_types(int* count) { + GArray* types = g_array_new(FALSE, FALSE, sizeof(GType)); + + // Map over all VipsOperation subclasses recursively + vips_type_map(vips_operation_get_type(), collect_operation_type, types, NULL); + + *count = types->len; + + // Convert GArray to C array - caller must free + GType* result = g_malloc(sizeof(GType) * types->len); + for (guint i = 0; i < types->len; i++) { + result[i] = g_array_index(types, GType, i); + } + + g_array_free(types, TRUE); + return result; +} + +// Get operation info by nickname +ShimOperationInfo* shim_get_operation_info(const char* nickname) { + // Find the operation class by nickname + const VipsObjectClass* object_class = vips_class_find("VipsOperation", nickname); + if (!object_class) { + return NULL; + } + + GType operation_type = G_OBJECT_CLASS_TYPE(object_class); + VipsOperationClass* operation_class = VIPS_OPERATION_CLASS(object_class); + + ShimOperationInfo* info = g_malloc(sizeof(ShimOperationInfo)); + info->nickname = g_strdup(object_class->nickname ? object_class->nickname : nickname); + info->description = g_strdup(object_class->description ? object_class->description : ""); + info->operation_type = operation_type; + info->flags = operation_class ? operation_class->flags : 0; + + return info; +} + +// Callback for collecting parameter info +typedef struct { + GArray* params; +} CollectParamsData; + +static void* collect_parameter_info(VipsObjectClass* object_class, + GParamSpec* pspec, + VipsArgumentClass* argument_class, + void* a, void* b) { + CollectParamsData* data = (CollectParamsData*)a; + + ShimParameterInfo param_info; + param_info.name = g_strdup(g_param_spec_get_name(pspec)); + param_info.description = g_strdup(g_param_spec_get_blurb(pspec)); + param_info.parameter_type = G_PARAM_SPEC_VALUE_TYPE(pspec); + param_info.flags = argument_class->flags; + param_info.priority = argument_class->priority; + + g_array_append_val(data->params, param_info); + return NULL; +} + +// Get parameters for an operation +ShimParameterInfo* shim_get_operation_parameters(const char* nickname, int* count) { + // Find the operation class by nickname + const VipsObjectClass* object_class = vips_class_find("VipsOperation", nickname); + if (!object_class) { + *count = 0; + return NULL; + } + + CollectParamsData data; + data.params = g_array_new(FALSE, FALSE, sizeof(ShimParameterInfo)); + + // Collect all arguments (cast away const - vips_argument_class_map doesn't modify the class) + vips_argument_class_map((VipsObjectClass*)object_class, collect_parameter_info, &data, NULL); + + *count = data.params->len; + + // Convert to C array - caller must free + ShimParameterInfo* result = g_malloc(sizeof(ShimParameterInfo) * data.params->len); + for (guint i = 0; i < data.params->len; i++) { + result[i] = g_array_index(data.params, ShimParameterInfo, i); + } + + g_array_free(data.params, TRUE); + return result; +} + +// Free allocated arrays +void shim_free_operation_types(GType* types) { + g_free(types); +} + +void shim_free_operation_info(ShimOperationInfo* info) { + if (info) { + g_free((char*)info->nickname); + g_free((char*)info->description); + g_free(info); + } +} + +void shim_free_parameter_info(ShimParameterInfo* params) { + // Note: We don't free individual strings here as they're owned by GLib + g_free(params); +} + +// Helper functions for type introspection +const char* shim_gtype_name(GType gtype) { + return g_type_name(gtype); +} + +GType shim_gtype_fundamental(GType gtype) { + return g_type_fundamental(gtype); +} + +gboolean shim_gtype_is_enum(GType gtype) { + return G_TYPE_IS_ENUM(gtype); +} + +gboolean shim_gtype_is_flags(GType gtype) { + return G_TYPE_IS_FLAGS(gtype); } \ No newline at end of file diff --git a/Sources/CvipsShim/include/CvipsShim.h b/Sources/CvipsShim/include/CvipsShim.h index 31655f5..274a096 100644 --- a/Sources/CvipsShim/include/CvipsShim.h +++ b/Sources/CvipsShim/include/CvipsShim.h @@ -106,4 +106,40 @@ gboolean shim_vips_source_is_pipe(VipsSource *source); #endif #endif +// Introspection functions for operation discovery +typedef struct { + const char* nickname; + const char* description; + GType operation_type; + int flags; +} ShimOperationInfo; + +typedef struct { + const char* name; + const char* description; + GType parameter_type; + int flags; + int priority; +} ShimParameterInfo; + +// Get all operation types and count +GType* shim_get_all_operation_types(int* count); + +// Get operation info by nickname +ShimOperationInfo* shim_get_operation_info(const char* nickname); + +// Get parameters for an operation +ShimParameterInfo* shim_get_operation_parameters(const char* nickname, int* count); + +// Free allocated arrays +void shim_free_operation_types(GType* types); +void shim_free_operation_info(ShimOperationInfo* info); +void shim_free_parameter_info(ShimParameterInfo* params); + +// Helper functions for type introspection +const char* shim_gtype_name(GType gtype); +GType shim_gtype_fundamental(GType gtype); +gboolean shim_gtype_is_enum(GType gtype); +gboolean shim_gtype_is_flags(GType gtype); + #endif /* C_vips_shim_h */ diff --git a/Sources/VIPS/Conversion/conversion.swift b/Sources/VIPS/Conversion/conversion.swift index 630fb8c..f97982a 100644 --- a/Sources/VIPS/Conversion/conversion.swift +++ b/Sources/VIPS/Conversion/conversion.swift @@ -3,6 +3,17 @@ extension VIPSImage { try self.cast(format: format, shift: shift) } + /// Alias for extractArea - crop an image + /// - Parameters: + /// - left: Left edge of extract area + /// - top: Top edge of extract area + /// - width: Width of extract area + /// - height: Height of extract area + /// - Returns: Cropped image + public func crop(left: Int, top: Int, width: Int, height: Int) throws -> VIPSImage { + try extractArea(left: left, top: top, width: width, height: height) + } + /// See VIPSImage.bandjoin(`in`:) public func bandjoin(_ other: [VIPSImage]) throws -> VIPSImage { return try VIPSImage { out in diff --git a/Sources/VIPS/Generated/Foreign/foreign_gif.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_gif.generated.swift deleted file mode 100644 index 5caa2ce..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_gif.generated.swift +++ /dev/null @@ -1,430 +0,0 @@ -// -// foreign_gif.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save as gif - /// - /// - Parameters: - /// - filename: Filename to save to - /// - dither: Amount of dithering - /// - effort: Quantisation effort - /// - bitdepth: Number of bits per pixel - /// - interframeMaxerror: Maximum inter-frame error for transparency - /// - reuse: Reuse palette from input - /// - interpaletteMaxerror: Maximum inter-palette error for palette reusage - /// - interlace: Generate an interlaced (progressive) GIF - /// - keepDuplicateFrames: Keep duplicate frames in the output instead of combining them - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func gifsave( - filename: String, - dither: Double? = nil, - effort: Int? = nil, - bitdepth: Int? = nil, - interframeMaxerror: Double? = nil, - reuse: Bool? = nil, - interpaletteMaxerror: Double? = nil, - interlace: Bool? = nil, - keepDuplicateFrames: Bool? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let dither = dither { - opt.set("dither", value: dither) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let interframeMaxerror = interframeMaxerror { - opt.set("interframe_maxerror", value: interframeMaxerror) - } - if let reuse = reuse { - opt.set("reuse", value: reuse) - } - if let interpaletteMaxerror = interpaletteMaxerror { - opt.set("interpalette_maxerror", value: interpaletteMaxerror) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let keepDuplicateFrames = keepDuplicateFrames { - opt.set("keep_duplicate_frames", value: keepDuplicateFrames) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("gifsave", options: &opt) - } - - /// Save as gif - /// - /// - Parameters: - /// - dither: Amount of dithering - /// - effort: Quantisation effort - /// - bitdepth: Number of bits per pixel - /// - interframeMaxerror: Maximum inter-frame error for transparency - /// - reuse: Reuse palette from input - /// - interpaletteMaxerror: Maximum inter-palette error for palette reusage - /// - interlace: Generate an interlaced (progressive) GIF - /// - keepDuplicateFrames: Keep duplicate frames in the output instead of combining them - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func gifsave( - dither: Double? = nil, - effort: Int? = nil, - bitdepth: Int? = nil, - interframeMaxerror: Double? = nil, - reuse: Bool? = nil, - interpaletteMaxerror: Double? = nil, - interlace: Bool? = nil, - keepDuplicateFrames: Bool? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let dither = dither { - opt.set("dither", value: dither) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let interframeMaxerror = interframeMaxerror { - opt.set("interframe_maxerror", value: interframeMaxerror) - } - if let reuse = reuse { - opt.set("reuse", value: reuse) - } - if let interpaletteMaxerror = interpaletteMaxerror { - opt.set("interpalette_maxerror", value: interpaletteMaxerror) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let keepDuplicateFrames = keepDuplicateFrames { - opt.set("keep_duplicate_frames", value: keepDuplicateFrames) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("gifsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from gifsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save as gif - /// - /// - Parameters: - /// - target: Target to save to - /// - dither: Amount of dithering - /// - effort: Quantisation effort - /// - bitdepth: Number of bits per pixel - /// - interframeMaxerror: Maximum inter-frame error for transparency - /// - reuse: Reuse palette from input - /// - interpaletteMaxerror: Maximum inter-palette error for palette reusage - /// - interlace: Generate an interlaced (progressive) GIF - /// - keepDuplicateFrames: Keep duplicate frames in the output instead of combining them - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func gifsave( - target: VIPSTarget, - dither: Double? = nil, - effort: Int? = nil, - bitdepth: Int? = nil, - interframeMaxerror: Double? = nil, - reuse: Bool? = nil, - interpaletteMaxerror: Double? = nil, - interlace: Bool? = nil, - keepDuplicateFrames: Bool? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let dither = dither { - opt.set("dither", value: dither) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let interframeMaxerror = interframeMaxerror { - opt.set("interframe_maxerror", value: interframeMaxerror) - } - if let reuse = reuse { - opt.set("reuse", value: reuse) - } - if let interpaletteMaxerror = interpaletteMaxerror { - opt.set("interpalette_maxerror", value: interpaletteMaxerror) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let keepDuplicateFrames = keepDuplicateFrames { - opt.set("keep_duplicate_frames", value: keepDuplicateFrames) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("gifsave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load gif with libnsgif - /// - /// - Parameters: - /// - filename: Filename to load from - /// - n: Number of pages to load, -1 for all - /// - page: First page to load - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func gifload( - filename: String, - n: Int? = nil, - page: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let n = n { - opt.set("n", value: n) - } - if let page = page { - opt.set("page", value: page) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("gifload", options: &opt) - } - } - - /// Load gif with libnsgif - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - n: Number of pages to load, -1 for all - /// - page: First page to load - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func gifload( - buffer: VIPSBlob, - n: Int? = nil, - page: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let n = n { - opt.set("n", value: n) - } - if let page = page { - opt.set("page", value: page) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("gifload_buffer", options: &opt) - } - } - } - - /// Load gif with libnsgif without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - n: Number of pages to load, -1 for all - /// - page: First page to load - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func gifload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - n: Int? = nil, - page: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try gifload( - buffer: blob, - n: n, - page: page, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load gif from source - /// - /// - Parameters: - /// - source: Source to load from - /// - n: Number of pages to load, -1 for all - /// - page: First page to load - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func gifload( - source: VIPSSource, - n: Int? = nil, - page: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let n = n { - opt.set("n", value: n) - } - if let page = page { - opt.set("page", value: page) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("gifload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_heif.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_heif.generated.swift deleted file mode 100644 index 035fe8a..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_heif.generated.swift +++ /dev/null @@ -1,451 +0,0 @@ -// -// foreign_heif.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save image in heif format - /// - /// - Parameters: - /// - filename: Filename to save to - /// - quality: Q factor - /// - bitdepth: Number of bits per pixel - /// - lossless: Enable lossless compression - /// - compression: Compression format - /// - effort: CPU effort - /// - subsampleMode: Select chroma subsample operation mode - /// - encoder: Select encoder to use - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func heifsave( - filename: String, - quality: Int? = nil, - bitdepth: Int? = nil, - lossless: Bool? = nil, - compression: VipsForeignHeifCompression? = nil, - effort: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - encoder: VipsForeignHeifEncoder? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let quality = quality { - opt.set("Q", value: quality) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let compression = compression { - opt.set("compression", value: compression) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let encoder = encoder { - opt.set("encoder", value: encoder) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("heifsave", options: &opt) - } - - /// Save image in heif format - /// - /// - Parameters: - /// - quality: Q factor - /// - bitdepth: Number of bits per pixel - /// - lossless: Enable lossless compression - /// - compression: Compression format - /// - effort: CPU effort - /// - subsampleMode: Select chroma subsample operation mode - /// - encoder: Select encoder to use - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func heifsave( - quality: Int? = nil, - bitdepth: Int? = nil, - lossless: Bool? = nil, - compression: VipsForeignHeifCompression? = nil, - effort: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - encoder: VipsForeignHeifEncoder? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let quality = quality { - opt.set("Q", value: quality) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let compression = compression { - opt.set("compression", value: compression) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let encoder = encoder { - opt.set("encoder", value: encoder) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("heifsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from heifsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image in heif format - /// - /// - Parameters: - /// - target: Target to save to - /// - quality: Q factor - /// - bitdepth: Number of bits per pixel - /// - lossless: Enable lossless compression - /// - compression: Compression format - /// - effort: CPU effort - /// - subsampleMode: Select chroma subsample operation mode - /// - encoder: Select encoder to use - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func heifsave( - target: VIPSTarget, - quality: Int? = nil, - bitdepth: Int? = nil, - lossless: Bool? = nil, - compression: VipsForeignHeifCompression? = nil, - effort: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - encoder: VipsForeignHeifEncoder? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let quality = quality { - opt.set("Q", value: quality) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let compression = compression { - opt.set("compression", value: compression) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let encoder = encoder { - opt.set("encoder", value: encoder) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("heifsave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load a heif image - /// - /// - Parameters: - /// - filename: Filename to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - thumbnail: Fetch thumbnail image - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func heifload( - filename: String, - page: Int? = nil, - n: Int? = nil, - thumbnail: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let thumbnail = thumbnail { - opt.set("thumbnail", value: thumbnail) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("heifload", options: &opt) - } - } - - /// Load a heif image - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - thumbnail: Fetch thumbnail image - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func heifload( - buffer: VIPSBlob, - page: Int? = nil, - n: Int? = nil, - thumbnail: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let thumbnail = thumbnail { - opt.set("thumbnail", value: thumbnail) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("heifload_buffer", options: &opt) - } - } - } - - /// Load a heif image without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - thumbnail: Fetch thumbnail image - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func heifload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - page: Int? = nil, - n: Int? = nil, - thumbnail: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try heifload( - buffer: blob, - page: page, - n: n, - thumbnail: thumbnail, - unlimited: unlimited, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load a heif image - /// - /// - Parameters: - /// - source: Source to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - thumbnail: Fetch thumbnail image - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func heifload( - source: VIPSSource, - page: Int? = nil, - n: Int? = nil, - thumbnail: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let thumbnail = thumbnail { - opt.set("thumbnail", value: thumbnail) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("heifload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_jpeg.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_jpeg.generated.swift deleted file mode 100644 index 1d911b0..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_jpeg.generated.swift +++ /dev/null @@ -1,540 +0,0 @@ -// -// foreign_jpeg.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save image to jpeg file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - quality: Q factor - /// - optimizeCoding: Compute optimal Huffman coding tables - /// - interlace: Generate an interlaced (progressive) jpeg - /// - trellisQuant: Apply trellis quantisation to each 8x8 block - /// - overshootDeringing: Apply overshooting to samples with extreme values - /// - optimizeScans: Split spectrum of DCT coefficients into separate scans - /// - quantTable: Use predefined quantization table with given index - /// - subsampleMode: Select chroma subsample operation mode - /// - restartInterval: Add restart markers every specified number of mcu - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jpegsave( - filename: String, - quality: Int? = nil, - optimizeCoding: Bool? = nil, - interlace: Bool? = nil, - trellisQuant: Bool? = nil, - overshootDeringing: Bool? = nil, - optimizeScans: Bool? = nil, - quantTable: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - restartInterval: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let quality = quality { - opt.set("Q", value: quality) - } - if let optimizeCoding = optimizeCoding { - opt.set("optimize_coding", value: optimizeCoding) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let trellisQuant = trellisQuant { - opt.set("trellis_quant", value: trellisQuant) - } - if let overshootDeringing = overshootDeringing { - opt.set("overshoot_deringing", value: overshootDeringing) - } - if let optimizeScans = optimizeScans { - opt.set("optimize_scans", value: optimizeScans) - } - if let quantTable = quantTable { - opt.set("quant_table", value: quantTable) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let restartInterval = restartInterval { - opt.set("restart_interval", value: restartInterval) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jpegsave", options: &opt) - } - - /// Save image to jpeg buffer - /// - /// - Parameters: - /// - quality: Q factor - /// - optimizeCoding: Compute optimal Huffman coding tables - /// - interlace: Generate an interlaced (progressive) jpeg - /// - trellisQuant: Apply trellis quantisation to each 8x8 block - /// - overshootDeringing: Apply overshooting to samples with extreme values - /// - optimizeScans: Split spectrum of DCT coefficients into separate scans - /// - quantTable: Use predefined quantization table with given index - /// - subsampleMode: Select chroma subsample operation mode - /// - restartInterval: Add restart markers every specified number of mcu - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jpegsave( - quality: Int? = nil, - optimizeCoding: Bool? = nil, - interlace: Bool? = nil, - trellisQuant: Bool? = nil, - overshootDeringing: Bool? = nil, - optimizeScans: Bool? = nil, - quantTable: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - restartInterval: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let quality = quality { - opt.set("Q", value: quality) - } - if let optimizeCoding = optimizeCoding { - opt.set("optimize_coding", value: optimizeCoding) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let trellisQuant = trellisQuant { - opt.set("trellis_quant", value: trellisQuant) - } - if let overshootDeringing = overshootDeringing { - opt.set("overshoot_deringing", value: overshootDeringing) - } - if let optimizeScans = optimizeScans { - opt.set("optimize_scans", value: optimizeScans) - } - if let quantTable = quantTable { - opt.set("quant_table", value: quantTable) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let restartInterval = restartInterval { - opt.set("restart_interval", value: restartInterval) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("jpegsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from jpegsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to jpeg mime - /// - /// - Parameters: - /// - quality: Q factor - /// - optimizeCoding: Compute optimal Huffman coding tables - /// - interlace: Generate an interlaced (progressive) jpeg - /// - trellisQuant: Apply trellis quantisation to each 8x8 block - /// - overshootDeringing: Apply overshooting to samples with extreme values - /// - optimizeScans: Split spectrum of DCT coefficients into separate scans - /// - quantTable: Use predefined quantization table with given index - /// - subsampleMode: Select chroma subsample operation mode - /// - restartInterval: Add restart markers every specified number of mcu - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jpegsaveMime( - quality: Int? = nil, - optimizeCoding: Bool? = nil, - interlace: Bool? = nil, - trellisQuant: Bool? = nil, - overshootDeringing: Bool? = nil, - optimizeScans: Bool? = nil, - quantTable: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - restartInterval: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - if let quality = quality { - opt.set("Q", value: quality) - } - if let optimizeCoding = optimizeCoding { - opt.set("optimize_coding", value: optimizeCoding) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let trellisQuant = trellisQuant { - opt.set("trellis_quant", value: trellisQuant) - } - if let overshootDeringing = overshootDeringing { - opt.set("overshoot_deringing", value: overshootDeringing) - } - if let optimizeScans = optimizeScans { - opt.set("optimize_scans", value: optimizeScans) - } - if let quantTable = quantTable { - opt.set("quant_table", value: quantTable) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let restartInterval = restartInterval { - opt.set("restart_interval", value: restartInterval) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jpegsave_mime", options: &opt) - } - - /// Save image to jpeg target - /// - /// - Parameters: - /// - target: Target to save to - /// - quality: Q factor - /// - optimizeCoding: Compute optimal Huffman coding tables - /// - interlace: Generate an interlaced (progressive) jpeg - /// - trellisQuant: Apply trellis quantisation to each 8x8 block - /// - overshootDeringing: Apply overshooting to samples with extreme values - /// - optimizeScans: Split spectrum of DCT coefficients into separate scans - /// - quantTable: Use predefined quantization table with given index - /// - subsampleMode: Select chroma subsample operation mode - /// - restartInterval: Add restart markers every specified number of mcu - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jpegsave( - target: VIPSTarget, - quality: Int? = nil, - optimizeCoding: Bool? = nil, - interlace: Bool? = nil, - trellisQuant: Bool? = nil, - overshootDeringing: Bool? = nil, - optimizeScans: Bool? = nil, - quantTable: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - restartInterval: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let quality = quality { - opt.set("Q", value: quality) - } - if let optimizeCoding = optimizeCoding { - opt.set("optimize_coding", value: optimizeCoding) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let trellisQuant = trellisQuant { - opt.set("trellis_quant", value: trellisQuant) - } - if let overshootDeringing = overshootDeringing { - opt.set("overshoot_deringing", value: overshootDeringing) - } - if let optimizeScans = optimizeScans { - opt.set("optimize_scans", value: optimizeScans) - } - if let quantTable = quantTable { - opt.set("quant_table", value: quantTable) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let restartInterval = restartInterval { - opt.set("restart_interval", value: restartInterval) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jpegsave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load jpeg from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - shrink: Shrink factor on load - /// - autorotate: Rotate image using exif orientation - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func jpegload( - filename: String, - shrink: Int? = nil, - autorotate: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let shrink = shrink { - opt.set("shrink", value: shrink) - } - if let autorotate = autorotate { - opt.set("autorotate", value: autorotate) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jpegload", options: &opt) - } - } - - /// Load jpeg from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - shrink: Shrink factor on load - /// - autorotate: Rotate image using exif orientation - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func jpegload( - buffer: VIPSBlob, - shrink: Int? = nil, - autorotate: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let shrink = shrink { - opt.set("shrink", value: shrink) - } - if let autorotate = autorotate { - opt.set("autorotate", value: autorotate) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jpegload_buffer", options: &opt) - } - } - } - - /// Load jpeg from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - shrink: Shrink factor on load - /// - autorotate: Rotate image using exif orientation - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func jpegload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - shrink: Int? = nil, - autorotate: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try jpegload( - buffer: blob, - shrink: shrink, - autorotate: autorotate, - unlimited: unlimited, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load image from jpeg source - /// - /// - Parameters: - /// - source: Source to load from - /// - shrink: Shrink factor on load - /// - autorotate: Rotate image using exif orientation - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func jpegload( - source: VIPSSource, - shrink: Int? = nil, - autorotate: Bool? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let shrink = shrink { - opt.set("shrink", value: shrink) - } - if let autorotate = autorotate { - opt.set("autorotate", value: autorotate) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jpegload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_other.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_other.generated.swift deleted file mode 100644 index 4d9694d..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_other.generated.swift +++ /dev/null @@ -1,2878 +0,0 @@ -// -// foreign_other.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save image to csv - /// - /// - Parameters: - /// - filename: Filename to save to - /// - separator: Separator characters - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func csvsave( - filename: String, - separator: String? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let separator = separator { - opt.set("separator", value: separator) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("csvsave", options: &opt) - } - - /// Save image to csv - /// - /// - Parameters: - /// - target: Target to save to - /// - separator: Separator characters - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func csvsave( - target: VIPSTarget, - separator: String? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let separator = separator { - opt.set("separator", value: separator) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("csvsave_target", options: &opt) - } - - /// Save image to deepzoom file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - imagename: Image name - /// - layout: Directory layout - /// - suffix: Filename suffix for tiles - /// - overlap: Tile overlap in pixels - /// - tileSize: Tile size in pixels - /// - centre: Center image in tile - /// - depth: Pyramid depth - /// - angle: Rotate image during save - /// - container: Pyramid container type - /// - compression: ZIP deflate compression level - /// - regionShrink: Method to shrink regions - /// - skipBlanks: Skip tiles which are nearly equal to the background - /// - id: Resource ID - /// - quality: Q factor - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func dzsave( - filename: String, - imagename: String? = nil, - layout: VipsForeignDzLayout? = nil, - suffix: String? = nil, - overlap: Int? = nil, - tileSize: Int? = nil, - centre: Bool? = nil, - depth: VipsForeignDzDepth? = nil, - angle: VipsAngle? = nil, - container: VipsForeignDzContainer? = nil, - compression: Int? = nil, - regionShrink: VipsRegionShrink? = nil, - skipBlanks: Int? = nil, - id: String? = nil, - quality: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let imagename = imagename { - opt.set("imagename", value: imagename) - } - if let layout = layout { - opt.set("layout", value: layout) - } - if let suffix = suffix { - opt.set("suffix", value: suffix) - } - if let overlap = overlap { - opt.set("overlap", value: overlap) - } - if let tileSize = tileSize { - opt.set("tile_size", value: tileSize) - } - if let centre = centre { - opt.set("centre", value: centre) - } - if let depth = depth { - opt.set("depth", value: depth) - } - if let angle = angle { - opt.set("angle", value: angle) - } - if let container = container { - opt.set("container", value: container) - } - if let compression = compression { - opt.set("compression", value: compression) - } - if let regionShrink = regionShrink { - opt.set("region_shrink", value: regionShrink) - } - if let skipBlanks = skipBlanks { - opt.set("skip_blanks", value: skipBlanks) - } - if let id = id { - opt.set("id", value: id) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("dzsave", options: &opt) - } - - /// Save image to dz buffer - /// - /// - Parameters: - /// - imagename: Image name - /// - layout: Directory layout - /// - suffix: Filename suffix for tiles - /// - overlap: Tile overlap in pixels - /// - tileSize: Tile size in pixels - /// - centre: Center image in tile - /// - depth: Pyramid depth - /// - angle: Rotate image during save - /// - container: Pyramid container type - /// - compression: ZIP deflate compression level - /// - regionShrink: Method to shrink regions - /// - skipBlanks: Skip tiles which are nearly equal to the background - /// - id: Resource ID - /// - quality: Q factor - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func dzsave( - imagename: String? = nil, - layout: VipsForeignDzLayout? = nil, - suffix: String? = nil, - overlap: Int? = nil, - tileSize: Int? = nil, - centre: Bool? = nil, - depth: VipsForeignDzDepth? = nil, - angle: VipsAngle? = nil, - container: VipsForeignDzContainer? = nil, - compression: Int? = nil, - regionShrink: VipsRegionShrink? = nil, - skipBlanks: Int? = nil, - id: String? = nil, - quality: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let imagename = imagename { - opt.set("imagename", value: imagename) - } - if let layout = layout { - opt.set("layout", value: layout) - } - if let suffix = suffix { - opt.set("suffix", value: suffix) - } - if let overlap = overlap { - opt.set("overlap", value: overlap) - } - if let tileSize = tileSize { - opt.set("tile_size", value: tileSize) - } - if let centre = centre { - opt.set("centre", value: centre) - } - if let depth = depth { - opt.set("depth", value: depth) - } - if let angle = angle { - opt.set("angle", value: angle) - } - if let container = container { - opt.set("container", value: container) - } - if let compression = compression { - opt.set("compression", value: compression) - } - if let regionShrink = regionShrink { - opt.set("region_shrink", value: regionShrink) - } - if let skipBlanks = skipBlanks { - opt.set("skip_blanks", value: skipBlanks) - } - if let id = id { - opt.set("id", value: id) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("dzsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from dzsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to deepzoom target - /// - /// - Parameters: - /// - target: Target to save to - /// - imagename: Image name - /// - layout: Directory layout - /// - suffix: Filename suffix for tiles - /// - overlap: Tile overlap in pixels - /// - tileSize: Tile size in pixels - /// - centre: Center image in tile - /// - depth: Pyramid depth - /// - angle: Rotate image during save - /// - container: Pyramid container type - /// - compression: ZIP deflate compression level - /// - regionShrink: Method to shrink regions - /// - skipBlanks: Skip tiles which are nearly equal to the background - /// - id: Resource ID - /// - quality: Q factor - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func dzsave( - target: VIPSTarget, - imagename: String? = nil, - layout: VipsForeignDzLayout? = nil, - suffix: String? = nil, - overlap: Int? = nil, - tileSize: Int? = nil, - centre: Bool? = nil, - depth: VipsForeignDzDepth? = nil, - angle: VipsAngle? = nil, - container: VipsForeignDzContainer? = nil, - compression: Int? = nil, - regionShrink: VipsRegionShrink? = nil, - skipBlanks: Int? = nil, - id: String? = nil, - quality: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let imagename = imagename { - opt.set("imagename", value: imagename) - } - if let layout = layout { - opt.set("layout", value: layout) - } - if let suffix = suffix { - opt.set("suffix", value: suffix) - } - if let overlap = overlap { - opt.set("overlap", value: overlap) - } - if let tileSize = tileSize { - opt.set("tile_size", value: tileSize) - } - if let centre = centre { - opt.set("centre", value: centre) - } - if let depth = depth { - opt.set("depth", value: depth) - } - if let angle = angle { - opt.set("angle", value: angle) - } - if let container = container { - opt.set("container", value: container) - } - if let compression = compression { - opt.set("compression", value: compression) - } - if let regionShrink = regionShrink { - opt.set("region_shrink", value: regionShrink) - } - if let skipBlanks = skipBlanks { - opt.set("skip_blanks", value: skipBlanks) - } - if let id = id { - opt.set("id", value: id) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("dzsave_target", options: &opt) - } - - /// Save image to fits file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func fitssave( - filename: String, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("fitssave", options: &opt) - } - - /// Save image in jpeg2000 format - /// - /// - Parameters: - /// - filename: Filename to save to - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - lossless: Enable lossless compression - /// - quality: Q factor - /// - subsampleMode: Select chroma subsample operation mode - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jp2ksave( - filename: String, - tileWidth: Int? = nil, - tileHeight: Int? = nil, - lossless: Bool? = nil, - quality: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jp2ksave", options: &opt) - } - - /// Save image in jpeg2000 format - /// - /// - Parameters: - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - lossless: Enable lossless compression - /// - quality: Q factor - /// - subsampleMode: Select chroma subsample operation mode - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jp2ksave( - tileWidth: Int? = nil, - tileHeight: Int? = nil, - lossless: Bool? = nil, - quality: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("jp2ksave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from jp2ksave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image in jpeg2000 format - /// - /// - Parameters: - /// - target: Target to save to - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - lossless: Enable lossless compression - /// - quality: Q factor - /// - subsampleMode: Select chroma subsample operation mode - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jp2ksave( - target: VIPSTarget, - tileWidth: Int? = nil, - tileHeight: Int? = nil, - lossless: Bool? = nil, - quality: Int? = nil, - subsampleMode: VipsForeignSubsample? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let subsampleMode = subsampleMode { - opt.set("subsample_mode", value: subsampleMode) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jp2ksave_target", options: &opt) - } - - /// Save image in jpeg-xl format - /// - /// - Parameters: - /// - filename: Filename to save to - /// - tier: Decode speed tier - /// - distance: Target butteraugli distance - /// - effort: Encoding effort - /// - lossless: Enable lossless compression - /// - quality: Quality factor - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jxlsave( - filename: String, - tier: Int? = nil, - distance: Double? = nil, - effort: Int? = nil, - lossless: Bool? = nil, - quality: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let tier = tier { - opt.set("tier", value: tier) - } - if let distance = distance { - opt.set("distance", value: distance) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jxlsave", options: &opt) - } - - /// Save image in jpeg-xl format - /// - /// - Parameters: - /// - tier: Decode speed tier - /// - distance: Target butteraugli distance - /// - effort: Encoding effort - /// - lossless: Enable lossless compression - /// - quality: Quality factor - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jxlsave( - tier: Int? = nil, - distance: Double? = nil, - effort: Int? = nil, - lossless: Bool? = nil, - quality: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let tier = tier { - opt.set("tier", value: tier) - } - if let distance = distance { - opt.set("distance", value: distance) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("jxlsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from jxlsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image in jpeg-xl format - /// - /// - Parameters: - /// - target: Target to save to - /// - tier: Decode speed tier - /// - distance: Target butteraugli distance - /// - effort: Encoding effort - /// - lossless: Enable lossless compression - /// - quality: Quality factor - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func jxlsave( - target: VIPSTarget, - tier: Int? = nil, - distance: Double? = nil, - effort: Int? = nil, - lossless: Bool? = nil, - quality: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let tier = tier { - opt.set("tier", value: tier) - } - if let distance = distance { - opt.set("distance", value: distance) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("jxlsave_target", options: &opt) - } - - /// Save file with imagemagick - /// - /// - Parameters: - /// - filename: Filename to save to - /// - format: Format to save in - /// - quality: Quality to use - /// - optimizeGifFrames: Apply GIF frames optimization - /// - optimizeGifTransparency: Apply GIF transparency optimization - /// - bitdepth: Number of bits per pixel - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func magicksave( - filename: String, - format: String? = nil, - quality: Int? = nil, - optimizeGifFrames: Bool? = nil, - optimizeGifTransparency: Bool? = nil, - bitdepth: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let format = format { - opt.set("format", value: format) - } - if let quality = quality { - opt.set("quality", value: quality) - } - if let optimizeGifFrames = optimizeGifFrames { - opt.set("optimize_gif_frames", value: optimizeGifFrames) - } - if let optimizeGifTransparency = optimizeGifTransparency { - opt.set("optimize_gif_transparency", value: optimizeGifTransparency) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("magicksave", options: &opt) - } - - /// Save image to magick buffer - /// - /// - Parameters: - /// - format: Format to save in - /// - quality: Quality to use - /// - optimizeGifFrames: Apply GIF frames optimization - /// - optimizeGifTransparency: Apply GIF transparency optimization - /// - bitdepth: Number of bits per pixel - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func magicksave( - format: String? = nil, - quality: Int? = nil, - optimizeGifFrames: Bool? = nil, - optimizeGifTransparency: Bool? = nil, - bitdepth: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let format = format { - opt.set("format", value: format) - } - if let quality = quality { - opt.set("quality", value: quality) - } - if let optimizeGifFrames = optimizeGifFrames { - opt.set("optimize_gif_frames", value: optimizeGifFrames) - } - if let optimizeGifTransparency = optimizeGifTransparency { - opt.set("optimize_gif_transparency", value: optimizeGifTransparency) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("magicksave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from magicksave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to matrix - /// - /// - Parameters: - /// - filename: Filename to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func matrixsave( - filename: String, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("matrixsave", options: &opt) - } - - /// Save image to matrix - /// - /// - Parameters: - /// - target: Target to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func matrixsave( - target: VIPSTarget, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("matrixsave_target", options: &opt) - } - - /// Save image to ppm file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - format: Format to save in - /// - ascii: Save as ascii - /// - bitdepth: Set to 1 to write as a 1 bit image - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func ppmsave( - filename: String, - format: VipsForeignPpmFormat? = nil, - ascii: Bool? = nil, - bitdepth: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let format = format { - opt.set("format", value: format) - } - if let ascii = ascii { - opt.set("ascii", value: ascii) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("ppmsave", options: &opt) - } - - /// Save to ppm - /// - /// - Parameters: - /// - target: Target to save to - /// - format: Format to save in - /// - ascii: Save as ascii - /// - bitdepth: Set to 1 to write as a 1 bit image - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func ppmsave( - target: VIPSTarget, - format: VipsForeignPpmFormat? = nil, - ascii: Bool? = nil, - bitdepth: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let format = format { - opt.set("format", value: format) - } - if let ascii = ascii { - opt.set("ascii", value: ascii) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("ppmsave_target", options: &opt) - } - - /// Save image to radiance file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func radsave( - filename: String, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("radsave", options: &opt) - } - - /// Save image to radiance buffer - /// - /// - Parameters: - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func radsave( - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("radsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from radsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to radiance target - /// - /// - Parameters: - /// - target: Target to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func radsave( - target: VIPSTarget, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("radsave_target", options: &opt) - } - - /// Save image to raw file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func rawsave( - filename: String, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("rawsave", options: &opt) - } - - /// Write raw image to buffer - /// - /// - Parameters: - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func rawsave( - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("rawsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from rawsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Write raw image to target - /// - /// - Parameters: - /// - target: Target to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func rawsave( - target: VIPSTarget, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("rawsave_target", options: &opt) - } - - /// Save image to file in vips format - /// - /// - Parameters: - /// - filename: Filename to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func vipssave( - filename: String, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("vipssave", options: &opt) - } - - /// Save image to target in vips format - /// - /// - Parameters: - /// - target: Target to save to - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func vipssave( - target: VIPSTarget, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("vipssave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load an analyze6 image - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func analyzeload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("analyzeload", options: &opt) - } - } - - /// Load csv - /// - /// - Parameters: - /// - filename: Filename to load from - /// - skip: Skip this many lines at the start of the file - /// - lines: Read this many lines from the file - /// - whitespace: Set of whitespace characters - /// - separator: Set of separator characters - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func csvload( - filename: String, - skip: Int? = nil, - lines: Int? = nil, - whitespace: String? = nil, - separator: String? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let skip = skip { - opt.set("skip", value: skip) - } - if let lines = lines { - opt.set("lines", value: lines) - } - if let whitespace = whitespace { - opt.set("whitespace", value: whitespace) - } - if let separator = separator { - opt.set("separator", value: separator) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("csvload", options: &opt) - } - } - - /// Load csv - /// - /// - Parameters: - /// - source: Source to load from - /// - skip: Skip this many lines at the start of the file - /// - lines: Read this many lines from the file - /// - whitespace: Set of whitespace characters - /// - separator: Set of separator characters - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func csvload( - source: VIPSSource, - skip: Int? = nil, - lines: Int? = nil, - whitespace: String? = nil, - separator: String? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let skip = skip { - opt.set("skip", value: skip) - } - if let lines = lines { - opt.set("lines", value: lines) - } - if let whitespace = whitespace { - opt.set("whitespace", value: whitespace) - } - if let separator = separator { - opt.set("separator", value: separator) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("csvload_source", options: &opt) - } - } - - /// Load a fits image - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func fitsload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("fitsload", options: &opt) - } - } - - /// Load fits from a source - /// - /// - Parameters: - /// - source: Source to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func fitsload( - source: VIPSSource, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("fitsload_source", options: &opt) - } - } - - /// Load jpeg2000 image - /// - /// - Parameters: - /// - filename: Filename to load from - /// - page: Load this page from the image - /// - oneshot: Load images a frame at a time - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func jp2kload( - filename: String, - page: Int? = nil, - oneshot: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let page = page { - opt.set("page", value: page) - } - if let oneshot = oneshot { - opt.set("oneshot", value: oneshot) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jp2kload", options: &opt) - } - } - - /// Load jpeg2000 image - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: Load this page from the image - /// - oneshot: Load images a frame at a time - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func jp2kload( - buffer: VIPSBlob, - page: Int? = nil, - oneshot: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let page = page { - opt.set("page", value: page) - } - if let oneshot = oneshot { - opt.set("oneshot", value: oneshot) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jp2kload_buffer", options: &opt) - } - } - } - - /// Load jpeg2000 image without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: Load this page from the image - /// - oneshot: Load images a frame at a time - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func jp2kload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - page: Int? = nil, - oneshot: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try jp2kload( - buffer: blob, - page: page, - oneshot: oneshot, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load jpeg2000 image - /// - /// - Parameters: - /// - source: Source to load from - /// - page: Load this page from the image - /// - oneshot: Load images a frame at a time - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func jp2kload( - source: VIPSSource, - page: Int? = nil, - oneshot: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let page = page { - opt.set("page", value: page) - } - if let oneshot = oneshot { - opt.set("oneshot", value: oneshot) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jp2kload_source", options: &opt) - } - } - - /// Load jpeg-xl image - /// - /// - Parameters: - /// - filename: Filename to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func jxlload( - filename: String, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jxlload", options: &opt) - } - } - - /// Load jpeg-xl image - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func jxlload( - buffer: VIPSBlob, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jxlload_buffer", options: &opt) - } - } - } - - /// Load jpeg-xl image without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func jxlload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try jxlload( - buffer: blob, - page: page, - n: n, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load jpeg-xl image - /// - /// - Parameters: - /// - source: Source to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func jxlload( - source: VIPSSource, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("jxlload_source", options: &opt) - } - } - - /// Load file with imagemagick7 - /// - /// - Parameters: - /// - filename: Filename to load from - /// - density: Canvas resolution for rendering vector formats like SVG - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func magickload( - filename: String, - density: String? = nil, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let density = density { - opt.set("density", value: density) - } - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("magickload", options: &opt) - } - } - - /// Load buffer with imagemagick7 - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - density: Canvas resolution for rendering vector formats like SVG - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func magickload( - buffer: VIPSBlob, - density: String? = nil, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let density = density { - opt.set("density", value: density) - } - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("magickload_buffer", options: &opt) - } - } - } - - /// Load buffer with imagemagick7 without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - density: Canvas resolution for rendering vector formats like SVG - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func magickload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - density: String? = nil, - page: Int? = nil, - n: Int? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try magickload( - buffer: blob, - density: density, - page: page, - n: n, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load mat from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func matload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("matload", options: &opt) - } - } - - /// Load matrix - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func matrixload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("matrixload", options: &opt) - } - } - - /// Load matrix - /// - /// - Parameters: - /// - source: Source to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func matrixload( - source: VIPSSource, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("matrixload_source", options: &opt) - } - } - - /// Load an openexr image - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func openexrload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("openexrload", options: &opt) - } - } - - /// Load file with openslide - /// - /// - Parameters: - /// - filename: Filename to load from - /// - level: Load this level from the file - /// - autocrop: Crop to image bounds - /// - associated: Load this associated image - /// - attachAssociated: Attach all associated images - /// - rgb: Output RGB (not RGBA) - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func openslideload( - filename: String, - level: Int? = nil, - autocrop: Bool? = nil, - associated: String? = nil, - attachAssociated: Bool? = nil, - rgb: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let level = level { - opt.set("level", value: level) - } - if let autocrop = autocrop { - opt.set("autocrop", value: autocrop) - } - if let associated = associated { - opt.set("associated", value: associated) - } - if let attachAssociated = attachAssociated { - opt.set("attach_associated", value: attachAssociated) - } - if let rgb = rgb { - opt.set("rgb", value: rgb) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("openslideload", options: &opt) - } - } - - /// Load source with openslide - /// - /// - Parameters: - /// - source: Source to load from - /// - level: Load this level from the file - /// - autocrop: Crop to image bounds - /// - associated: Load this associated image - /// - attachAssociated: Attach all associated images - /// - rgb: Output RGB (not RGBA) - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func openslideload( - source: VIPSSource, - level: Int? = nil, - autocrop: Bool? = nil, - associated: String? = nil, - attachAssociated: Bool? = nil, - rgb: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let level = level { - opt.set("level", value: level) - } - if let autocrop = autocrop { - opt.set("autocrop", value: autocrop) - } - if let associated = associated { - opt.set("associated", value: associated) - } - if let attachAssociated = attachAssociated { - opt.set("attach_associated", value: attachAssociated) - } - if let rgb = rgb { - opt.set("rgb", value: rgb) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("openslideload_source", options: &opt) - } - } - - /// Load ppm from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func ppmload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("ppmload", options: &opt) - } - } - - /// Load ppm from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func ppmload( - buffer: VIPSBlob, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("ppmload_buffer", options: &opt) - } - } - } - - /// Load ppm from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func ppmload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try ppmload( - buffer: blob, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load ppm from source - /// - /// - Parameters: - /// - source: Source to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func ppmload( - source: VIPSSource, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("ppmload_source", options: &opt) - } - } - - /// Load named icc profile - /// - /// - Parameters: - /// - name: Profile name - public static func profileLoad(name: String) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("name", value: name) - opt.set("profile", value: out) - - try Self.call("profile_load", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from profile_load") - } - - return VIPSBlob(vipsBlob) - } - - /// Load a radiance image from a file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func radload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("radload", options: &opt) - } - } - - /// Load rad from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func radload( - buffer: VIPSBlob, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("radload_buffer", options: &opt) - } - } - } - - /// Load rad from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func radload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try radload( - buffer: blob, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load rad from source - /// - /// - Parameters: - /// - source: Source to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func radload( - source: VIPSSource, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("radload_source", options: &opt) - } - } - - /// Load raw data from a file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - bands: Number of bands in image - /// - offset: Offset in bytes from start of file - /// - format: Pixel format in image - /// - interpretation: Pixel interpretation - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func rawload( - filename: String, - width: Int, - height: Int, - bands: Int, - offset: UInt64? = nil, - format: VipsBandFormat? = nil, - interpretation: VipsInterpretation? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("bands", value: bands) - if let offset = offset { - opt.set("offset", value: offset) - } - if let format = format { - opt.set("format", value: format) - } - if let interpretation = interpretation { - opt.set("interpretation", value: interpretation) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("rawload", options: &opt) - } - } - - /// Load vips from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func vipsload( - filename: String, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("vipsload", options: &opt) - } - } - - /// Load vips from source - /// - /// - Parameters: - /// - source: Source to load from - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func vipsload( - source: VIPSSource, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("vipsload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_pdf.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_pdf.generated.swift deleted file mode 100644 index 6fd6300..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_pdf.generated.swift +++ /dev/null @@ -1,263 +0,0 @@ -// -// foreign_pdf.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load pdf from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - dpi: DPI to render at - /// - scale: Factor to scale by - /// - background: Background colour - /// - password: Password to decrypt with - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func pdfload( - filename: String, - page: Int? = nil, - n: Int? = nil, - dpi: Double? = nil, - scale: Double? = nil, - background: [Double]? = nil, - password: String? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let background = background { - opt.set("background", value: background) - } - if let password = password { - opt.set("password", value: password) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("pdfload", options: &opt) - } - } - - /// Load pdf from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - dpi: DPI to render at - /// - scale: Factor to scale by - /// - background: Background colour - /// - password: Password to decrypt with - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func pdfload( - buffer: VIPSBlob, - page: Int? = nil, - n: Int? = nil, - dpi: Double? = nil, - scale: Double? = nil, - background: [Double]? = nil, - password: String? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let background = background { - opt.set("background", value: background) - } - if let password = password { - opt.set("password", value: password) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("pdfload_buffer", options: &opt) - } - } - } - - /// Load pdf from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - dpi: DPI to render at - /// - scale: Factor to scale by - /// - background: Background colour - /// - password: Password to decrypt with - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func pdfload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - page: Int? = nil, - n: Int? = nil, - dpi: Double? = nil, - scale: Double? = nil, - background: [Double]? = nil, - password: String? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try pdfload( - buffer: blob, - page: page, - n: n, - dpi: dpi, - scale: scale, - background: background, - password: password, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load pdf from source - /// - /// - Parameters: - /// - source: Source to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - dpi: DPI to render at - /// - scale: Factor to scale by - /// - background: Background colour - /// - password: Password to decrypt with - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func pdfload( - source: VIPSSource, - page: Int? = nil, - n: Int? = nil, - dpi: Double? = nil, - scale: Double? = nil, - background: [Double]? = nil, - password: String? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let background = background { - opt.set("background", value: background) - } - if let password = password { - opt.set("password", value: password) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("pdfload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_png.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_png.generated.swift deleted file mode 100644 index 918b3de..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_png.generated.swift +++ /dev/null @@ -1,412 +0,0 @@ -// -// foreign_png.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save image to file as png - /// - /// - Parameters: - /// - filename: Filename to save to - /// - compression: Compression factor - /// - interlace: Interlace image - /// - filter: libspng row filter flag(s) - /// - palette: Quantise to 8bpp palette - /// - quality: Quantisation quality - /// - dither: Amount of dithering - /// - bitdepth: Write as a 1, 2, 4, 8 or 16 bit image - /// - effort: Quantisation CPU effort - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func pngsave( - filename: String, - compression: Int? = nil, - interlace: Bool? = nil, - filter: VipsForeignPngFilter? = nil, - palette: Bool? = nil, - quality: Int? = nil, - dither: Double? = nil, - bitdepth: Int? = nil, - effort: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let compression = compression { - opt.set("compression", value: compression) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let filter = filter { - opt.set("filter", value: filter) - } - if let palette = palette { - opt.set("palette", value: palette) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let dither = dither { - opt.set("dither", value: dither) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("pngsave", options: &opt) - } - - /// Save image to buffer as png - /// - /// - Parameters: - /// - compression: Compression factor - /// - interlace: Interlace image - /// - filter: libspng row filter flag(s) - /// - palette: Quantise to 8bpp palette - /// - quality: Quantisation quality - /// - dither: Amount of dithering - /// - bitdepth: Write as a 1, 2, 4, 8 or 16 bit image - /// - effort: Quantisation CPU effort - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func pngsave( - compression: Int? = nil, - interlace: Bool? = nil, - filter: VipsForeignPngFilter? = nil, - palette: Bool? = nil, - quality: Int? = nil, - dither: Double? = nil, - bitdepth: Int? = nil, - effort: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let compression = compression { - opt.set("compression", value: compression) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let filter = filter { - opt.set("filter", value: filter) - } - if let palette = palette { - opt.set("palette", value: palette) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let dither = dither { - opt.set("dither", value: dither) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("pngsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from pngsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to target as png - /// - /// - Parameters: - /// - target: Target to save to - /// - compression: Compression factor - /// - interlace: Interlace image - /// - filter: libspng row filter flag(s) - /// - palette: Quantise to 8bpp palette - /// - quality: Quantisation quality - /// - dither: Amount of dithering - /// - bitdepth: Write as a 1, 2, 4, 8 or 16 bit image - /// - effort: Quantisation CPU effort - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func pngsave( - target: VIPSTarget, - compression: Int? = nil, - interlace: Bool? = nil, - filter: VipsForeignPngFilter? = nil, - palette: Bool? = nil, - quality: Int? = nil, - dither: Double? = nil, - bitdepth: Int? = nil, - effort: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let compression = compression { - opt.set("compression", value: compression) - } - if let interlace = interlace { - opt.set("interlace", value: interlace) - } - if let filter = filter { - opt.set("filter", value: filter) - } - if let palette = palette { - opt.set("palette", value: palette) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let dither = dither { - opt.set("dither", value: dither) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("pngsave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load png from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func pngload( - filename: String, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("pngload", options: &opt) - } - } - - /// Load png from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func pngload( - buffer: VIPSBlob, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("pngload_buffer", options: &opt) - } - } - } - - /// Load png from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func pngload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try pngload( - buffer: blob, - unlimited: unlimited, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load png from source - /// - /// - Parameters: - /// - source: Source to load from - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func pngload( - source: VIPSSource, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("pngload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_svg.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_svg.generated.swift deleted file mode 100644 index 6b40945..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_svg.generated.swift +++ /dev/null @@ -1,245 +0,0 @@ -// -// foreign_svg.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load svg with rsvg - /// - /// - Parameters: - /// - filename: Filename to load from - /// - dpi: Render at this DPI - /// - scale: Scale output by this factor - /// - unlimited: Allow SVG of any size - /// - stylesheet: Custom CSS - /// - highBitdepth: Enable scRGB 128-bit output (32-bit per channel) - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func svgload( - filename: String, - dpi: Double? = nil, - scale: Double? = nil, - unlimited: Bool? = nil, - stylesheet: String? = nil, - highBitdepth: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let stylesheet = stylesheet { - opt.set("stylesheet", value: stylesheet) - } - if let highBitdepth = highBitdepth { - opt.set("high_bitdepth", value: highBitdepth) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("svgload", options: &opt) - } - } - - /// Load svg with rsvg - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - dpi: Render at this DPI - /// - scale: Scale output by this factor - /// - unlimited: Allow SVG of any size - /// - stylesheet: Custom CSS - /// - highBitdepth: Enable scRGB 128-bit output (32-bit per channel) - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func svgload( - buffer: VIPSBlob, - dpi: Double? = nil, - scale: Double? = nil, - unlimited: Bool? = nil, - stylesheet: String? = nil, - highBitdepth: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let stylesheet = stylesheet { - opt.set("stylesheet", value: stylesheet) - } - if let highBitdepth = highBitdepth { - opt.set("high_bitdepth", value: highBitdepth) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("svgload_buffer", options: &opt) - } - } - } - - /// Load svg with rsvg without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - dpi: Render at this DPI - /// - scale: Scale output by this factor - /// - unlimited: Allow SVG of any size - /// - stylesheet: Custom CSS - /// - highBitdepth: Enable scRGB 128-bit output (32-bit per channel) - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func svgload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - dpi: Double? = nil, - scale: Double? = nil, - unlimited: Bool? = nil, - stylesheet: String? = nil, - highBitdepth: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try svgload( - buffer: blob, - dpi: dpi, - scale: scale, - unlimited: unlimited, - stylesheet: stylesheet, - highBitdepth: highBitdepth, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load svg from source - /// - /// - Parameters: - /// - source: Source to load from - /// - dpi: Render at this DPI - /// - scale: Scale output by this factor - /// - unlimited: Allow SVG of any size - /// - stylesheet: Custom CSS - /// - highBitdepth: Enable scRGB 128-bit output (32-bit per channel) - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func svgload( - source: VIPSSource, - dpi: Double? = nil, - scale: Double? = nil, - unlimited: Bool? = nil, - stylesheet: String? = nil, - highBitdepth: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let stylesheet = stylesheet { - opt.set("stylesheet", value: stylesheet) - } - if let highBitdepth = highBitdepth { - opt.set("high_bitdepth", value: highBitdepth) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("svgload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_tiff.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_tiff.generated.swift deleted file mode 100644 index 8040ceb..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_tiff.generated.swift +++ /dev/null @@ -1,664 +0,0 @@ -// -// foreign_tiff.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save image to tiff file - /// - /// - Parameters: - /// - filename: Filename to save to - /// - compression: Compression for this file - /// - quality: Q factor - /// - predictor: Compression prediction - /// - tile: Write a tiled tiff - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - pyramid: Write a pyramidal tiff - /// - miniswhite: Use 0 for white in 1-bit images - /// - bitdepth: Write as a 1, 2, 4 or 8 bit image - /// - resunit: Resolution unit - /// - xres: Horizontal resolution in pixels/mm - /// - yres: Vertical resolution in pixels/mm - /// - bigtiff: Write a bigtiff image - /// - properties: Write a properties document to IMAGEDESCRIPTION - /// - regionShrink: Method to shrink regions - /// - level: Deflate (1-9, default 6) or ZSTD (1-22, default 9) compression level - /// - lossless: Enable WEBP lossless mode - /// - depth: Pyramid depth - /// - subifd: Save pyr layers as sub-IFDs - /// - premultiply: Save with premultiplied alpha - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func tiffsave( - filename: String, - compression: VipsForeignTiffCompression? = nil, - quality: Int? = nil, - predictor: VipsForeignTiffPredictor? = nil, - tile: Bool? = nil, - tileWidth: Int? = nil, - tileHeight: Int? = nil, - pyramid: Bool? = nil, - miniswhite: Bool? = nil, - bitdepth: Int? = nil, - resunit: VipsForeignTiffResunit? = nil, - xres: Double? = nil, - yres: Double? = nil, - bigtiff: Bool? = nil, - properties: Bool? = nil, - regionShrink: VipsRegionShrink? = nil, - level: Int? = nil, - lossless: Bool? = nil, - depth: VipsForeignDzDepth? = nil, - subifd: Bool? = nil, - premultiply: Bool? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let compression = compression { - opt.set("compression", value: compression) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let predictor = predictor { - opt.set("predictor", value: predictor) - } - if let tile = tile { - opt.set("tile", value: tile) - } - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let pyramid = pyramid { - opt.set("pyramid", value: pyramid) - } - if let miniswhite = miniswhite { - opt.set("miniswhite", value: miniswhite) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let resunit = resunit { - opt.set("resunit", value: resunit) - } - if let xres = xres { - opt.set("xres", value: xres) - } - if let yres = yres { - opt.set("yres", value: yres) - } - if let bigtiff = bigtiff { - opt.set("bigtiff", value: bigtiff) - } - if let properties = properties { - opt.set("properties", value: properties) - } - if let regionShrink = regionShrink { - opt.set("region_shrink", value: regionShrink) - } - if let level = level { - opt.set("level", value: level) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let depth = depth { - opt.set("depth", value: depth) - } - if let subifd = subifd { - opt.set("subifd", value: subifd) - } - if let premultiply = premultiply { - opt.set("premultiply", value: premultiply) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("tiffsave", options: &opt) - } - - /// Save image to tiff buffer - /// - /// - Parameters: - /// - compression: Compression for this file - /// - quality: Q factor - /// - predictor: Compression prediction - /// - tile: Write a tiled tiff - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - pyramid: Write a pyramidal tiff - /// - miniswhite: Use 0 for white in 1-bit images - /// - bitdepth: Write as a 1, 2, 4 or 8 bit image - /// - resunit: Resolution unit - /// - xres: Horizontal resolution in pixels/mm - /// - yres: Vertical resolution in pixels/mm - /// - bigtiff: Write a bigtiff image - /// - properties: Write a properties document to IMAGEDESCRIPTION - /// - regionShrink: Method to shrink regions - /// - level: Deflate (1-9, default 6) or ZSTD (1-22, default 9) compression level - /// - lossless: Enable WEBP lossless mode - /// - depth: Pyramid depth - /// - subifd: Save pyr layers as sub-IFDs - /// - premultiply: Save with premultiplied alpha - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func tiffsave( - compression: VipsForeignTiffCompression? = nil, - quality: Int? = nil, - predictor: VipsForeignTiffPredictor? = nil, - tile: Bool? = nil, - tileWidth: Int? = nil, - tileHeight: Int? = nil, - pyramid: Bool? = nil, - miniswhite: Bool? = nil, - bitdepth: Int? = nil, - resunit: VipsForeignTiffResunit? = nil, - xres: Double? = nil, - yres: Double? = nil, - bigtiff: Bool? = nil, - properties: Bool? = nil, - regionShrink: VipsRegionShrink? = nil, - level: Int? = nil, - lossless: Bool? = nil, - depth: VipsForeignDzDepth? = nil, - subifd: Bool? = nil, - premultiply: Bool? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let compression = compression { - opt.set("compression", value: compression) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let predictor = predictor { - opt.set("predictor", value: predictor) - } - if let tile = tile { - opt.set("tile", value: tile) - } - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let pyramid = pyramid { - opt.set("pyramid", value: pyramid) - } - if let miniswhite = miniswhite { - opt.set("miniswhite", value: miniswhite) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let resunit = resunit { - opt.set("resunit", value: resunit) - } - if let xres = xres { - opt.set("xres", value: xres) - } - if let yres = yres { - opt.set("yres", value: yres) - } - if let bigtiff = bigtiff { - opt.set("bigtiff", value: bigtiff) - } - if let properties = properties { - opt.set("properties", value: properties) - } - if let regionShrink = regionShrink { - opt.set("region_shrink", value: regionShrink) - } - if let level = level { - opt.set("level", value: level) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let depth = depth { - opt.set("depth", value: depth) - } - if let subifd = subifd { - opt.set("subifd", value: subifd) - } - if let premultiply = premultiply { - opt.set("premultiply", value: premultiply) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("tiffsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from tiffsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to tiff target - /// - /// - Parameters: - /// - target: Target to save to - /// - compression: Compression for this file - /// - quality: Q factor - /// - predictor: Compression prediction - /// - tile: Write a tiled tiff - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - pyramid: Write a pyramidal tiff - /// - miniswhite: Use 0 for white in 1-bit images - /// - bitdepth: Write as a 1, 2, 4 or 8 bit image - /// - resunit: Resolution unit - /// - xres: Horizontal resolution in pixels/mm - /// - yres: Vertical resolution in pixels/mm - /// - bigtiff: Write a bigtiff image - /// - properties: Write a properties document to IMAGEDESCRIPTION - /// - regionShrink: Method to shrink regions - /// - level: Deflate (1-9, default 6) or ZSTD (1-22, default 9) compression level - /// - lossless: Enable WEBP lossless mode - /// - depth: Pyramid depth - /// - subifd: Save pyr layers as sub-IFDs - /// - premultiply: Save with premultiplied alpha - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func tiffsave( - target: VIPSTarget, - compression: VipsForeignTiffCompression? = nil, - quality: Int? = nil, - predictor: VipsForeignTiffPredictor? = nil, - tile: Bool? = nil, - tileWidth: Int? = nil, - tileHeight: Int? = nil, - pyramid: Bool? = nil, - miniswhite: Bool? = nil, - bitdepth: Int? = nil, - resunit: VipsForeignTiffResunit? = nil, - xres: Double? = nil, - yres: Double? = nil, - bigtiff: Bool? = nil, - properties: Bool? = nil, - regionShrink: VipsRegionShrink? = nil, - level: Int? = nil, - lossless: Bool? = nil, - depth: VipsForeignDzDepth? = nil, - subifd: Bool? = nil, - premultiply: Bool? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let compression = compression { - opt.set("compression", value: compression) - } - if let quality = quality { - opt.set("Q", value: quality) - } - if let predictor = predictor { - opt.set("predictor", value: predictor) - } - if let tile = tile { - opt.set("tile", value: tile) - } - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let pyramid = pyramid { - opt.set("pyramid", value: pyramid) - } - if let miniswhite = miniswhite { - opt.set("miniswhite", value: miniswhite) - } - if let bitdepth = bitdepth { - opt.set("bitdepth", value: bitdepth) - } - if let resunit = resunit { - opt.set("resunit", value: resunit) - } - if let xres = xres { - opt.set("xres", value: xres) - } - if let yres = yres { - opt.set("yres", value: yres) - } - if let bigtiff = bigtiff { - opt.set("bigtiff", value: bigtiff) - } - if let properties = properties { - opt.set("properties", value: properties) - } - if let regionShrink = regionShrink { - opt.set("region_shrink", value: regionShrink) - } - if let level = level { - opt.set("level", value: level) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let depth = depth { - opt.set("depth", value: depth) - } - if let subifd = subifd { - opt.set("subifd", value: subifd) - } - if let premultiply = premultiply { - opt.set("premultiply", value: premultiply) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("tiffsave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load tiff from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - autorotate: Rotate image using orientation tag - /// - subifd: Subifd index - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func tiffload( - filename: String, - page: Int? = nil, - n: Int? = nil, - autorotate: Bool? = nil, - subifd: Int? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let autorotate = autorotate { - opt.set("autorotate", value: autorotate) - } - if let subifd = subifd { - opt.set("subifd", value: subifd) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("tiffload", options: &opt) - } - } - - /// Load tiff from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - autorotate: Rotate image using orientation tag - /// - subifd: Subifd index - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func tiffload( - buffer: VIPSBlob, - page: Int? = nil, - n: Int? = nil, - autorotate: Bool? = nil, - subifd: Int? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let autorotate = autorotate { - opt.set("autorotate", value: autorotate) - } - if let subifd = subifd { - opt.set("subifd", value: subifd) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("tiffload_buffer", options: &opt) - } - } - } - - /// Load tiff from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - autorotate: Rotate image using orientation tag - /// - subifd: Subifd index - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func tiffload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - page: Int? = nil, - n: Int? = nil, - autorotate: Bool? = nil, - subifd: Int? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try tiffload( - buffer: blob, - page: page, - n: n, - autorotate: autorotate, - subifd: subifd, - unlimited: unlimited, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load tiff from source - /// - /// - Parameters: - /// - source: Source to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - autorotate: Rotate image using orientation tag - /// - subifd: Subifd index - /// - unlimited: Remove all denial of service limits - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func tiffload( - source: VIPSSource, - page: Int? = nil, - n: Int? = nil, - autorotate: Bool? = nil, - subifd: Int? = nil, - unlimited: Bool? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let autorotate = autorotate { - opt.set("autorotate", value: autorotate) - } - if let subifd = subifd { - opt.set("subifd", value: subifd) - } - if let unlimited = unlimited { - opt.set("unlimited", value: unlimited) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("tiffload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/Foreign/foreign_webp.generated.swift b/Sources/VIPS/Generated/Foreign/foreign_webp.generated.swift deleted file mode 100644 index 8e0b904..0000000 --- a/Sources/VIPS/Generated/Foreign/foreign_webp.generated.swift +++ /dev/null @@ -1,640 +0,0 @@ -// -// foreign_webp.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Save as webp - /// - /// - Parameters: - /// - filename: Filename to save to - /// - quality: Q factor - /// - lossless: Enable lossless compression - /// - preset: Preset for lossy compression - /// - smartSubsample: Enable high quality chroma subsampling - /// - nearLossless: Enable preprocessing in lossless mode (uses Q) - /// - alphaQ: Change alpha plane fidelity for lossy compression - /// - minSize: Optimise for minimum size - /// - kmin: Minimum number of frames between key frames - /// - kmax: Maximum number of frames between key frames - /// - effort: Level of CPU effort to reduce file size - /// - targetSize: Desired target size in bytes - /// - mixed: Allow mixed encoding (might reduce file size) - /// - smartDeblock: Enable auto-adjusting of the deblocking filter - /// - passes: Number of entropy-analysis passes (in [1..10]) - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func webpsave( - filename: String, - quality: Int? = nil, - lossless: Bool? = nil, - preset: VipsForeignWebpPreset? = nil, - smartSubsample: Bool? = nil, - nearLossless: Bool? = nil, - alphaQ: Int? = nil, - minSize: Bool? = nil, - kmin: Int? = nil, - kmax: Int? = nil, - effort: Int? = nil, - targetSize: Int? = nil, - mixed: Bool? = nil, - smartDeblock: Bool? = nil, - passes: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("filename", value: filename) - if let quality = quality { - opt.set("Q", value: quality) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let preset = preset { - opt.set("preset", value: preset) - } - if let smartSubsample = smartSubsample { - opt.set("smart_subsample", value: smartSubsample) - } - if let nearLossless = nearLossless { - opt.set("near_lossless", value: nearLossless) - } - if let alphaQ = alphaQ { - opt.set("alpha_q", value: alphaQ) - } - if let minSize = minSize { - opt.set("min_size", value: minSize) - } - if let kmin = kmin { - opt.set("kmin", value: kmin) - } - if let kmax = kmax { - opt.set("kmax", value: kmax) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let targetSize = targetSize { - opt.set("target_size", value: targetSize) - } - if let mixed = mixed { - opt.set("mixed", value: mixed) - } - if let smartDeblock = smartDeblock { - opt.set("smart_deblock", value: smartDeblock) - } - if let passes = passes { - opt.set("passes", value: passes) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("webpsave", options: &opt) - } - - /// Save as webp - /// - /// - Parameters: - /// - quality: Q factor - /// - lossless: Enable lossless compression - /// - preset: Preset for lossy compression - /// - smartSubsample: Enable high quality chroma subsampling - /// - nearLossless: Enable preprocessing in lossless mode (uses Q) - /// - alphaQ: Change alpha plane fidelity for lossy compression - /// - minSize: Optimise for minimum size - /// - kmin: Minimum number of frames between key frames - /// - kmax: Maximum number of frames between key frames - /// - effort: Level of CPU effort to reduce file size - /// - targetSize: Desired target size in bytes - /// - mixed: Allow mixed encoding (might reduce file size) - /// - smartDeblock: Enable auto-adjusting of the deblocking filter - /// - passes: Number of entropy-analysis passes (in [1..10]) - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func webpsave( - quality: Int? = nil, - lossless: Bool? = nil, - preset: VipsForeignWebpPreset? = nil, - smartSubsample: Bool? = nil, - nearLossless: Bool? = nil, - alphaQ: Int? = nil, - minSize: Bool? = nil, - kmin: Int? = nil, - kmax: Int? = nil, - effort: Int? = nil, - targetSize: Int? = nil, - mixed: Bool? = nil, - smartDeblock: Bool? = nil, - passes: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws -> VIPSBlob { - var opt = VIPSOption() - - let out: UnsafeMutablePointer?> = .allocate(capacity: 1) - out.initialize(to: nil) - defer { - out.deallocate() - } - - opt.set("in", value: self.image) - if let quality = quality { - opt.set("Q", value: quality) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let preset = preset { - opt.set("preset", value: preset) - } - if let smartSubsample = smartSubsample { - opt.set("smart_subsample", value: smartSubsample) - } - if let nearLossless = nearLossless { - opt.set("near_lossless", value: nearLossless) - } - if let alphaQ = alphaQ { - opt.set("alpha_q", value: alphaQ) - } - if let minSize = minSize { - opt.set("min_size", value: minSize) - } - if let kmin = kmin { - opt.set("kmin", value: kmin) - } - if let kmax = kmax { - opt.set("kmax", value: kmax) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let targetSize = targetSize { - opt.set("target_size", value: targetSize) - } - if let mixed = mixed { - opt.set("mixed", value: mixed) - } - if let smartDeblock = smartDeblock { - opt.set("smart_deblock", value: smartDeblock) - } - if let passes = passes { - opt.set("passes", value: passes) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - opt.set("buffer", value: out) - - try Self.call("webpsave_buffer", options: &opt) - - guard let vipsBlob = out.pointee else { - throw VIPSError("Failed to get buffer from webpsave_buffer") - } - - return VIPSBlob(vipsBlob) - } - - /// Save image to webp mime - /// - /// - Parameters: - /// - quality: Q factor - /// - lossless: Enable lossless compression - /// - preset: Preset for lossy compression - /// - smartSubsample: Enable high quality chroma subsampling - /// - nearLossless: Enable preprocessing in lossless mode (uses Q) - /// - alphaQ: Change alpha plane fidelity for lossy compression - /// - minSize: Optimise for minimum size - /// - kmin: Minimum number of frames between key frames - /// - kmax: Maximum number of frames between key frames - /// - effort: Level of CPU effort to reduce file size - /// - targetSize: Desired target size in bytes - /// - mixed: Allow mixed encoding (might reduce file size) - /// - smartDeblock: Enable auto-adjusting of the deblocking filter - /// - passes: Number of entropy-analysis passes (in [1..10]) - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func webpsaveMime( - quality: Int? = nil, - lossless: Bool? = nil, - preset: VipsForeignWebpPreset? = nil, - smartSubsample: Bool? = nil, - nearLossless: Bool? = nil, - alphaQ: Int? = nil, - minSize: Bool? = nil, - kmin: Int? = nil, - kmax: Int? = nil, - effort: Int? = nil, - targetSize: Int? = nil, - mixed: Bool? = nil, - smartDeblock: Bool? = nil, - passes: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - if let quality = quality { - opt.set("Q", value: quality) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let preset = preset { - opt.set("preset", value: preset) - } - if let smartSubsample = smartSubsample { - opt.set("smart_subsample", value: smartSubsample) - } - if let nearLossless = nearLossless { - opt.set("near_lossless", value: nearLossless) - } - if let alphaQ = alphaQ { - opt.set("alpha_q", value: alphaQ) - } - if let minSize = minSize { - opt.set("min_size", value: minSize) - } - if let kmin = kmin { - opt.set("kmin", value: kmin) - } - if let kmax = kmax { - opt.set("kmax", value: kmax) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let targetSize = targetSize { - opt.set("target_size", value: targetSize) - } - if let mixed = mixed { - opt.set("mixed", value: mixed) - } - if let smartDeblock = smartDeblock { - opt.set("smart_deblock", value: smartDeblock) - } - if let passes = passes { - opt.set("passes", value: passes) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("webpsave_mime", options: &opt) - } - - /// Save as webp - /// - /// - Parameters: - /// - target: Target to save to - /// - quality: Q factor - /// - lossless: Enable lossless compression - /// - preset: Preset for lossy compression - /// - smartSubsample: Enable high quality chroma subsampling - /// - nearLossless: Enable preprocessing in lossless mode (uses Q) - /// - alphaQ: Change alpha plane fidelity for lossy compression - /// - minSize: Optimise for minimum size - /// - kmin: Minimum number of frames between key frames - /// - kmax: Maximum number of frames between key frames - /// - effort: Level of CPU effort to reduce file size - /// - targetSize: Desired target size in bytes - /// - mixed: Allow mixed encoding (might reduce file size) - /// - smartDeblock: Enable auto-adjusting of the deblocking filter - /// - passes: Number of entropy-analysis passes (in [1..10]) - /// - keep: Which metadata to retain - /// - background: Background value - /// - pageHeight: Set page height for multipage save - /// - profile: Filename of ICC profile to embed - public func webpsave( - target: VIPSTarget, - quality: Int? = nil, - lossless: Bool? = nil, - preset: VipsForeignWebpPreset? = nil, - smartSubsample: Bool? = nil, - nearLossless: Bool? = nil, - alphaQ: Int? = nil, - minSize: Bool? = nil, - kmin: Int? = nil, - kmax: Int? = nil, - effort: Int? = nil, - targetSize: Int? = nil, - mixed: Bool? = nil, - smartDeblock: Bool? = nil, - passes: Int? = nil, - keep: VipsForeignKeep? = nil, - background: [Double]? = nil, - pageHeight: Int? = nil, - profile: String? = nil - ) throws { - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("target", value: target) - if let quality = quality { - opt.set("Q", value: quality) - } - if let lossless = lossless { - opt.set("lossless", value: lossless) - } - if let preset = preset { - opt.set("preset", value: preset) - } - if let smartSubsample = smartSubsample { - opt.set("smart_subsample", value: smartSubsample) - } - if let nearLossless = nearLossless { - opt.set("near_lossless", value: nearLossless) - } - if let alphaQ = alphaQ { - opt.set("alpha_q", value: alphaQ) - } - if let minSize = minSize { - opt.set("min_size", value: minSize) - } - if let kmin = kmin { - opt.set("kmin", value: kmin) - } - if let kmax = kmax { - opt.set("kmax", value: kmax) - } - if let effort = effort { - opt.set("effort", value: effort) - } - if let targetSize = targetSize { - opt.set("target_size", value: targetSize) - } - if let mixed = mixed { - opt.set("mixed", value: mixed) - } - if let smartDeblock = smartDeblock { - opt.set("smart_deblock", value: smartDeblock) - } - if let passes = passes { - opt.set("passes", value: passes) - } - if let keep = keep { - opt.set("keep", value: keep) - } - if let background = background { - opt.set("background", value: background) - } - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - if let profile = profile { - opt.set("profile", value: profile) - } - - try Self.call("webpsave_target", options: &opt) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Load webp from file - /// - /// - Parameters: - /// - filename: Filename to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - scale: Factor to scale by - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func webpload( - filename: String, - page: Int? = nil, - n: Int? = nil, - scale: Double? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("webpload", options: &opt) - } - } - - /// Load webp from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - scale: Factor to scale by - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func webpload( - buffer: VIPSBlob, - page: Int? = nil, - n: Int? = nil, - scale: Double? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("webpload_buffer", options: &opt) - } - } - } - - /// Load webp from buffer without copying the data. The caller must ensure the buffer remains valid for - /// the lifetime of the returned image and all its descendants. - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - scale: Factor to scale by - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - @inlinable - public static func webpload( - unsafeBuffer buffer: UnsafeRawBufferPointer, - page: Int? = nil, - n: Int? = nil, - scale: Double? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - let blob = VIPSBlob(noCopy: buffer) - return try webpload( - buffer: blob, - page: page, - n: n, - scale: scale, - memory: memory, - access: access, - failOn: failOn, - revalidate: revalidate - ) - } - - /// Load webp from source - /// - /// - Parameters: - /// - source: Source to load from - /// - page: First page to load - /// - n: Number of pages to load, -1 for all - /// - scale: Factor to scale by - /// - memory: Force open via memory - /// - access: Required access pattern for this file - /// - failOn: Error level to fail on - /// - revalidate: Don't use a cached result for this operation - public static func webpload( - source: VIPSSource, - page: Int? = nil, - n: Int? = nil, - scale: Double? = nil, - memory: Bool? = nil, - access: VipsAccess? = nil, - failOn: VipsFailOn? = nil, - revalidate: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - if let page = page { - opt.set("page", value: page) - } - if let n = n { - opt.set("n", value: n) - } - if let scale = scale { - opt.set("scale", value: scale) - } - if let memory = memory { - opt.set("memory", value: memory) - } - if let access = access { - opt.set("access", value: access) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - if let revalidate = revalidate { - opt.set("revalidate", value: revalidate) - } - opt.set("out", value: &out) - - try Self.call("webpload_source", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/arithmetic.generated.swift b/Sources/VIPS/Generated/arithmetic.generated.swift deleted file mode 100644 index cee8e50..0000000 --- a/Sources/VIPS/Generated/arithmetic.generated.swift +++ /dev/null @@ -1,789 +0,0 @@ -// -// arithmetic.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Transform float lab to signed short - public func Lab2LabS() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("Lab2LabS", options: &opt) - } - } - - /// Unpack a labq image to short lab - public func LabQ2LabS() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LabQ2LabS", options: &opt) - } - } - - /// Transform signed short lab to float - public func LabS2Lab() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LabS2Lab", options: &opt) - } - } - - /// Transform short lab to labq coding - public func LabS2LabQ() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LabS2LabQ", options: &opt) - } - } - - /// Absolute value of an image - public func abs() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("abs", options: &opt) - } - } - - /// Add two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func add(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("add", options: &opt) - } - } - - #if SHIM_VIPS_VERSION_8_16 - /// Append an alpha channel - public func addalpha() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("addalpha", options: &opt) - } - } - #endif - - /// Find image average - public func avg() throws -> Double { - var opt = VIPSOption() - - var out: Double = 0.0 - - opt.set("in", value: self.image) - opt.set("out", value: &out) - - try Self.call("avg", options: &opt) - - return out - } - - /// Boolean operation on two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - /// - boolean: Boolean to perform - public func boolean(_ rhs: some VIPSImageProtocol, boolean: VipsOperationBoolean) throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("boolean", value: boolean) - opt.set("out", value: &out) - - try Self.call("boolean", options: &opt) - } - } - - /// Boolean operations against a constant - /// - /// - Parameters: - /// - boolean: Boolean to perform - /// - c: Array of constants - public func booleanConst(boolean: VipsOperationBoolean, c: [Double]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("boolean", value: boolean) - opt.set("c", value: c) - opt.set("out", value: &out) - - try Self.call("boolean_const", options: &opt) - } - } - - /// Perform a complex operation on an image - /// - /// - Parameters: - /// - cmplx: Complex to perform - public func complex(cmplx: VipsOperationComplex) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("cmplx", value: cmplx) - opt.set("out", value: &out) - - try Self.call("complex", options: &opt) - } - } - - /// Complex binary operations on two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - /// - cmplx: Binary complex operation to perform - public func complex2(_ rhs: some VIPSImageProtocol, cmplx: VipsOperationComplex2) throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("cmplx", value: cmplx) - opt.set("out", value: &out) - - try Self.call("complex2", options: &opt) - } - } - - /// Form a complex image from two real images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func complexform(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("complexform", options: &opt) - } - } - - /// Get a component from a complex image - /// - /// - Parameters: - /// - `get`: Complex to perform - public func complexget(`get`: VipsOperationComplexget) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("get", value: `get`) - opt.set("out", value: &out) - - try Self.call("complexget", options: &opt) - } - } - - /// Find image standard deviation - public func deviate() throws -> Double { - var opt = VIPSOption() - - var out: Double = 0.0 - - opt.set("in", value: self.image) - opt.set("out", value: &out) - - try Self.call("deviate", options: &opt) - - return out - } - - /// Divide two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func divide(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("divide", options: &opt) - } - } - - /// Invert an image - public func invert() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("invert", options: &opt) - } - } - - /// Build an inverted look-up table - /// - /// - Parameters: - /// - size: LUT size to generate - public func invertlut(size: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let size = size { - opt.set("size", value: size) - } - opt.set("out", value: &out) - - try Self.call("invertlut", options: &opt) - } - } - - /// Apply a math operation to an image - /// - /// - Parameters: - /// - math: Math to perform - public func math(_ math: VipsOperationMath) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("math", value: math) - opt.set("out", value: &out) - - try Self.call("math", options: &opt) - } - } - - /// Binary math operations - /// - /// - Parameters: - /// - `right`: Right-hand image argument - /// - math2: Math to perform - public func math2(_ rhs: some VIPSImageProtocol, math2: VipsOperationMath2) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("math2", value: math2) - opt.set("out", value: &out) - - try Self.call("math2", options: &opt) - } - } - - /// Binary math operations with a constant - /// - /// - Parameters: - /// - math2: Math to perform - /// - c: Array of constants - public func math2Const(math2: VipsOperationMath2, c: [Double]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("math2", value: math2) - opt.set("c", value: c) - opt.set("out", value: &out) - - try Self.call("math2_const", options: &opt) - } - } - - /// Invert a matrix - public func matrixinvert() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("matrixinvert", options: &opt) - } - } - - /// Multiply two matrices - /// - /// - Parameters: - /// - `right`: Second matrix to multiply - public func matrixmultiply(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("matrixmultiply", options: &opt) - } - } - - /// Find image maximum - /// - /// - Parameters: - /// - size: Number of maximum values to find - public func max(size: Int? = nil) throws -> Double { - var opt = VIPSOption() - - var out: Double = 0.0 - - opt.set("in", value: self.image) - if let size = size { - opt.set("size", value: size) - } - opt.set("out", value: &out) - - try Self.call("max", options: &opt) - - return out - } - - /// Maximum of a pair of images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func maxpair(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("maxpair", options: &opt) - } - } - - /// Find image minimum - /// - /// - Parameters: - /// - size: Number of minimum values to find - public func min(size: Int? = nil) throws -> Double { - var opt = VIPSOption() - - var out: Double = 0.0 - - opt.set("in", value: self.image) - if let size = size { - opt.set("size", value: size) - } - opt.set("out", value: &out) - - try Self.call("min", options: &opt) - - return out - } - - /// Minimum of a pair of images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func minpair(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("minpair", options: &opt) - } - } - - /// Multiply two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func multiply(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("multiply", options: &opt) - } - } - - #if SHIM_VIPS_VERSION_8_13 - /// Premultiply image alpha - /// - /// - Parameters: - /// - maxAlpha: Maximum value of alpha channel - public func premultiply(maxAlpha: Double? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let maxAlpha = maxAlpha { - opt.set("max_alpha", value: maxAlpha) - } - opt.set("out", value: &out) - - try Self.call("premultiply", options: &opt) - } - } - #endif - - /// Relational operation on two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - /// - relational: Relational to perform - public func relational(_ rhs: some VIPSImageProtocol, relational: VipsOperationRelational) - throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("relational", value: relational) - opt.set("out", value: &out) - - try Self.call("relational", options: &opt) - } - } - - /// Relational operations against a constant - /// - /// - Parameters: - /// - relational: Relational to perform - /// - c: Array of constants - public func relationalConst(relational: VipsOperationRelational, c: [Double]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("relational", value: relational) - opt.set("c", value: c) - opt.set("out", value: &out) - - try Self.call("relational_const", options: &opt) - } - } - - /// Remainder after integer division of two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func remainder(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("remainder", options: &opt) - } - } - - /// Remainder after integer division of an image and a constant - /// - /// - Parameters: - /// - value: Constant value - public func remainder(_ value: Double) throws -> Self { - return try remainderConst(c: [value]) - } - - /// Remainder after integer division of an image and a constant - /// - /// - Parameters: - /// - value: Constant value - public func remainder(_ value: Int) throws -> Self { - return try remainderConst(c: [Double(value)]) - } - - /// Remainder after integer division of an image and a constant - /// - /// - Parameters: - /// - c: Array of constants - public func remainderConst(c: [Double]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("c", value: c) - opt.set("out", value: &out) - - try Self.call("remainder_const", options: &opt) - } - } - - /// Perform a round function on an image - /// - /// - Parameters: - /// - round: Rounding operation to perform - public func round(_ round: VipsOperationRound) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("round", value: round) - opt.set("out", value: &out) - - try Self.call("round", options: &opt) - } - } - - /// Unit vector of pixel - public func sign() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("sign", options: &opt) - } - } - - /// Find many image stats - public func stats() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("stats", options: &opt) - } - } - - /// Subtract two images - /// - /// - Parameters: - /// - `right`: Right-hand image argument - public func subtract(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("subtract", options: &opt) - } - } - - #if SHIM_VIPS_VERSION_8_13 - /// Unpremultiply image alpha - /// - /// - Parameters: - /// - maxAlpha: Maximum value of alpha channel - /// - alphaBand: Unpremultiply with this alpha - public func unpremultiply(maxAlpha: Double? = nil, alphaBand: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let maxAlpha = maxAlpha { - opt.set("max_alpha", value: maxAlpha) - } - if let alphaBand = alphaBand { - opt.set("alpha_band", value: alphaBand) - } - opt.set("out", value: &out) - - try Self.call("unpremultiply", options: &opt) - } - } - #endif - - /// Test for equality - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func equal(_ rhs: some VIPSImageProtocol) throws -> Self { - return try relational(rhs, relational: .equal) - } - - /// Test for equality - /// - /// - Parameters: - /// - value: Constant value - public func equal(_ value: Double) throws -> Self { - return try relationalConst(relational: .equal, c: [value]) - } - - /// Test for inequality - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func notequal(_ rhs: some VIPSImageProtocol) throws -> Self { - return try relational(rhs, relational: .noteq) - } - - /// Test for inequality - /// - /// - Parameters: - /// - value: Constant value - public func notequal(_ value: Double) throws -> Self { - return try relationalConst(relational: .noteq, c: [value]) - } - - /// Test for less than - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func less(_ rhs: some VIPSImageProtocol) throws -> Self { - return try relational(rhs, relational: .less) - } - - /// Test for less than - /// - /// - Parameters: - /// - value: Constant value - public func less(_ value: Double) throws -> Self { - return try relationalConst(relational: .less, c: [value]) - } - - /// Test for less than or equal - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func lesseq(_ rhs: some VIPSImageProtocol) throws -> Self { - return try relational(rhs, relational: .lesseq) - } - - /// Test for less than or equal - /// - /// - Parameters: - /// - value: Constant value - public func lesseq(_ value: Double) throws -> Self { - return try relationalConst(relational: .lesseq, c: [value]) - } - - /// Test for greater than - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func more(_ rhs: some VIPSImageProtocol) throws -> Self { - return try relational(rhs, relational: .more) - } - - /// Test for greater than - /// - /// - Parameters: - /// - value: Constant value - public func more(_ value: Double) throws -> Self { - return try relationalConst(relational: .more, c: [value]) - } - - /// Test for greater than or equal - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func moreeq(_ rhs: some VIPSImageProtocol) throws -> Self { - return try relational(rhs, relational: .moreeq) - } - - /// Test for greater than or equal - /// - /// - Parameters: - /// - value: Constant value - public func moreeq(_ value: Double) throws -> Self { - return try relationalConst(relational: .moreeq, c: [value]) - } - - /// Bitwise AND of two images - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func andimage(_ rhs: some VIPSImageProtocol) throws -> Self { - return try boolean(rhs, boolean: .and) - } - - /// Bitwise OR of two images - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func orimage(_ rhs: some VIPSImageProtocol) throws -> Self { - return try boolean(rhs, boolean: .or) - } - - /// Bitwise XOR of two images - /// - /// - Parameters: - /// - rhs: Right-hand input image - public func eorimage(_ rhs: some VIPSImageProtocol) throws -> Self { - return try boolean(rhs, boolean: .eor) - } - - /// Left shift - /// - /// - Parameters: - /// - amount: Number of bits to shift - public func lshift(_ amount: Int) throws -> Self { - return try booleanConst(boolean: .lshift, c: [Double(amount)]) - } - - /// Right shift - /// - /// - Parameters: - /// - amount: Number of bits to shift - public func rshift(_ amount: Int) throws -> Self { - return try booleanConst(boolean: .rshift, c: [Double(amount)]) - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Sum an array of images - /// - /// - Parameters: - /// - `in`: Array of input images - public static func sum(_ `in`: [VIPSImage]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: `in`) - opt.set("out", value: &out) - - try Self.call("sum", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/colour.generated.swift b/Sources/VIPS/Generated/colour.generated.swift deleted file mode 100644 index 23bc628..0000000 --- a/Sources/VIPS/Generated/colour.generated.swift +++ /dev/null @@ -1,489 +0,0 @@ -// -// colour.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Transform lch to cmc - public func CMC2LCh() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("CMC2LCh", options: &opt) - } - } - - /// Transform cmyk to xyz - public func CMYK2XYZ() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("CMYK2XYZ", options: &opt) - } - } - - /// Transform hsv to srgb - public func HSV2sRGB() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("HSV2sRGB", options: &opt) - } - } - - /// Transform lch to cmc - public func LCh2CMC() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LCh2CMC", options: &opt) - } - } - - /// Transform lch to lab - public func LCh2Lab() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LCh2Lab", options: &opt) - } - } - - /// Transform lab to lch - public func Lab2LCh() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("Lab2LCh", options: &opt) - } - } - - /// Transform float lab to labq coding - public func Lab2LabQ() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("Lab2LabQ", options: &opt) - } - } - - /// Transform cielab to xyz - /// - /// - Parameters: - /// - temp: Color temperature - public func Lab2XYZ(temp: [Double]? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let temp = temp { - opt.set("temp", value: temp) - } - opt.set("out", value: &out) - - try Self.call("Lab2XYZ", options: &opt) - } - } - - /// Unpack a labq image to float lab - public func LabQ2Lab() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LabQ2Lab", options: &opt) - } - } - - /// Convert a labq image to srgb - public func LabQ2sRGB() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("LabQ2sRGB", options: &opt) - } - } - - /// Transform xyz to cmyk - public func XYZ2CMYK() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("XYZ2CMYK", options: &opt) - } - } - - /// Transform xyz to lab - /// - /// - Parameters: - /// - temp: Colour temperature - public func XYZ2Lab(temp: [Double]? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let temp = temp { - opt.set("temp", value: temp) - } - opt.set("out", value: &out) - - try Self.call("XYZ2Lab", options: &opt) - } - } - - /// Transform xyz to yxy - public func XYZ2Yxy() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("XYZ2Yxy", options: &opt) - } - } - - /// Transform xyz to scrgb - public func XYZ2scRGB() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("XYZ2scRGB", options: &opt) - } - } - - /// Transform yxy to xyz - public func Yxy2XYZ() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("Yxy2XYZ", options: &opt) - } - } - - /// Convert to a new colorspace - /// - /// - Parameters: - /// - space: Destination color space - /// - sourceSpace: Source color space - public func colourspace(space: VipsInterpretation, sourceSpace: VipsInterpretation? = nil) - throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("space", value: space) - if let sourceSpace = sourceSpace { - opt.set("source_space", value: sourceSpace) - } - opt.set("out", value: &out) - - try Self.call("colourspace", options: &opt) - } - } - - /// False-color an image - public func falsecolour() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("falsecolour", options: &opt) - } - } - - /// Output to device with icc profile - /// - /// - Parameters: - /// - pcs: Set Profile Connection Space - /// - intent: Rendering intent - /// - blackPointCompensation: Enable black point compensation - /// - outputProfile: Filename to load output profile from - /// - depth: Output device space depth in bits - public func iccExport( - pcs: VipsPCS? = nil, - intent: VipsIntent? = nil, - blackPointCompensation: Bool? = nil, - outputProfile: String? = nil, - depth: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let pcs = pcs { - opt.set("pcs", value: pcs) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let blackPointCompensation = blackPointCompensation { - opt.set("black_point_compensation", value: blackPointCompensation) - } - if let outputProfile = outputProfile { - opt.set("output_profile", value: outputProfile) - } - if let depth = depth { - opt.set("depth", value: depth) - } - opt.set("out", value: &out) - - try Self.call("icc_export", options: &opt) - } - } - - /// Import from device with icc profile - /// - /// - Parameters: - /// - pcs: Set Profile Connection Space - /// - intent: Rendering intent - /// - blackPointCompensation: Enable black point compensation - /// - embedded: Use embedded input profile, if available - /// - inputProfile: Filename to load input profile from - public func iccImport( - pcs: VipsPCS? = nil, - intent: VipsIntent? = nil, - blackPointCompensation: Bool? = nil, - embedded: Bool? = nil, - inputProfile: String? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let pcs = pcs { - opt.set("pcs", value: pcs) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let blackPointCompensation = blackPointCompensation { - opt.set("black_point_compensation", value: blackPointCompensation) - } - if let embedded = embedded { - opt.set("embedded", value: embedded) - } - if let inputProfile = inputProfile { - opt.set("input_profile", value: inputProfile) - } - opt.set("out", value: &out) - - try Self.call("icc_import", options: &opt) - } - } - - /// Transform between devices with icc profiles - /// - /// - Parameters: - /// - outputProfile: Filename to load output profile from - /// - pcs: Set Profile Connection Space - /// - intent: Rendering intent - /// - blackPointCompensation: Enable black point compensation - /// - embedded: Use embedded input profile, if available - /// - inputProfile: Filename to load input profile from - /// - depth: Output device space depth in bits - public func iccTransform( - outputProfile: String, - pcs: VipsPCS? = nil, - intent: VipsIntent? = nil, - blackPointCompensation: Bool? = nil, - embedded: Bool? = nil, - inputProfile: String? = nil, - depth: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("output_profile", value: outputProfile) - if let pcs = pcs { - opt.set("pcs", value: pcs) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let blackPointCompensation = blackPointCompensation { - opt.set("black_point_compensation", value: blackPointCompensation) - } - if let embedded = embedded { - opt.set("embedded", value: embedded) - } - if let inputProfile = inputProfile { - opt.set("input_profile", value: inputProfile) - } - if let depth = depth { - opt.set("depth", value: depth) - } - opt.set("out", value: &out) - - try Self.call("icc_transform", options: &opt) - } - } - - /// Label regions in an image - public func labelregions() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: &out) - - try Self.call("labelregions", options: &opt) - } - } - - /// Transform srgb to hsv - public func sRGB2HSV() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("sRGB2HSV", options: &opt) - } - } - - /// Convert an srgb image to scrgb - public func sRGB2scRGB() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("sRGB2scRGB", options: &opt) - } - } - - /// Convert scrgb to bw - /// - /// - Parameters: - /// - depth: Output device space depth in bits - public func scRGB2BW(depth: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let depth = depth { - opt.set("depth", value: depth) - } - opt.set("out", value: &out) - - try Self.call("scRGB2BW", options: &opt) - } - } - - /// Transform scrgb to xyz - public func scRGB2XYZ() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("scRGB2XYZ", options: &opt) - } - } - - /// Convert scrgb to srgb - /// - /// - Parameters: - /// - depth: Output device space depth in bits - public func scRGB2sRGB(depth: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let depth = depth { - opt.set("depth", value: depth) - } - opt.set("out", value: &out) - - try Self.call("scRGB2sRGB", options: &opt) - } - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Make an image where pixel values are coordinates - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - csize: Size of third dimension - /// - dsize: Size of fourth dimension - /// - esize: Size of fifth dimension - public static func xyz( - width: Int, - height: Int, - csize: Int? = nil, - dsize: Int? = nil, - esize: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let csize = csize { - opt.set("csize", value: csize) - } - if let dsize = dsize { - opt.set("dsize", value: dsize) - } - if let esize = esize { - opt.set("esize", value: esize) - } - opt.set("out", value: &out) - - try Self.call("xyz", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/conversion.generated.swift b/Sources/VIPS/Generated/conversion.generated.swift deleted file mode 100644 index 29a1160..0000000 --- a/Sources/VIPS/Generated/conversion.generated.swift +++ /dev/null @@ -1,1058 +0,0 @@ -// -// conversion.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Affine transform of an image - /// - /// - Parameters: - /// - matrix: Transformation matrix - /// - interpolate: Interpolate pixels with this - /// - oarea: Area of output to generate - /// - odx: Horizontal output displacement - /// - ody: Vertical output displacement - /// - idx: Horizontal input displacement - /// - idy: Vertical input displacement - /// - background: Background value - /// - premultiplied: Images have premultiplied alpha - /// - extend: How to generate the extra pixels - public func affine( - matrix: [Double], - interpolate: VIPSInterpolate? = nil, - oarea: [Int]? = nil, - odx: Double? = nil, - ody: Double? = nil, - idx: Double? = nil, - idy: Double? = nil, - background: [Double]? = nil, - premultiplied: Bool? = nil, - extend: VipsExtend? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("matrix", value: matrix) - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - if let oarea = oarea { - opt.set("oarea", value: oarea) - } - if let odx = odx { - opt.set("odx", value: odx) - } - if let ody = ody { - opt.set("ody", value: ody) - } - if let idx = idx { - opt.set("idx", value: idx) - } - if let idy = idy { - opt.set("idy", value: idy) - } - if let background = background { - opt.set("background", value: background) - } - if let premultiplied = premultiplied { - opt.set("premultiplied", value: premultiplied) - } - if let extend = extend { - opt.set("extend", value: extend) - } - opt.set("out", value: &out) - - try Self.call("affine", options: &opt) - } - } - - /// Autorotate image by exif tag - public func autorot() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("autorot", options: &opt) - } - } - - /// Append a constant band to an image - /// - /// - Parameters: - /// - c: Array of constants to add - public func bandjoinConst(c: [Double]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("c", value: c) - opt.set("out", value: &out) - - try Self.call("bandjoin_const", options: &opt) - } - } - - /// Cast an image - /// - /// - Parameters: - /// - format: Format to cast to - /// - shift: Shift integer values up and down - public func cast(format: VipsBandFormat, shift: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("format", value: format) - if let shift = shift { - opt.set("shift", value: shift) - } - opt.set("out", value: &out) - - try Self.call("cast", options: &opt) - } - } - - /// Blend a pair of images with a blend mode - /// - /// - Parameters: - /// - overlay: Overlay image - /// - mode: VipsBlendMode to join with - /// - x: x position of overlay - /// - y: y position of overlay - /// - compositingSpace: Composite images in this colour space - /// - premultiplied: Images have premultiplied alpha - public func composite2( - overlay: some VIPSImageProtocol, - mode: VipsBlendMode, - x: Int? = nil, - y: Int? = nil, - compositingSpace: VipsInterpretation? = nil, - premultiplied: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("base", value: self) - opt.set("overlay", value: overlay) - opt.set("mode", value: mode) - if let x = x { - opt.set("x", value: x) - } - if let y = y { - opt.set("y", value: y) - } - if let compositingSpace = compositingSpace { - opt.set("compositing_space", value: compositingSpace) - } - if let premultiplied = premultiplied { - opt.set("premultiplied", value: premultiplied) - } - opt.set("out", value: &out) - - try Self.call("composite2", options: &opt) - } - } - - /// Copy an image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - bands: Number of bands in image - /// - format: Pixel format in image - /// - coding: Pixel coding - /// - interpretation: Pixel interpretation - /// - xres: Horizontal resolution in pixels/mm - /// - yres: Vertical resolution in pixels/mm - /// - xoffset: Horizontal offset of origin - /// - yoffset: Vertical offset of origin - public func copy( - width: Int? = nil, - height: Int? = nil, - bands: Int? = nil, - format: VipsBandFormat? = nil, - coding: VipsCoding? = nil, - interpretation: VipsInterpretation? = nil, - xres: Double? = nil, - yres: Double? = nil, - xoffset: Int? = nil, - yoffset: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let width = width { - opt.set("width", value: width) - } - if let height = height { - opt.set("height", value: height) - } - if let bands = bands { - opt.set("bands", value: bands) - } - if let format = format { - opt.set("format", value: format) - } - if let coding = coding { - opt.set("coding", value: coding) - } - if let interpretation = interpretation { - opt.set("interpretation", value: interpretation) - } - if let xres = xres { - opt.set("xres", value: xres) - } - if let yres = yres { - opt.set("yres", value: yres) - } - if let xoffset = xoffset { - opt.set("xoffset", value: xoffset) - } - if let yoffset = yoffset { - opt.set("yoffset", value: yoffset) - } - opt.set("out", value: &out) - - try Self.call("copy", options: &opt) - } - } - - /// Extract an area from an image - /// - /// - Parameters: - /// - `left`: Left edge of extract area - /// - top: Top edge of extract area - /// - width: Width of extract area - /// - height: Height of extract area - public func crop(`left`: Int, top: Int, width: Int, height: Int) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("input", value: self) - opt.set("left", value: `left`) - opt.set("top", value: top) - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("out", value: &out) - - try Self.call("crop", options: &opt) - } - } - - /// Embed an image in a larger image - /// - /// - Parameters: - /// - x: Left edge of input in output - /// - y: Top edge of input in output - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - extend: How to generate the extra pixels - /// - background: Color for background pixels - public func embed( - x: Int, - y: Int, - width: Int, - height: Int, - extend: VipsExtend? = nil, - background: [Double]? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("x", value: x) - opt.set("y", value: y) - opt.set("width", value: width) - opt.set("height", value: height) - if let extend = extend { - opt.set("extend", value: extend) - } - if let background = background { - opt.set("background", value: background) - } - opt.set("out", value: &out) - - try Self.call("embed", options: &opt) - } - } - - /// Extract an area from an image - /// - /// - Parameters: - /// - `left`: Left edge of extract area - /// - top: Top edge of extract area - /// - width: Width of extract area - /// - height: Height of extract area - public func extractArea(`left`: Int, top: Int, width: Int, height: Int) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("input", value: self) - opt.set("left", value: `left`) - opt.set("top", value: top) - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("out", value: &out) - - try Self.call("extract_area", options: &opt) - } - } - - /// Extract band from an image - /// - /// - Parameters: - /// - band: Band to extract - /// - n: Number of bands to extract - public func extractBand(_ band: Int, n: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("band", value: band) - if let n = n { - opt.set("n", value: n) - } - opt.set("out", value: &out) - - try Self.call("extract_band", options: &opt) - } - } - - /// Flip an image - /// - /// - Parameters: - /// - direction: Direction to flip image - public func flip(direction: VipsDirection) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("direction", value: direction) - opt.set("out", value: &out) - - try Self.call("flip", options: &opt) - } - } - - /// Grid an image - /// - /// - Parameters: - /// - tileHeight: Chop into tiles this high - /// - across: Number of tiles across - /// - down: Number of tiles down - public func grid(tileHeight: Int, across: Int, down: Int) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("tile_height", value: tileHeight) - opt.set("across", value: across) - opt.set("down", value: down) - opt.set("out", value: &out) - - try Self.call("grid", options: &opt) - } - } - - /// Insert image @sub into @main at @x, @y - /// - /// - Parameters: - /// - sub: Sub-image to insert into main image - /// - x: Left edge of sub in main - /// - y: Top edge of sub in main - /// - expand: Expand output to hold all of both inputs - /// - background: Color for new pixels - public func insert( - sub: some VIPSImageProtocol, - x: Int, - y: Int, - expand: Bool? = nil, - background: [Double]? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("main", value: self) - opt.set("sub", value: sub) - opt.set("x", value: x) - opt.set("y", value: y) - if let expand = expand { - opt.set("expand", value: expand) - } - if let background = background { - opt.set("background", value: background) - } - opt.set("out", value: &out) - - try Self.call("insert", options: &opt) - } - } - - /// Join a pair of images - /// - /// - Parameters: - /// - in2: Second input image - /// - direction: Join left-right or up-down - /// - expand: Expand output to hold all of both inputs - /// - shim: Pixels between images - /// - background: Colour for new pixels - /// - align: Align on the low, centre or high coordinate edge - public func join( - in2: some VIPSImageProtocol, - direction: VipsDirection, - expand: Bool? = nil, - shim: Int? = nil, - background: [Double]? = nil, - align: VipsAlign? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in1", value: self) - opt.set("in2", value: in2) - opt.set("direction", value: direction) - if let expand = expand { - opt.set("expand", value: expand) - } - if let shim = shim { - opt.set("shim", value: shim) - } - if let background = background { - opt.set("background", value: background) - } - if let align = align { - opt.set("align", value: align) - } - opt.set("out", value: &out) - - try Self.call("join", options: &opt) - } - } - - /// Linear recombination with matrix - /// - /// - Parameters: - /// - m: Matrix of coefficients - public func recomb(m: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("m", value: m) - opt.set("out", value: &out) - - try Self.call("recomb", options: &opt) - } - } - - /// Reduce an image - /// - /// - Parameters: - /// - hshrink: Horizontal shrink factor - /// - vshrink: Vertical shrink factor - /// - kernel: Resampling kernel - /// - gap: Reducing gap - public func reduce( - hshrink: Double, - vshrink: Double, - kernel: VipsKernel? = nil, - gap: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("hshrink", value: hshrink) - opt.set("vshrink", value: vshrink) - if let kernel = kernel { - opt.set("kernel", value: kernel) - } - if let gap = gap { - opt.set("gap", value: gap) - } - opt.set("out", value: &out) - - try Self.call("reduce", options: &opt) - } - } - - /// Shrink an image horizontally - /// - /// - Parameters: - /// - hshrink: Horizontal shrink factor - /// - kernel: Resampling kernel - /// - gap: Reducing gap - public func reduceh(hshrink: Double, kernel: VipsKernel? = nil, gap: Double? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("hshrink", value: hshrink) - if let kernel = kernel { - opt.set("kernel", value: kernel) - } - if let gap = gap { - opt.set("gap", value: gap) - } - opt.set("out", value: &out) - - try Self.call("reduceh", options: &opt) - } - } - - /// Shrink an image vertically - /// - /// - Parameters: - /// - vshrink: Vertical shrink factor - /// - kernel: Resampling kernel - /// - gap: Reducing gap - public func reducev(vshrink: Double, kernel: VipsKernel? = nil, gap: Double? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("vshrink", value: vshrink) - if let kernel = kernel { - opt.set("kernel", value: kernel) - } - if let gap = gap { - opt.set("gap", value: gap) - } - opt.set("out", value: &out) - - try Self.call("reducev", options: &opt) - } - } - - /// Resize an image - /// - /// - Parameters: - /// - scale: Scale image by this factor - /// - kernel: Resampling kernel - /// - gap: Reducing gap - /// - vscale: Vertical scale image by this factor - public func resize( - scale: Double, - kernel: VipsKernel? = nil, - gap: Double? = nil, - vscale: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("scale", value: scale) - if let kernel = kernel { - opt.set("kernel", value: kernel) - } - if let gap = gap { - opt.set("gap", value: gap) - } - if let vscale = vscale { - opt.set("vscale", value: vscale) - } - opt.set("out", value: &out) - - try Self.call("resize", options: &opt) - } - } - - /// Rotate an image - /// - /// - Parameters: - /// - angle: Angle to rotate image - public func rot(angle: VipsAngle) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("angle", value: angle) - opt.set("out", value: &out) - - try Self.call("rot", options: &opt) - } - } - - /// Rotate an image - /// - /// - Parameters: - /// - angle: Angle to rotate image - public func rot45(angle: VipsAngle45? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let angle = angle { - opt.set("angle", value: angle) - } - opt.set("out", value: &out) - - try Self.call("rot45", options: &opt) - } - } - - /// Rotate an image by a number of degrees - /// - /// - Parameters: - /// - angle: Rotate clockwise by this many degrees - /// - interpolate: Interpolate pixels with this - /// - background: Background value - /// - odx: Horizontal output displacement - /// - ody: Vertical output displacement - /// - idx: Horizontal input displacement - /// - idy: Vertical input displacement - public func rotate( - angle: Double, - interpolate: VIPSInterpolate? = nil, - background: [Double]? = nil, - odx: Double? = nil, - ody: Double? = nil, - idx: Double? = nil, - idy: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("angle", value: angle) - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - if let background = background { - opt.set("background", value: background) - } - if let odx = odx { - opt.set("odx", value: odx) - } - if let ody = ody { - opt.set("ody", value: ody) - } - if let idx = idx { - opt.set("idx", value: idx) - } - if let idy = idy { - opt.set("idy", value: idy) - } - opt.set("out", value: &out) - - try Self.call("rotate", options: &opt) - } - } - - /// Scale an image to uchar - /// - /// - Parameters: - /// - exp: Exponent for log scale - /// - log: Log scale - public func scale(exp: Double? = nil, log: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let exp = exp { - opt.set("exp", value: exp) - } - if let log = log { - opt.set("log", value: log) - } - opt.set("out", value: &out) - - try Self.call("scale", options: &opt) - } - } - - /// Shrink an image - /// - /// - Parameters: - /// - hshrink: Horizontal shrink factor - /// - vshrink: Vertical shrink factor - /// - ceil: Round-up output dimensions - public func shrink(hshrink: Double, vshrink: Double, ceil: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("hshrink", value: hshrink) - opt.set("vshrink", value: vshrink) - if let ceil = ceil { - opt.set("ceil", value: ceil) - } - opt.set("out", value: &out) - - try Self.call("shrink", options: &opt) - } - } - - /// Shrink an image horizontally - /// - /// - Parameters: - /// - hshrink: Horizontal shrink factor - /// - ceil: Round-up output dimensions - public func shrinkh(hshrink: Int, ceil: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("hshrink", value: hshrink) - if let ceil = ceil { - opt.set("ceil", value: ceil) - } - opt.set("out", value: &out) - - try Self.call("shrinkh", options: &opt) - } - } - - /// Shrink an image vertically - /// - /// - Parameters: - /// - vshrink: Vertical shrink factor - /// - ceil: Round-up output dimensions - public func shrinkv(vshrink: Int, ceil: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("vshrink", value: vshrink) - if let ceil = ceil { - opt.set("ceil", value: ceil) - } - opt.set("out", value: &out) - - try Self.call("shrinkv", options: &opt) - } - } - - /// Similarity transform of an image - /// - /// - Parameters: - /// - scale: Scale by this factor - /// - angle: Rotate clockwise by this many degrees - /// - interpolate: Interpolate pixels with this - /// - background: Background value - /// - odx: Horizontal output displacement - /// - ody: Vertical output displacement - /// - idx: Horizontal input displacement - /// - idy: Vertical input displacement - public func similarity( - scale: Double? = nil, - angle: Double? = nil, - interpolate: VIPSInterpolate? = nil, - background: [Double]? = nil, - odx: Double? = nil, - ody: Double? = nil, - idx: Double? = nil, - idy: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let scale = scale { - opt.set("scale", value: scale) - } - if let angle = angle { - opt.set("angle", value: angle) - } - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - if let background = background { - opt.set("background", value: background) - } - if let odx = odx { - opt.set("odx", value: odx) - } - if let ody = ody { - opt.set("ody", value: ody) - } - if let idx = idx { - opt.set("idx", value: idx) - } - if let idy = idy { - opt.set("idy", value: idy) - } - opt.set("out", value: &out) - - try Self.call("similarity", options: &opt) - } - } - - /// Extract an area from an image - /// - /// - Parameters: - /// - width: Width of extract area - /// - height: Height of extract area - /// - interesting: How to measure interestingness - /// - premultiplied: Input image already has premultiplied alpha - public func smartcrop( - width: Int, - height: Int, - interesting: VipsInteresting? = nil, - premultiplied: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("input", value: self) - opt.set("width", value: width) - opt.set("height", value: height) - if let interesting = interesting { - opt.set("interesting", value: interesting) - } - if let premultiplied = premultiplied { - opt.set("premultiplied", value: premultiplied) - } - opt.set("out", value: &out) - - try Self.call("smartcrop", options: &opt) - } - } - - /// Cache an image as a set of tiles - /// - /// - Parameters: - /// - tileWidth: Tile width in pixels - /// - tileHeight: Tile height in pixels - /// - maxTiles: Maximum number of tiles to cache - /// - access: Expected access pattern - /// - threaded: Allow threaded access - /// - persistent: Keep cache between evaluations - public func tilecache( - tileWidth: Int? = nil, - tileHeight: Int? = nil, - maxTiles: Int? = nil, - access: VipsAccess? = nil, - threaded: Bool? = nil, - persistent: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let tileWidth = tileWidth { - opt.set("tile_width", value: tileWidth) - } - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let maxTiles = maxTiles { - opt.set("max_tiles", value: maxTiles) - } - if let access = access { - opt.set("access", value: access) - } - if let threaded = threaded { - opt.set("threaded", value: threaded) - } - if let persistent = persistent { - opt.set("persistent", value: persistent) - } - opt.set("out", value: &out) - - try Self.call("tilecache", options: &opt) - } - } - - /// Transpose3d an image - /// - /// - Parameters: - /// - pageHeight: Height of each input page - public func transpose3d(pageHeight: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let pageHeight = pageHeight { - opt.set("page_height", value: pageHeight) - } - opt.set("out", value: &out) - - try Self.call("transpose3d", options: &opt) - } - } - - /// Wrap image origin - /// - /// - Parameters: - /// - x: Left edge of input in output - /// - y: Top edge of input in output - public func wrap(x: Int? = nil, y: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let x = x { - opt.set("x", value: x) - } - if let y = y { - opt.set("y", value: y) - } - opt.set("out", value: &out) - - try Self.call("wrap", options: &opt) - } - } - - /// Zoom an image - /// - /// - Parameters: - /// - xfac: Horizontal zoom factor - /// - yfac: Vertical zoom factor - public func zoom(xfac: Int, yfac: Int) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("input", value: self) - opt.set("xfac", value: xfac) - opt.set("yfac", value: yfac) - opt.set("out", value: &out) - - try Self.call("zoom", options: &opt) - } - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Join an array of images - /// - /// - Parameters: - /// - `in`: Array of input images - /// - across: Number of images across grid - /// - shim: Pixels between images - /// - background: Colour for new pixels - /// - halign: Align on the left, centre or right - /// - valign: Align on the top, centre or bottom - /// - hspacing: Horizontal spacing between images - /// - vspacing: Vertical spacing between images - public static func arrayjoin( - _ `in`: [VIPSImage], - across: Int? = nil, - shim: Int? = nil, - background: [Double]? = nil, - halign: VipsAlign? = nil, - valign: VipsAlign? = nil, - hspacing: Int? = nil, - vspacing: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: `in`) - if let across = across { - opt.set("across", value: across) - } - if let shim = shim { - opt.set("shim", value: shim) - } - if let background = background { - opt.set("background", value: background) - } - if let halign = halign { - opt.set("halign", value: halign) - } - if let valign = valign { - opt.set("valign", value: valign) - } - if let hspacing = hspacing { - opt.set("hspacing", value: hspacing) - } - if let vspacing = vspacing { - opt.set("vspacing", value: vspacing) - } - opt.set("out", value: &out) - - try Self.call("arrayjoin", options: &opt) - } - } - - /// Bandwise join a set of images - /// - /// - Parameters: - /// - `in`: Array of input images - public static func bandjoin(_ `in`: [VIPSImage]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: `in`) - opt.set("out", value: &out) - - try Self.call("bandjoin", options: &opt) - } - } - - /// Band-wise rank of a set of images - /// - /// - Parameters: - /// - `in`: Array of input images - /// - index: Select this band element from sorted list - public static func bandrank(_ `in`: [VIPSImage], index: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: `in`) - if let index = index { - opt.set("index", value: index) - } - opt.set("out", value: &out) - - try Self.call("bandrank", options: &opt) - } - } - - /// Blend an array of images with an array of blend modes - /// - /// - Parameters: - /// - `in`: Array of input images - /// - mode: Array of VipsBlendMode to join with - /// - x: Array of x coordinates to join at - /// - y: Array of y coordinates to join at - /// - compositingSpace: Composite images in this colour space - /// - premultiplied: Images have premultiplied alpha - public static func composite( - _ `in`: [VIPSImage], - mode: [Int], - x: [Int]? = nil, - y: [Int]? = nil, - compositingSpace: VipsInterpretation? = nil, - premultiplied: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: `in`) - opt.set("mode", value: mode) - if let x = x { - opt.set("x", value: x) - } - if let y = y { - opt.set("y", value: y) - } - if let compositingSpace = compositingSpace { - opt.set("compositing_space", value: compositingSpace) - } - if let premultiplied = premultiplied { - opt.set("premultiplied", value: premultiplied) - } - opt.set("out", value: &out) - - try Self.call("composite", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/convolution.generated.swift b/Sources/VIPS/Generated/convolution.generated.swift deleted file mode 100644 index 646bcf8..0000000 --- a/Sources/VIPS/Generated/convolution.generated.swift +++ /dev/null @@ -1,261 +0,0 @@ -// -// convolution.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Canny edge detector - /// - /// - Parameters: - /// - sigma: Sigma of Gaussian - /// - precision: Convolve with this precision - public func canny(sigma: Double? = nil, precision: VipsPrecision? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let sigma = sigma { - opt.set("sigma", value: sigma) - } - if let precision = precision { - opt.set("precision", value: precision) - } - opt.set("out", value: &out) - - try Self.call("canny", options: &opt) - } - } - - /// Convolution operation - /// - /// - Parameters: - /// - mask: Input matrix image - /// - precision: Convolve with this precision - /// - layers: Use this many layers in approximation - /// - cluster: Cluster lines closer than this in approximation - public func conv( - mask: some VIPSImageProtocol, - precision: VipsPrecision? = nil, - layers: Int? = nil, - cluster: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - if let precision = precision { - opt.set("precision", value: precision) - } - if let layers = layers { - opt.set("layers", value: layers) - } - if let cluster = cluster { - opt.set("cluster", value: cluster) - } - opt.set("out", value: &out) - - try Self.call("conv", options: &opt) - } - } - - /// Approximate integer convolution - /// - /// - Parameters: - /// - mask: Input matrix image - /// - layers: Use this many layers in approximation - /// - cluster: Cluster lines closer than this in approximation - public func conva(mask: some VIPSImageProtocol, layers: Int? = nil, cluster: Int? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - if let layers = layers { - opt.set("layers", value: layers) - } - if let cluster = cluster { - opt.set("cluster", value: cluster) - } - opt.set("out", value: &out) - - try Self.call("conva", options: &opt) - } - } - - /// Approximate separable integer convolution - /// - /// - Parameters: - /// - mask: Input matrix image - /// - layers: Use this many layers in approximation - public func convasep(mask: some VIPSImageProtocol, layers: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - if let layers = layers { - opt.set("layers", value: layers) - } - opt.set("out", value: &out) - - try Self.call("convasep", options: &opt) - } - } - - /// Float convolution operation - /// - /// - Parameters: - /// - mask: Input matrix image - public func convf(mask: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - opt.set("out", value: &out) - - try Self.call("convf", options: &opt) - } - } - - /// Int convolution operation - /// - /// - Parameters: - /// - mask: Input matrix image - public func convi(mask: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - opt.set("out", value: &out) - - try Self.call("convi", options: &opt) - } - } - - /// Separable convolution operation - /// - /// - Parameters: - /// - mask: Input matrix image - /// - precision: Convolve with this precision - /// - layers: Use this many layers in approximation - /// - cluster: Cluster lines closer than this in approximation - public func convsep( - mask: some VIPSImageProtocol, - precision: VipsPrecision? = nil, - layers: Int? = nil, - cluster: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - if let precision = precision { - opt.set("precision", value: precision) - } - if let layers = layers { - opt.set("layers", value: layers) - } - if let cluster = cluster { - opt.set("cluster", value: cluster) - } - opt.set("out", value: &out) - - try Self.call("convsep", options: &opt) - } - } - - /// Gaussian blur - /// - /// - Parameters: - /// - sigma: Sigma of Gaussian - /// - minAmpl: Minimum amplitude of Gaussian - /// - precision: Convolve with this precision - public func gaussblur(sigma: Double, minAmpl: Double? = nil, precision: VipsPrecision? = nil) - throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("sigma", value: sigma) - if let minAmpl = minAmpl { - opt.set("min_ampl", value: minAmpl) - } - if let precision = precision { - opt.set("precision", value: precision) - } - opt.set("out", value: &out) - - try Self.call("gaussblur", options: &opt) - } - } - - /// Unsharp masking for print - /// - /// - Parameters: - /// - sigma: Sigma of Gaussian - /// - x1: Flat/jaggy threshold - /// - y2: Maximum brightening - /// - y3: Maximum darkening - /// - m1: Slope for flat areas - /// - m2: Slope for jaggy areas - public func sharpen( - sigma: Double? = nil, - x1: Double? = nil, - y2: Double? = nil, - y3: Double? = nil, - m1: Double? = nil, - m2: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let sigma = sigma { - opt.set("sigma", value: sigma) - } - if let x1 = x1 { - opt.set("x1", value: x1) - } - if let y2 = y2 { - opt.set("y2", value: y2) - } - if let y3 = y3 { - opt.set("y3", value: y3) - } - if let m1 = m1 { - opt.set("m1", value: m1) - } - if let m2 = m2 { - opt.set("m2", value: m2) - } - opt.set("out", value: &out) - - try Self.call("sharpen", options: &opt) - } - } - - /// Sobel edge detector - public func sobel() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("sobel", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/create.generated.swift b/Sources/VIPS/Generated/create.generated.swift deleted file mode 100644 index 42f9341..0000000 --- a/Sources/VIPS/Generated/create.generated.swift +++ /dev/null @@ -1,971 +0,0 @@ -// -// create.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Build a look-up table - public func buildlut() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("buildlut", options: &opt) - } - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Make a black image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - bands: Number of bands in image - public static func black(width: Int, height: Int, bands: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let bands = bands { - opt.set("bands", value: bands) - } - opt.set("out", value: &out) - - try Self.call("black", options: &opt) - } - } - - /// Make an image showing the eye's spatial response - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - uchar: Output an unsigned char image - /// - factor: Maximum spatial frequency - public static func eye(width: Int, height: Int, uchar: Bool? = nil, factor: Double? = nil) - throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let factor = factor { - opt.set("factor", value: factor) - } - opt.set("out", value: &out) - - try Self.call("eye", options: &opt) - } - } - - /// Make a fractal surface - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - fractalDimension: Fractal dimension - public static func fractsurf(width: Int, height: Int, fractalDimension: Double) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("fractal_dimension", value: fractalDimension) - opt.set("out", value: &out) - - try Self.call("fractsurf", options: &opt) - } - } - - /// Make a gaussian image - /// - /// - Parameters: - /// - sigma: Sigma of Gaussian - /// - minAmpl: Minimum amplitude of Gaussian - /// - separable: Generate separable Gaussian - /// - precision: Generate with this precision - public static func gaussmat( - sigma: Double, - minAmpl: Double, - separable: Bool? = nil, - precision: VipsPrecision? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("sigma", value: sigma) - opt.set("min_ampl", value: minAmpl) - if let separable = separable { - opt.set("separable", value: separable) - } - if let precision = precision { - opt.set("precision", value: precision) - } - opt.set("out", value: &out) - - try Self.call("gaussmat", options: &opt) - } - } - - /// Make a gaussnoise image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - sigma: Standard deviation of pixels in generated image - /// - mean: Mean of pixels in generated image - /// - seed: Random number seed - public static func gaussnoise( - width: Int, - height: Int, - sigma: Double? = nil, - mean: Double? = nil, - seed: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let sigma = sigma { - opt.set("sigma", value: sigma) - } - if let mean = mean { - opt.set("mean", value: mean) - } - if let seed = seed { - opt.set("seed", value: seed) - } - opt.set("out", value: &out) - - try Self.call("gaussnoise", options: &opt) - } - } - - /// Make a grey ramp image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - uchar: Output an unsigned char image - public static func grey(width: Int, height: Int, uchar: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - opt.set("out", value: &out) - - try Self.call("grey", options: &opt) - } - } - - /// Make a 1d image where pixel values are indexes - /// - /// - Parameters: - /// - bands: Number of bands in LUT - /// - ushort: Create a 16-bit LUT - /// - size: Size of 16-bit LUT - public static func identity(bands: Int? = nil, ushort: Bool? = nil, size: Int? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - if let bands = bands { - opt.set("bands", value: bands) - } - if let ushort = ushort { - opt.set("ushort", value: ushort) - } - if let size = size { - opt.set("size", value: size) - } - opt.set("out", value: &out) - - try Self.call("identity", options: &opt) - } - } - - /// Make a laplacian of gaussian image - /// - /// - Parameters: - /// - sigma: Radius of Gaussian - /// - minAmpl: Minimum amplitude of Gaussian - /// - separable: Generate separable Gaussian - /// - precision: Generate with this precision - public static func logmat( - sigma: Double, - minAmpl: Double, - separable: Bool? = nil, - precision: VipsPrecision? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("sigma", value: sigma) - opt.set("min_ampl", value: minAmpl) - if let separable = separable { - opt.set("separable", value: separable) - } - if let precision = precision { - opt.set("precision", value: precision) - } - opt.set("out", value: &out) - - try Self.call("logmat", options: &opt) - } - } - - /// Make a butterworth filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - order: Filter order - /// - frequencyCutoff: Frequency cutoff - /// - amplitudeCutoff: Amplitude cutoff - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskButterworth( - width: Int, - height: Int, - order: Double, - frequencyCutoff: Double, - amplitudeCutoff: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("order", value: order) - opt.set("frequency_cutoff", value: frequencyCutoff) - opt.set("amplitude_cutoff", value: amplitudeCutoff) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_butterworth", options: &opt) - } - } - - /// Make a butterworth_band filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - order: Filter order - /// - frequencyCutoffX: Frequency cutoff x - /// - frequencyCutoffY: Frequency cutoff y - /// - radius: Radius of circle - /// - amplitudeCutoff: Amplitude cutoff - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskButterworthBand( - width: Int, - height: Int, - order: Double, - frequencyCutoffX: Double, - frequencyCutoffY: Double, - radius: Double, - amplitudeCutoff: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("order", value: order) - opt.set("frequency_cutoff_x", value: frequencyCutoffX) - opt.set("frequency_cutoff_y", value: frequencyCutoffY) - opt.set("radius", value: radius) - opt.set("amplitude_cutoff", value: amplitudeCutoff) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_butterworth_band", options: &opt) - } - } - - /// Make a butterworth ring filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - order: Filter order - /// - frequencyCutoff: Frequency cutoff - /// - amplitudeCutoff: Amplitude cutoff - /// - ringwidth: Ringwidth - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskButterworthRing( - width: Int, - height: Int, - order: Double, - frequencyCutoff: Double, - amplitudeCutoff: Double, - ringwidth: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("order", value: order) - opt.set("frequency_cutoff", value: frequencyCutoff) - opt.set("amplitude_cutoff", value: amplitudeCutoff) - opt.set("ringwidth", value: ringwidth) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_butterworth_ring", options: &opt) - } - } - - /// Make fractal filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - fractalDimension: Fractal dimension - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskFractal( - width: Int, - height: Int, - fractalDimension: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("fractal_dimension", value: fractalDimension) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_fractal", options: &opt) - } - } - - /// Make a gaussian filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - frequencyCutoff: Frequency cutoff - /// - amplitudeCutoff: Amplitude cutoff - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskGaussian( - width: Int, - height: Int, - frequencyCutoff: Double, - amplitudeCutoff: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("frequency_cutoff", value: frequencyCutoff) - opt.set("amplitude_cutoff", value: amplitudeCutoff) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_gaussian", options: &opt) - } - } - - /// Make a gaussian filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - frequencyCutoffX: Frequency cutoff x - /// - frequencyCutoffY: Frequency cutoff y - /// - radius: Radius of circle - /// - amplitudeCutoff: Amplitude cutoff - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskGaussianBand( - width: Int, - height: Int, - frequencyCutoffX: Double, - frequencyCutoffY: Double, - radius: Double, - amplitudeCutoff: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("frequency_cutoff_x", value: frequencyCutoffX) - opt.set("frequency_cutoff_y", value: frequencyCutoffY) - opt.set("radius", value: radius) - opt.set("amplitude_cutoff", value: amplitudeCutoff) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_gaussian_band", options: &opt) - } - } - - /// Make a gaussian ring filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - frequencyCutoff: Frequency cutoff - /// - amplitudeCutoff: Amplitude cutoff - /// - ringwidth: Ringwidth - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskGaussianRing( - width: Int, - height: Int, - frequencyCutoff: Double, - amplitudeCutoff: Double, - ringwidth: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("frequency_cutoff", value: frequencyCutoff) - opt.set("amplitude_cutoff", value: amplitudeCutoff) - opt.set("ringwidth", value: ringwidth) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_gaussian_ring", options: &opt) - } - } - - /// Make an ideal filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - frequencyCutoff: Frequency cutoff - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskIdeal( - width: Int, - height: Int, - frequencyCutoff: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("frequency_cutoff", value: frequencyCutoff) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_ideal", options: &opt) - } - } - - /// Make an ideal band filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - frequencyCutoffX: Frequency cutoff x - /// - frequencyCutoffY: Frequency cutoff y - /// - radius: Radius of circle - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskIdealBand( - width: Int, - height: Int, - frequencyCutoffX: Double, - frequencyCutoffY: Double, - radius: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("frequency_cutoff_x", value: frequencyCutoffX) - opt.set("frequency_cutoff_y", value: frequencyCutoffY) - opt.set("radius", value: radius) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_ideal_band", options: &opt) - } - } - - /// Make an ideal ring filter - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - frequencyCutoff: Frequency cutoff - /// - ringwidth: Ringwidth - /// - uchar: Output an unsigned char image - /// - nodc: Remove DC component - /// - reject: Invert the sense of the filter - /// - optical: Rotate quadrants to optical space - public static func maskIdealRing( - width: Int, - height: Int, - frequencyCutoff: Double, - ringwidth: Double, - uchar: Bool? = nil, - nodc: Bool? = nil, - reject: Bool? = nil, - optical: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("frequency_cutoff", value: frequencyCutoff) - opt.set("ringwidth", value: ringwidth) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let nodc = nodc { - opt.set("nodc", value: nodc) - } - if let reject = reject { - opt.set("reject", value: reject) - } - if let optical = optical { - opt.set("optical", value: optical) - } - opt.set("out", value: &out) - - try Self.call("mask_ideal_ring", options: &opt) - } - } - - /// Make a perlin noise image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - cellSize: Size of Perlin cells - /// - uchar: Output an unsigned char image - /// - seed: Random number seed - public static func perlin( - width: Int, - height: Int, - cellSize: Int? = nil, - uchar: Bool? = nil, - seed: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let cellSize = cellSize { - opt.set("cell_size", value: cellSize) - } - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let seed = seed { - opt.set("seed", value: seed) - } - opt.set("out", value: &out) - - try Self.call("perlin", options: &opt) - } - } - - /// Make a 2d sine wave - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - uchar: Output an unsigned char image - /// - hfreq: Horizontal spatial frequency - /// - vfreq: Vertical spatial frequency - public static func sines( - width: Int, - height: Int, - uchar: Bool? = nil, - hfreq: Double? = nil, - vfreq: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - if let hfreq = hfreq { - opt.set("hfreq", value: hfreq) - } - if let vfreq = vfreq { - opt.set("vfreq", value: vfreq) - } - opt.set("out", value: &out) - - try Self.call("sines", options: &opt) - } - } - - /// Make a text image - /// - /// - Parameters: - /// - text: Text to render - /// - font: Font to render with - /// - width: Maximum image width in pixels - /// - height: Maximum image height in pixels - /// - align: Align on the low, centre or high edge - /// - justify: Justify lines - /// - dpi: DPI to render at - /// - spacing: Line spacing - /// - fontfile: Load this font file - /// - rgba: Enable RGBA output - /// - wrap: Wrap lines on word or character boundaries - public static func text( - _ text: String, - font: String? = nil, - width: Int? = nil, - height: Int? = nil, - align: VipsAlign? = nil, - justify: Bool? = nil, - dpi: Int? = nil, - spacing: Int? = nil, - fontfile: String? = nil, - rgba: Bool? = nil, - wrap: VipsTextWrap? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("text", value: text) - if let font = font { - opt.set("font", value: font) - } - if let width = width { - opt.set("width", value: width) - } - if let height = height { - opt.set("height", value: height) - } - if let align = align { - opt.set("align", value: align) - } - if let justify = justify { - opt.set("justify", value: justify) - } - if let dpi = dpi { - opt.set("dpi", value: dpi) - } - if let spacing = spacing { - opt.set("spacing", value: spacing) - } - if let fontfile = fontfile { - opt.set("fontfile", value: fontfile) - } - if let rgba = rgba { - opt.set("rgba", value: rgba) - } - if let wrap = wrap { - opt.set("wrap", value: wrap) - } - opt.set("out", value: &out) - - try Self.call("text", options: &opt) - } - } - - /// Build a look-up table - /// - /// - Parameters: - /// - inMax: Size of LUT to build - /// - outMax: Maximum value in output LUT - /// - Lb: Lowest value in output - /// - Lw: Highest value in output - /// - Ps: Position of shadow - /// - Pm: Position of mid-tones - /// - Ph: Position of highlights - /// - S: Adjust shadows by this much - /// - M: Adjust mid-tones by this much - /// - H: Adjust highlights by this much - public static func tonelut( - inMax: Int? = nil, - outMax: Int? = nil, - Lb: Double? = nil, - Lw: Double? = nil, - Ps: Double? = nil, - Pm: Double? = nil, - Ph: Double? = nil, - S: Double? = nil, - M: Double? = nil, - H: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - if let inMax = inMax { - opt.set("in_max", value: inMax) - } - if let outMax = outMax { - opt.set("out_max", value: outMax) - } - if let Lb = Lb { - opt.set("Lb", value: Lb) - } - if let Lw = Lw { - opt.set("Lw", value: Lw) - } - if let Ps = Ps { - opt.set("Ps", value: Ps) - } - if let Pm = Pm { - opt.set("Pm", value: Pm) - } - if let Ph = Ph { - opt.set("Ph", value: Ph) - } - if let S = S { - opt.set("S", value: S) - } - if let M = M { - opt.set("M", value: M) - } - if let H = H { - opt.set("H", value: H) - } - opt.set("out", value: &out) - - try Self.call("tonelut", options: &opt) - } - } - - /// Make a worley noise image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - cellSize: Size of Worley cells - /// - seed: Random number seed - public static func worley(width: Int, height: Int, cellSize: Int? = nil, seed: Int? = nil) - throws -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let cellSize = cellSize { - opt.set("cell_size", value: cellSize) - } - if let seed = seed { - opt.set("seed", value: seed) - } - opt.set("out", value: &out) - - try Self.call("worley", options: &opt) - } - } - - /// Make a zone plate - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - uchar: Output an unsigned char image - public static func zone(width: Int, height: Int, uchar: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - if let uchar = uchar { - opt.set("uchar", value: uchar) - } - opt.set("out", value: &out) - - try Self.call("zone", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/freqfilt.generated.swift b/Sources/VIPS/Generated/freqfilt.generated.swift deleted file mode 100644 index 1a9ac05..0000000 --- a/Sources/VIPS/Generated/freqfilt.generated.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// freqfilt.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Frequency-domain filtering - /// - /// - Parameters: - /// - mask: Input mask image - public func freqmult(mask: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - opt.set("out", value: &out) - - try Self.call("freqmult", options: &opt) - } - } - - /// Forward fft - public func fwfft() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("fwfft", options: &opt) - } - } - - /// Inverse fft - /// - /// - Parameters: - /// - real: Output only the real part of the transform - public func invfft(real: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let real = real { - opt.set("real", value: real) - } - opt.set("out", value: &out) - - try Self.call("invfft", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/histogram.generated.swift b/Sources/VIPS/Generated/histogram.generated.swift deleted file mode 100644 index 4b3e187..0000000 --- a/Sources/VIPS/Generated/histogram.generated.swift +++ /dev/null @@ -1,268 +0,0 @@ -// -// histogram.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Form cumulative histogram - public func histCum() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("hist_cum", options: &opt) - } - } - - /// Estimate image entropy - public func histEntropy() throws -> Double { - var opt = VIPSOption() - - var out: Double = 0.0 - - opt.set("in", value: self.image) - opt.set("out", value: &out) - - try Self.call("hist_entropy", options: &opt) - - return out - } - - /// Histogram equalisation - /// - /// - Parameters: - /// - band: Equalise with this band - public func histEqual(band: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let band = band { - opt.set("band", value: band) - } - opt.set("out", value: &out) - - try Self.call("hist_equal", options: &opt) - } - } - - /// Find image histogram - /// - /// - Parameters: - /// - band: Find histogram of band - public func histFind(band: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let band = band { - opt.set("band", value: band) - } - opt.set("out", value: &out) - - try Self.call("hist_find", options: &opt) - } - } - - /// Find indexed image histogram - /// - /// - Parameters: - /// - index: Index image - /// - combine: Combine bins like this - public func histFindIndexed(index: some VIPSImageProtocol, combine: VipsCombine? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("index", value: index) - if let combine = combine { - opt.set("combine", value: combine) - } - opt.set("out", value: &out) - - try Self.call("hist_find_indexed", options: &opt) - } - } - - /// Find n-dimensional image histogram - /// - /// - Parameters: - /// - bins: Number of bins in each dimension - public func histFindNdim(bins: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let bins = bins { - opt.set("bins", value: bins) - } - opt.set("out", value: &out) - - try Self.call("hist_find_ndim", options: &opt) - } - } - - /// Test for monotonicity - public func histIsmonotonic() throws -> Bool { - var opt = VIPSOption() - - var out: Bool = false - - opt.set("in", value: self.image) - opt.set("monotonic", value: &out) - - try Self.call("hist_ismonotonic", options: &opt) - - return out - } - - /// Local histogram equalisation - /// - /// - Parameters: - /// - width: Window width in pixels - /// - height: Window height in pixels - /// - maxSlope: Maximum slope (CLAHE) - public func histLocal(width: Int, height: Int, maxSlope: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("width", value: width) - opt.set("height", value: height) - if let maxSlope = maxSlope { - opt.set("max_slope", value: maxSlope) - } - opt.set("out", value: &out) - - try Self.call("hist_local", options: &opt) - } - } - - /// Match two histograms - /// - /// - Parameters: - /// - ref: Reference histogram - public func histMatch(ref: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("ref", value: ref) - opt.set("out", value: &out) - - try Self.call("hist_match", options: &opt) - } - } - - /// Normalise histogram - public func histNorm() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("hist_norm", options: &opt) - } - } - - /// Plot histogram - public func histPlot() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("hist_plot", options: &opt) - } - } - - /// Find hough circle transform - /// - /// - Parameters: - /// - scale: Scale down dimensions by this factor - /// - minRadius: Smallest radius to search for - /// - maxRadius: Largest radius to search for - public func houghCircle(scale: Int? = nil, minRadius: Int? = nil, maxRadius: Int? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let scale = scale { - opt.set("scale", value: scale) - } - if let minRadius = minRadius { - opt.set("min_radius", value: minRadius) - } - if let maxRadius = maxRadius { - opt.set("max_radius", value: maxRadius) - } - opt.set("out", value: &out) - - try Self.call("hough_circle", options: &opt) - } - } - - /// Find hough line transform - /// - /// - Parameters: - /// - width: Horizontal size of parameter space - /// - height: Vertical size of parameter space - public func houghLine(width: Int? = nil, height: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let width = width { - opt.set("width", value: width) - } - if let height = height { - opt.set("height", value: height) - } - opt.set("out", value: &out) - - try Self.call("hough_line", options: &opt) - } - } - - /// Calculate phase correlation - /// - /// - Parameters: - /// - in2: Second input image - public func phasecor(in2: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("in2", value: in2) - opt.set("out", value: &out) - - try Self.call("phasecor", options: &opt) - } - } - - /// Make displayable power spectrum - public func spectrum() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("spectrum", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/misc.generated.swift b/Sources/VIPS/Generated/misc.generated.swift deleted file mode 100644 index 6f35cfb..0000000 --- a/Sources/VIPS/Generated/misc.generated.swift +++ /dev/null @@ -1,1034 +0,0 @@ -// -// misc.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Boolean operation across image bands - /// - /// - Parameters: - /// - boolean: Boolean to perform - public func bandbool(boolean: VipsOperationBoolean) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("boolean", value: boolean) - opt.set("out", value: &out) - - try Self.call("bandbool", options: &opt) - } - } - - /// Fold up x axis into bands - /// - /// - Parameters: - /// - factor: Fold by this factor - public func bandfold(factor: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let factor = factor { - opt.set("factor", value: factor) - } - opt.set("out", value: &out) - - try Self.call("bandfold", options: &opt) - } - } - - /// Band-wise average - public func bandmean() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("bandmean", options: &opt) - } - } - - /// Unfold image bands into x axis - /// - /// - Parameters: - /// - factor: Unfold by this factor - public func bandunfold(factor: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let factor = factor { - opt.set("factor", value: factor) - } - opt.set("out", value: &out) - - try Self.call("bandunfold", options: &opt) - } - } - - /// Byteswap an image - public func byteswap() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("byteswap", options: &opt) - } - } - - /// Use pixel values to pick cases from an array of images - /// - /// - Parameters: - /// - cases: Array of case images - public func `case`(cases: [VIPSImage]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("index", value: self) - opt.set("cases", value: cases) - opt.set("out", value: &out) - - try Self.call("case", options: &opt) - } - } - - /// Clamp values of an image - /// - /// - Parameters: - /// - min: Minimum value - /// - max: Maximum value - public func clamp(min: Double? = nil, max: Double? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let min = min { - opt.set("min", value: min) - } - if let max = max { - opt.set("max", value: max) - } - opt.set("out", value: &out) - - try Self.call("clamp", options: &opt) - } - } - - /// Convolve with rotating mask - /// - /// - Parameters: - /// - mask: Input matrix image - /// - times: Rotate and convolve this many times - /// - angle: Rotate mask by this much between convolutions - /// - combine: Combine convolution results like this - /// - precision: Convolve with this precision - /// - layers: Use this many layers in approximation - /// - cluster: Cluster lines closer than this in approximation - public func compass( - mask: some VIPSImageProtocol, - times: Int? = nil, - angle: VipsAngle45? = nil, - combine: VipsCombine? = nil, - precision: VipsPrecision? = nil, - layers: Int? = nil, - cluster: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - if let times = times { - opt.set("times", value: times) - } - if let angle = angle { - opt.set("angle", value: angle) - } - if let combine = combine { - opt.set("combine", value: combine) - } - if let precision = precision { - opt.set("precision", value: precision) - } - if let layers = layers { - opt.set("layers", value: layers) - } - if let cluster = cluster { - opt.set("cluster", value: cluster) - } - opt.set("out", value: &out) - - try Self.call("compass", options: &opt) - } - } - - /// Calculate de00 - /// - /// - Parameters: - /// - `right`: Right-hand input image - public func dE00(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("dE00", options: &opt) - } - } - - /// Calculate de76 - /// - /// - Parameters: - /// - `right`: Right-hand input image - public func dE76(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("dE76", options: &opt) - } - } - - /// Calculate decmc - /// - /// - Parameters: - /// - `right`: Right-hand input image - public func dECMC(_ rhs: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("left", value: self) - opt.set("right", value: rhs) - opt.set("out", value: &out) - - try Self.call("dECMC", options: &opt) - } - } - - /// Fast correlation - /// - /// - Parameters: - /// - ref: Input reference image - public func fastcor(ref: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("ref", value: ref) - opt.set("out", value: &out) - - try Self.call("fastcor", options: &opt) - } - } - - /// Fill image zeros with nearest non-zero pixel - public func fillNearest() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("fill_nearest", options: &opt) - } - } - - /// Search an image for non-edge areas - /// - /// - Parameters: - /// - threshold: Object threshold - /// - background: Color for background pixels - /// - lineArt: Enable line art mode - public func findTrim( - threshold: Double? = nil, - background: [Double]? = nil, - lineArt: Bool? = nil - ) throws -> Int { - var opt = VIPSOption() - - var out: Int = 0 - - opt.set("in", value: self.image) - if let threshold = threshold { - opt.set("threshold", value: threshold) - } - if let background = background { - opt.set("background", value: background) - } - if let lineArt = lineArt { - opt.set("line_art", value: lineArt) - } - opt.set("left", value: &out) - - try Self.call("find_trim", options: &opt) - - return out - } - - /// Flatten alpha out of an image - /// - /// - Parameters: - /// - background: Background value - /// - maxAlpha: Maximum value of alpha channel - public func flatten(background: [Double]? = nil, maxAlpha: Double? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let background = background { - opt.set("background", value: background) - } - if let maxAlpha = maxAlpha { - opt.set("max_alpha", value: maxAlpha) - } - opt.set("out", value: &out) - - try Self.call("flatten", options: &opt) - } - } - - /// Transform float rgb to radiance coding - public func float2rad() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("float2rad", options: &opt) - } - } - - /// Gamma an image - /// - /// - Parameters: - /// - exponent: Gamma factor - public func gamma(exponent: Double? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let exponent = exponent { - opt.set("exponent", value: exponent) - } - opt.set("out", value: &out) - - try Self.call("gamma", options: &opt) - } - } - - /// Read a point from an image - /// - /// - Parameters: - /// - x: Point to read - /// - y: Point to read - /// - unpackComplex: Complex pixels should be unpacked - public func getpoint(x: Int, y: Int, unpackComplex: Bool? = nil) throws -> [Double] { - var opt = VIPSOption() - - var out: UnsafeMutablePointer! = .allocate(capacity: 1) - - opt.set("in", value: self.image) - opt.set("x", value: x) - opt.set("y", value: y) - if let unpackComplex = unpackComplex { - opt.set("unpack_complex", value: unpackComplex) - } - opt.set("out_array", value: &out) - - try Self.call("getpoint", options: &opt) - - guard let out else { - throw VIPSError("getpoint: no output") - } - - defer { - vips_area_unref(shim_vips_area(out)) - } - - var length = Int32(0) - let doubles = vips_array_double_get(out, &length) - let buffer = UnsafeBufferPointer(start: doubles, count: Int(length)) - return Array(buffer) - } - - /// Global balance an image mosaic - /// - /// - Parameters: - /// - gamma: Image gamma - /// - intOutput: Integer output - public func globalbalance(gamma: Double? = nil, intOutput: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let gamma = gamma { - opt.set("gamma", value: gamma) - } - if let intOutput = intOutput { - opt.set("int_output", value: intOutput) - } - opt.set("out", value: &out) - - try Self.call("globalbalance", options: &opt) - } - } - - /// Place an image within a larger image with a certain gravity - /// - /// - Parameters: - /// - direction: Direction to place image within width/height - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - extend: How to generate the extra pixels - /// - background: Color for background pixels - public func gravity( - direction: VipsCompassDirection, - width: Int, - height: Int, - extend: VipsExtend? = nil, - background: [Double]? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("direction", value: direction) - opt.set("width", value: width) - opt.set("height", value: height) - if let extend = extend { - opt.set("extend", value: extend) - } - if let background = background { - opt.set("background", value: background) - } - opt.set("out", value: &out) - - try Self.call("gravity", options: &opt) - } - } - - /// Ifthenelse an image - /// - /// - Parameters: - /// - in1: Source for TRUE pixels - /// - in2: Source for FALSE pixels - /// - blend: Blend smoothly between then and else parts - public func ifthenelse( - in1: some VIPSImageProtocol, - in2: some VIPSImageProtocol, - blend: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("cond", value: self) - opt.set("in1", value: in1) - opt.set("in2", value: in2) - if let blend = blend { - opt.set("blend", value: blend) - } - opt.set("out", value: &out) - - try Self.call("ifthenelse", options: &opt) - } - } - - /// Cache an image as a set of lines - /// - /// - Parameters: - /// - tileHeight: Tile height in pixels - /// - access: Expected access pattern - /// - threaded: Allow threaded access - /// - persistent: Keep cache between evaluations - public func linecache( - tileHeight: Int? = nil, - access: VipsAccess? = nil, - threaded: Bool? = nil, - persistent: Bool? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - if let access = access { - opt.set("access", value: access) - } - if let threaded = threaded { - opt.set("threaded", value: threaded) - } - if let persistent = persistent { - opt.set("persistent", value: persistent) - } - opt.set("out", value: &out) - - try Self.call("linecache", options: &opt) - } - } - - /// Map an image though a lut - /// - /// - Parameters: - /// - lut: Look-up table image - /// - band: Apply one-band lut to this band of in - public func maplut(lut: some VIPSImageProtocol, band: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("lut", value: lut) - if let band = band { - opt.set("band", value: band) - } - opt.set("out", value: &out) - - try Self.call("maplut", options: &opt) - } - } - - /// First-order match of two images - /// - /// - Parameters: - /// - sec: Secondary image - /// - xr1: Position of first reference tie-point - /// - yr1: Position of first reference tie-point - /// - xs1: Position of first secondary tie-point - /// - ys1: Position of first secondary tie-point - /// - xr2: Position of second reference tie-point - /// - yr2: Position of second reference tie-point - /// - xs2: Position of second secondary tie-point - /// - ys2: Position of second secondary tie-point - /// - hwindow: Half window size - /// - harea: Half area size - /// - search: Search to improve tie-points - /// - interpolate: Interpolate pixels with this - public func match( - sec: some VIPSImageProtocol, - xr1: Int, - yr1: Int, - xs1: Int, - ys1: Int, - xr2: Int, - yr2: Int, - xs2: Int, - ys2: Int, - hwindow: Int? = nil, - harea: Int? = nil, - search: Bool? = nil, - interpolate: VIPSInterpolate? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("ref", value: self) - opt.set("sec", value: sec) - opt.set("xr1", value: xr1) - opt.set("yr1", value: yr1) - opt.set("xs1", value: xs1) - opt.set("ys1", value: ys1) - opt.set("xr2", value: xr2) - opt.set("yr2", value: yr2) - opt.set("xs2", value: xs2) - opt.set("ys2", value: ys2) - if let hwindow = hwindow { - opt.set("hwindow", value: hwindow) - } - if let harea = harea { - opt.set("harea", value: harea) - } - if let search = search { - opt.set("search", value: search) - } - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - opt.set("out", value: &out) - - try Self.call("match", options: &opt) - } - } - - /// Measure a set of patches on a color chart - /// - /// - Parameters: - /// - h: Number of patches across chart - /// - v: Number of patches down chart - /// - `left`: Left edge of extract area - /// - top: Top edge of extract area - /// - width: Width of extract area - /// - height: Height of extract area - public func measure( - h: Int, - v: Int, - `left`: Int? = nil, - top: Int? = nil, - width: Int? = nil, - height: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("h", value: h) - opt.set("v", value: v) - if let `left` = `left` { - opt.set("left", value: `left`) - } - if let top = top { - opt.set("top", value: top) - } - if let width = width { - opt.set("width", value: width) - } - if let height = height { - opt.set("height", value: height) - } - opt.set("out", value: &out) - - try Self.call("measure", options: &opt) - } - } - - /// Merge two images - /// - /// - Parameters: - /// - sec: Secondary image - /// - direction: Horizontal or vertical merge - /// - dx: Horizontal displacement from sec to ref - /// - dy: Vertical displacement from sec to ref - /// - mblend: Maximum blend size - public func merge( - sec: some VIPSImageProtocol, - direction: VipsDirection, - dx: Int, - dy: Int, - mblend: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("ref", value: self) - opt.set("sec", value: sec) - opt.set("direction", value: direction) - opt.set("dx", value: dx) - opt.set("dy", value: dy) - if let mblend = mblend { - opt.set("mblend", value: mblend) - } - opt.set("out", value: &out) - - try Self.call("merge", options: &opt) - } - } - - /// Mosaic two images - /// - /// - Parameters: - /// - sec: Secondary image - /// - direction: Horizontal or vertical mosaic - /// - xref: Position of reference tie-point - /// - yref: Position of reference tie-point - /// - xsec: Position of secondary tie-point - /// - ysec: Position of secondary tie-point - /// - hwindow: Half window size - /// - harea: Half area size - /// - mblend: Maximum blend size - /// - bandno: Band to search for features on - public func mosaic( - sec: some VIPSImageProtocol, - direction: VipsDirection, - xref: Int, - yref: Int, - xsec: Int, - ysec: Int, - hwindow: Int? = nil, - harea: Int? = nil, - mblend: Int? = nil, - bandno: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("ref", value: self) - opt.set("sec", value: sec) - opt.set("direction", value: direction) - opt.set("xref", value: xref) - opt.set("yref", value: yref) - opt.set("xsec", value: xsec) - opt.set("ysec", value: ysec) - if let hwindow = hwindow { - opt.set("hwindow", value: hwindow) - } - if let harea = harea { - opt.set("harea", value: harea) - } - if let mblend = mblend { - opt.set("mblend", value: mblend) - } - if let bandno = bandno { - opt.set("bandno", value: bandno) - } - opt.set("out", value: &out) - - try Self.call("mosaic", options: &opt) - } - } - - /// First-order mosaic of two images - /// - /// - Parameters: - /// - sec: Secondary image - /// - direction: Horizontal or vertical mosaic - /// - xr1: Position of first reference tie-point - /// - yr1: Position of first reference tie-point - /// - xs1: Position of first secondary tie-point - /// - ys1: Position of first secondary tie-point - /// - xr2: Position of second reference tie-point - /// - yr2: Position of second reference tie-point - /// - xs2: Position of second secondary tie-point - /// - ys2: Position of second secondary tie-point - /// - hwindow: Half window size - /// - harea: Half area size - /// - search: Search to improve tie-points - /// - interpolate: Interpolate pixels with this - /// - mblend: Maximum blend size - public func mosaic1( - sec: some VIPSImageProtocol, - direction: VipsDirection, - xr1: Int, - yr1: Int, - xs1: Int, - ys1: Int, - xr2: Int, - yr2: Int, - xs2: Int, - ys2: Int, - hwindow: Int? = nil, - harea: Int? = nil, - search: Bool? = nil, - interpolate: VIPSInterpolate? = nil, - mblend: Int? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("ref", value: self) - opt.set("sec", value: sec) - opt.set("direction", value: direction) - opt.set("xr1", value: xr1) - opt.set("yr1", value: yr1) - opt.set("xs1", value: xs1) - opt.set("ys1", value: ys1) - opt.set("xr2", value: xr2) - opt.set("yr2", value: yr2) - opt.set("xs2", value: xs2) - opt.set("ys2", value: ys2) - if let hwindow = hwindow { - opt.set("hwindow", value: hwindow) - } - if let harea = harea { - opt.set("harea", value: harea) - } - if let search = search { - opt.set("search", value: search) - } - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - if let mblend = mblend { - opt.set("mblend", value: mblend) - } - opt.set("out", value: &out) - - try Self.call("mosaic1", options: &opt) - } - } - - /// Pick most-significant byte from an image - /// - /// - Parameters: - /// - band: Band to msb - public func msb(band: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let band = band { - opt.set("band", value: band) - } - opt.set("out", value: &out) - - try Self.call("msb", options: &opt) - } - } - - /// Find threshold for percent of pixels - /// - /// - Parameters: - /// - percent: Percent of pixels - public func percent(_ percent: Double) throws -> Int { - var opt = VIPSOption() - - var out: Int = 0 - - opt.set("in", value: self.image) - opt.set("percent", value: percent) - opt.set("threshold", value: &out) - - try Self.call("percent", options: &opt) - - return out - } - - /// Prewitt edge detector - public func prewitt() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("prewitt", options: &opt) - } - } - - /// Unpack radiance coding to float rgb - public func rad2float() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("rad2float", options: &opt) - } - } - - /// Rebuild an mosaiced image - /// - /// - Parameters: - /// - oldStr: Search for this string - /// - newStr: And swap for this string - public func remosaic(oldStr: String, newStr: String) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("old_str", value: oldStr) - opt.set("new_str", value: newStr) - opt.set("out", value: &out) - - try Self.call("remosaic", options: &opt) - } - } - - /// Replicate an image - /// - /// - Parameters: - /// - across: Repeat this many times horizontally - /// - down: Repeat this many times vertically - public func replicate(across: Int, down: Int) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("across", value: across) - opt.set("down", value: down) - opt.set("out", value: &out) - - try Self.call("replicate", options: &opt) - } - } - - /// Scharr edge detector - public func scharr() throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("out", value: &out) - - try Self.call("scharr", options: &opt) - } - } - - /// Check sequential access - /// - /// - Parameters: - /// - tileHeight: Tile height in pixels - public func sequential(tileHeight: Int? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - if let tileHeight = tileHeight { - opt.set("tile_height", value: tileHeight) - } - opt.set("out", value: &out) - - try Self.call("sequential", options: &opt) - } - } - - /// Spatial correlation - /// - /// - Parameters: - /// - ref: Input reference image - public func spcor(ref: some VIPSImageProtocol) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("ref", value: ref) - opt.set("out", value: &out) - - try Self.call("spcor", options: &opt) - } - } - - /// Statistical difference - /// - /// - Parameters: - /// - width: Window width in pixels - /// - height: Window height in pixels - /// - s0: New deviation - /// - b: Weight of new deviation - /// - m0: New mean - /// - a: Weight of new mean - public func stdif( - width: Int, - height: Int, - s0: Double? = nil, - b: Double? = nil, - m0: Double? = nil, - a: Double? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("width", value: width) - opt.set("height", value: height) - if let s0 = s0 { - opt.set("s0", value: s0) - } - if let b = b { - opt.set("b", value: b) - } - if let m0 = m0 { - opt.set("m0", value: m0) - } - if let a = a { - opt.set("a", value: a) - } - opt.set("out", value: &out) - - try Self.call("stdif", options: &opt) - } - } - - /// Subsample an image - /// - /// - Parameters: - /// - xfac: Horizontal subsample factor - /// - yfac: Vertical subsample factor - /// - point: Point sample - public func subsample(xfac: Int, yfac: Int, point: Bool? = nil) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("input", value: self) - opt.set("xfac", value: xfac) - opt.set("yfac", value: yfac) - if let point = point { - opt.set("point", value: point) - } - opt.set("out", value: &out) - - try Self.call("subsample", options: &opt) - } - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - #if SHIM_VIPS_VERSION_8_17 - /// Create an sdf image - /// - /// - Parameters: - /// - width: Image width in pixels - /// - height: Image height in pixels - /// - shape: SDF shape to create - /// - r: Radius - /// - a: Point a - /// - b: Point b - /// - corners: Corner radii - public static func sdf( - width: Int, - height: Int, - shape: VipsSdfShape, - r: Double? = nil, - a: [Double]? = nil, - b: [Double]? = nil, - corners: [Double]? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("shape", value: shape) - if let r = r { - opt.set("r", value: r) - } - if let a = a { - opt.set("a", value: a) - } - if let b = b { - opt.set("b", value: b) - } - if let corners = corners { - opt.set("corners", value: corners) - } - opt.set("out", value: &out) - - try Self.call("sdf", options: &opt) - } - } - #endif - - /// Find the index of the first non-zero pixel in tests - /// - /// - Parameters: - /// - tests: Table of images to test - public static func `switch`(tests: [VIPSImage]) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("tests", value: tests) - opt.set("out", value: &out) - - try Self.call("switch", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/morphology.generated.swift b/Sources/VIPS/Generated/morphology.generated.swift deleted file mode 100644 index 799e5e9..0000000 --- a/Sources/VIPS/Generated/morphology.generated.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// morphology.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Count lines in an image - /// - /// - Parameters: - /// - direction: Countlines left-right or up-down - public func countlines(direction: VipsDirection) throws -> Double { - var opt = VIPSOption() - - var out: Double = 0.0 - - opt.set("in", value: self.image) - opt.set("direction", value: direction) - opt.set("nolines", value: &out) - - try Self.call("countlines", options: &opt) - - return out - } - - /// Morphology operation - /// - /// - Parameters: - /// - mask: Input matrix image - /// - morph: Morphological operation to perform - public func morph(mask: some VIPSImageProtocol, morph: VipsOperationMorphology) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("mask", value: mask) - opt.set("morph", value: morph) - opt.set("out", value: &out) - - try Self.call("morph", options: &opt) - } - } - - /// Rank filter - /// - /// - Parameters: - /// - width: Window width in pixels - /// - height: Window height in pixels - /// - index: Select pixel at index - public func rank(width: Int, height: Int, index: Int) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("width", value: width) - opt.set("height", value: height) - opt.set("index", value: index) - opt.set("out", value: &out) - - try Self.call("rank", options: &opt) - } - } - -} diff --git a/Sources/VIPS/Generated/resample.generated.swift b/Sources/VIPS/Generated/resample.generated.swift deleted file mode 100644 index a9e38cd..0000000 --- a/Sources/VIPS/Generated/resample.generated.swift +++ /dev/null @@ -1,349 +0,0 @@ -// -// resample.generated.swift -// -// Generated by VIPS Swift Code Generator -// DO NOT EDIT - This file is automatically generated -// - -import Cvips -import CvipsShim - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Resample with a map image - /// - /// - Parameters: - /// - index: Index pixels with this - /// - interpolate: Interpolate pixels with this - /// - background: Background value - /// - premultiplied: Images have premultiplied alpha - /// - extend: How to generate the extra pixels - public func mapim( - index: some VIPSImageProtocol, - interpolate: VIPSInterpolate? = nil, - background: [Double]? = nil, - premultiplied: Bool? = nil, - extend: VipsExtend? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("index", value: index) - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - if let background = background { - opt.set("background", value: background) - } - if let premultiplied = premultiplied { - opt.set("premultiplied", value: premultiplied) - } - if let extend = extend { - opt.set("extend", value: extend) - } - opt.set("out", value: &out) - - try Self.call("mapim", options: &opt) - } - } - - /// Resample an image with a quadratic transform - /// - /// - Parameters: - /// - coeff: Coefficient matrix - /// - interpolate: Interpolate values with this - public func quadratic(coeff: some VIPSImageProtocol, interpolate: VIPSInterpolate? = nil) throws - -> Self - { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("coeff", value: coeff) - if let interpolate = interpolate { - opt.set("interpolate", value: interpolate) - } - opt.set("out", value: &out) - - try Self.call("quadratic", options: &opt) - } - } - - /// Generate thumbnail from image - /// - /// - Parameters: - /// - width: Size to this width - /// - height: Size to this height - /// - size: Only upsize, only downsize, or both - /// - noRotate: Don't use orientation tags to rotate image upright - /// - crop: Reduce to fill target rectangle, then crop - /// - linear: Reduce in linear light - /// - inputProfile: Fallback input profile - /// - outputProfile: Fallback output profile - /// - intent: Rendering intent - /// - failOn: Error level to fail on - public func thumbnailImage( - width: Int, - height: Int? = nil, - size: VipsSize? = nil, - noRotate: Bool? = nil, - crop: VipsInteresting? = nil, - linear: Bool? = nil, - inputProfile: String? = nil, - outputProfile: String? = nil, - intent: VipsIntent? = nil, - failOn: VipsFailOn? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("in", value: self) - opt.set("width", value: width) - if let height = height { - opt.set("height", value: height) - } - if let size = size { - opt.set("size", value: size) - } - if let noRotate = noRotate { - opt.set("no_rotate", value: noRotate) - } - if let crop = crop { - opt.set("crop", value: crop) - } - if let linear = linear { - opt.set("linear", value: linear) - } - if let inputProfile = inputProfile { - opt.set("input_profile", value: inputProfile) - } - if let outputProfile = outputProfile { - opt.set("output_profile", value: outputProfile) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - opt.set("out", value: &out) - - try Self.call("thumbnail_image", options: &opt) - } - } - -} - -extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ { - - /// Generate thumbnail from file - /// - /// - Parameters: - /// - filename: Filename to read from - /// - width: Size to this width - /// - height: Size to this height - /// - size: Only upsize, only downsize, or both - /// - noRotate: Don't use orientation tags to rotate image upright - /// - crop: Reduce to fill target rectangle, then crop - /// - linear: Reduce in linear light - /// - inputProfile: Fallback input profile - /// - outputProfile: Fallback output profile - /// - intent: Rendering intent - /// - failOn: Error level to fail on - public static func thumbnail( - filename: String, - width: Int, - height: Int? = nil, - size: VipsSize? = nil, - noRotate: Bool? = nil, - crop: VipsInteresting? = nil, - linear: Bool? = nil, - inputProfile: String? = nil, - outputProfile: String? = nil, - intent: VipsIntent? = nil, - failOn: VipsFailOn? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("filename", value: filename) - opt.set("width", value: width) - if let height = height { - opt.set("height", value: height) - } - if let size = size { - opt.set("size", value: size) - } - if let noRotate = noRotate { - opt.set("no_rotate", value: noRotate) - } - if let crop = crop { - opt.set("crop", value: crop) - } - if let linear = linear { - opt.set("linear", value: linear) - } - if let inputProfile = inputProfile { - opt.set("input_profile", value: inputProfile) - } - if let outputProfile = outputProfile { - opt.set("output_profile", value: outputProfile) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - opt.set("out", value: &out) - - try Self.call("thumbnail", options: &opt) - } - } - - /// Generate thumbnail from buffer - /// - /// - Parameters: - /// - buffer: Buffer to load from - /// - width: Size to this width - /// - optionString: Options that are passed on to the underlying loader - /// - height: Size to this height - /// - size: Only upsize, only downsize, or both - /// - noRotate: Don't use orientation tags to rotate image upright - /// - crop: Reduce to fill target rectangle, then crop - /// - linear: Reduce in linear light - /// - inputProfile: Fallback input profile - /// - outputProfile: Fallback output profile - /// - intent: Rendering intent - /// - failOn: Error level to fail on - @inlinable - public static func thumbnail( - buffer: VIPSBlob, - width: Int, - optionString: String? = nil, - height: Int? = nil, - size: VipsSize? = nil, - noRotate: Bool? = nil, - crop: VipsInteresting? = nil, - linear: Bool? = nil, - inputProfile: String? = nil, - outputProfile: String? = nil, - intent: VipsIntent? = nil, - failOn: VipsFailOn? = nil - ) throws -> Self { - // the operation will retain the blob - try buffer.withVipsBlob { blob in - try Self { out in - var opt = VIPSOption() - - opt.set("buffer", value: blob) - opt.set("width", value: width) - if let optionString = optionString { - opt.set("option_string", value: optionString) - } - if let height = height { - opt.set("height", value: height) - } - if let size = size { - opt.set("size", value: size) - } - if let noRotate = noRotate { - opt.set("no_rotate", value: noRotate) - } - if let crop = crop { - opt.set("crop", value: crop) - } - if let linear = linear { - opt.set("linear", value: linear) - } - if let inputProfile = inputProfile { - opt.set("input_profile", value: inputProfile) - } - if let outputProfile = outputProfile { - opt.set("output_profile", value: outputProfile) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - opt.set("out", value: &out) - - try Self.call("thumbnail_buffer", options: &opt) - } - } - } - - /// Generate thumbnail from source - /// - /// - Parameters: - /// - source: Source to load from - /// - width: Size to this width - /// - optionString: Options that are passed on to the underlying loader - /// - height: Size to this height - /// - size: Only upsize, only downsize, or both - /// - noRotate: Don't use orientation tags to rotate image upright - /// - crop: Reduce to fill target rectangle, then crop - /// - linear: Reduce in linear light - /// - inputProfile: Fallback input profile - /// - outputProfile: Fallback output profile - /// - intent: Rendering intent - /// - failOn: Error level to fail on - public static func thumbnail( - source: VIPSSource, - width: Int, - optionString: String? = nil, - height: Int? = nil, - size: VipsSize? = nil, - noRotate: Bool? = nil, - crop: VipsInteresting? = nil, - linear: Bool? = nil, - inputProfile: String? = nil, - outputProfile: String? = nil, - intent: VipsIntent? = nil, - failOn: VipsFailOn? = nil - ) throws -> Self { - return try Self { out in - var opt = VIPSOption() - - opt.set("source", value: source) - opt.set("width", value: width) - if let optionString = optionString { - opt.set("option_string", value: optionString) - } - if let height = height { - opt.set("height", value: height) - } - if let size = size { - opt.set("size", value: size) - } - if let noRotate = noRotate { - opt.set("no_rotate", value: noRotate) - } - if let crop = crop { - opt.set("crop", value: crop) - } - if let linear = linear { - opt.set("linear", value: linear) - } - if let inputProfile = inputProfile { - opt.set("input_profile", value: inputProfile) - } - if let outputProfile = outputProfile { - opt.set("output_profile", value: outputProfile) - } - if let intent = intent { - opt.set("intent", value: intent) - } - if let failOn = failOn { - opt.set("fail_on", value: failOn) - } - opt.set("out", value: &out) - - try Self.call("thumbnail_source", options: &opt) - } - } - -} diff --git a/Sources/VIPSGenerator/CodeGenerator.swift b/Sources/VIPSGenerator/CodeGenerator.swift new file mode 100644 index 0000000..57d7312 --- /dev/null +++ b/Sources/VIPSGenerator/CodeGenerator.swift @@ -0,0 +1,438 @@ +// +// CodeGenerator.swift +// VIPSGenerator +// +// Swift code generator for VIPS operations +// + +import Cvips +import CvipsShim +import Foundation +import VIPSIntrospection + +/// Code generator for VIPS operation wrappers +struct CodeGenerator { + + // MARK: - Skip Conditions + + /// Check if this operation should be skipped + /// - Parameter details: The operation details to check + /// - Returns: true if the operation should be skipped + func shouldSkip(_ details: VIPSOperationDetails) -> Bool { + // Skip deprecated operations + if details.isDeprecated { + return true + } + + // Skip operations without outputs (unless it's a save operation or operations like avg/min/max) + if details.requiredOutput.isEmpty { + // Allow save operations even without outputs + if details.nickname.contains("save") { + return false + } + // Otherwise skip + return true + } + + // Skip operations ending in _const (they are handled by overloads) + // EXCEPT we actually need to generate the _const operations themselves + // The skip happens at a different level (not here) + + return false + } + + // MARK: - Main Generation + + /// Generate the main wrapper method for an operation + /// - Parameter details: The operation details + /// - Returns: Generated Swift code, or nil if should be skipped + func generateWrapper(for details: VIPSOperationDetails) -> String? { + // Check if we should skip this operation + if shouldSkip(details) { + return nil + } + + // Get the first required output (if any) + let firstOutput = details.requiredOutput.first + let hasImageOutput = firstOutput.flatMap { details.parameters[$0] }.map { param in + param.parameterType == vips_image_get_type() + } ?? false + + var lines: [String] = [] + + // Generate documentation + lines.append(contentsOf: generateDocumentation(for: details)) + + // Generate method signature + let signature = generateSignature(for: details, hasImageOutput: hasImageOutput) + lines.append(signature) + + // Generate method body + lines.append(contentsOf: generateBody(for: details, hasImageOutput: hasImageOutput)) + + return lines.joined(separator: "\n") + } + + // MARK: - Documentation Generation + + /// Generate Swift doc comments for an operation + private func generateDocumentation(for details: VIPSOperationDetails) -> [String] { + var lines: [String] = [] + + // Capitalize the first letter of description + let description = details.description.prefix(1).uppercased() + details.description.dropFirst() + lines.append(" /// \(description)") + + // Add parameter documentation if there are any parameters + let allParams = details.methodArgs + details.optionalInput + if !allParams.isEmpty { + lines.append(" ///") + lines.append(" /// - Parameters:") + for paramName in allParams { + if let param = details.parameters[paramName] { + let swiftName = swiftizeParam(paramName) + lines.append(" /// - \(swiftName): \(param.description)") + } + } + } + + return lines + } + + // MARK: - Signature Generation + + /// Generate the method signature + private func generateSignature(for details: VIPSOperationDetails, hasImageOutput: Bool) -> String { + // Determine if this is a static or instance method + let isInstanceMethod = details.memberX != nil + let isLoadOperation = details.nickname.contains("load") + + // Build function name + var funcName = snakeToCamel(details.nickname) + + // Remove common suffixes for overloaded methods + let overloadSuffixes = ["Buffer", "Source", "Target"] + for suffix in overloadSuffixes { + if funcName.hasSuffix(suffix) { + funcName = String(funcName.dropLast(suffix.count)) + break + } + } + + // Escape function name if it's a Swift keyword + if swiftKeywords.contains(funcName) { + funcName = "`\(funcName)`" + } + + // Determine method type + let methodType: String + if isLoadOperation { + methodType = "public static func" + } else if isInstanceMethod { + methodType = "public func" + } else { + methodType = "public static func" + } + + // Build parameters + var params: [String] = [] + var isFirstParam = true + + // Add required parameters (excluding memberX) + for paramName in details.methodArgs { + guard let param = details.parameters[paramName] else { continue } + + let swiftParamName = swiftizeParam(paramName) + let swiftType = getSwiftType(param.parameterType) + + // Special handling for "right" parameter - rename to "rhs" with _ label + if paramName == "right" { + params.append("_ rhs: \(swiftType)") + } + // Special handling for "in" parameter when it's the first parameter - hide label + else if paramName == "in" && isFirstParam { + params.append("_ `in`: \(swiftType)") + } + // Check if first parameter name matches function name (omit label if so) + else if isFirstParam { + let cleanFuncName = funcName.trimmingCharacters(in: CharacterSet(charactersIn: "`")) + if swiftParamName == cleanFuncName || cleanFuncName.hasSuffix(swiftParamName.prefix(1).uppercased() + swiftParamName.dropFirst()) { + params.append("_ \(swiftParamName): \(swiftType)") + } else { + params.append("\(swiftParamName): \(swiftType)") + } + } else { + params.append("\(swiftParamName): \(swiftType)") + } + + isFirstParam = false + } + + // Add optional parameters + for paramName in details.optionalInput { + guard let param = details.parameters[paramName] else { continue } + + let swiftParamName = swiftizeParam(paramName) + let swiftType = getSwiftType(param.parameterType) + params.append("\(swiftParamName): \(swiftType)? = nil") + } + + // Build return type + var signature = " \(methodType) \(funcName)(\(params.joined(separator: ", "))) throws" + + // Add return type + if hasImageOutput { + signature += " -> Self" + } else if let firstOutput = details.requiredOutput.first, + let outputParam = details.parameters[firstOutput] { + // Handle other output types + if outputParam.parameterType == shim_VIPS_TYPE_BLOB() { + signature += " -> VIPSBlob" + } else { + let outputType = getSwiftType(outputParam.parameterType) + signature += " -> \(outputType)" + } + } else if details.nickname.contains("save") { + // Save operations don't return anything + } + + signature += " {" + + return signature + } + + // MARK: - Body Generation + + /// Generate the method body + private func generateBody(for details: VIPSOperationDetails, hasImageOutput: Bool) -> [String] { + var lines: [String] = [] + + // Check if we have blob parameters + let hasBlobParams = (details.methodArgs + details.optionalInput).contains { paramName in + details.parameters[paramName]?.parameterType == shim_VIPS_TYPE_BLOB() + } + + let firstOutput = details.requiredOutput.first + let isInstanceMethod = details.memberX != nil + + if hasImageOutput { + // Image output operations + if hasBlobParams { + // Find the blob parameter + if let blobParam = (details.methodArgs + details.optionalInput).first(where: { paramName in + details.parameters[paramName]?.parameterType == shim_VIPS_TYPE_BLOB() + }) { + let blobSwiftName = swiftizeParam(blobParam) + lines.append(" // the operation will retain the blob") + lines.append(" try \(blobSwiftName).withVipsBlob { blob in") + lines.append(" try Self { out in") + lines.append(" var opt = VIPSOption()") + lines.append("") + + // Set parameters with blob handling + lines.append(contentsOf: generateParameterSetting( + for: details, + indent: " ", + blobParamName: blobParam + )) + + lines.append(" opt.set(\"out\", value: &out)") + lines.append("") + lines.append(" try Self.call(\"\(details.nickname)\", options: &opt)") + lines.append(" }") + lines.append(" }") + } + } else { + // No blob parameters + lines.append(" return try Self { out in") + lines.append(" var opt = VIPSOption()") + lines.append("") + + // Set parameters + lines.append(contentsOf: generateParameterSetting( + for: details, + indent: " ", + blobParamName: nil + )) + + lines.append(" opt.set(\"out\", value: &out)") + lines.append("") + lines.append(" try Self.call(\"\(details.nickname)\", options: &opt)") + lines.append(" }") + } + } else if let firstOutput = firstOutput, + let outputParam = details.parameters[firstOutput] { + // Non-image outputs (Double, [Double], VIPSBlob, etc.) + lines.append(" var opt = VIPSOption()") + lines.append("") + + // Initialize output variable + let outputType = getSwiftType(outputParam.parameterType) + if outputParam.parameterType == shim_VIPS_TYPE_BLOB() { + lines.append(" let out: UnsafeMutablePointer?> = .allocate(capacity: 1)") + lines.append(" out.initialize(to: nil)") + lines.append(" defer {") + lines.append(" out.deallocate()") + lines.append(" }") + } else if outputType == "Double" { + lines.append(" var out: Double = 0.0") + } else if outputType == "Int" { + lines.append(" var out: Int = 0") + } else if outputType == "Bool" { + lines.append(" var out: Bool = false") + } else if outputType == "String" { + lines.append(" var out: String = \"\"") + } else if outputType == "[Double]" { + lines.append(" var out: UnsafeMutablePointer! = .allocate(capacity: 1)") + } else if outputType == "[Int]" { + lines.append(" var out: [Int] = []") + } else { + lines.append(" var out: \(outputType) = /* TODO: initialize \(outputType) */") + } + lines.append("") + + // Set parameters - use self.image for instance methods with non-image outputs + lines.append(contentsOf: generateParameterSetting( + for: details, + indent: " ", + blobParamName: nil, + useImageProperty: isInstanceMethod + )) + + // Set output parameter + let vipsOutputName = normalizeVipsParamName(firstOutput) + if outputParam.parameterType == shim_VIPS_TYPE_BLOB() { + lines.append(" opt.set(\"\(vipsOutputName)\", value: out)") + } else { + lines.append(" opt.set(\"\(vipsOutputName)\", value: &out)") + } + + lines.append("") + lines.append(" try Self.call(\"\(details.nickname)\", options: &opt)") + lines.append("") + + // Return the output + if outputParam.parameterType == shim_VIPS_TYPE_BLOB() { + lines.append(" guard let vipsBlob = out.pointee else {") + lines.append(" throw VIPSError(\"Failed to get buffer from \(details.nickname)\")") + lines.append(" }") + lines.append("") + lines.append(" return VIPSBlob(vipsBlob)") + } else if outputType == "[Double]" { + lines.append(" guard let out else {") + lines.append(" throw VIPSError(\"\(details.nickname): no output\")") + lines.append(" }") + lines.append("") + lines.append(" defer {") + lines.append(" vips_area_unref(shim_vips_area(out))") + lines.append(" }") + lines.append(" ") + lines.append(" var length = Int32(0)") + lines.append(" let doubles = vips_array_double_get(out, &length)") + lines.append(" let buffer = UnsafeBufferPointer(start: doubles, count: Int(length))") + lines.append(" return Array(buffer)") + } else { + lines.append(" return out") + } + } else if details.nickname.contains("save") && isInstanceMethod { + // Save operations that don't return anything + lines.append(" var opt = VIPSOption()") + lines.append("") + + // Set parameters + lines.append(contentsOf: generateParameterSetting( + for: details, + indent: " ", + blobParamName: nil + )) + + lines.append("") + lines.append(" try Self.call(\"\(details.nickname)\", options: &opt)") + } else { + // Other operations without outputs + lines.append(" var opt = VIPSOption()") + lines.append("") + + // Set parameters + lines.append(contentsOf: generateParameterSetting( + for: details, + indent: " ", + blobParamName: nil + )) + + lines.append("") + lines.append(" try Self.call(\"\(details.nickname)\", options: &opt)") + } + + lines.append(" }") + + return lines + } + + // MARK: - Parameter Setting + + /// Normalize parameter name for VIPS C API + /// GObject introspection may return hyphens, but VIPS uses underscores internally + private func normalizeVipsParamName(_ name: String) -> String { + return name.replacingOccurrences(of: "-", with: "_") + } + + /// Generate code to set operation parameters + private func generateParameterSetting( + for details: VIPSOperationDetails, + indent: String, + blobParamName: String?, + useImageProperty: Bool = false + ) -> [String] { + var lines: [String] = [] + + // Set the input image if this is an instance method + if let memberX = details.memberX { + let vipsParamName = normalizeVipsParamName(memberX) + if useImageProperty { + lines.append("\(indent)opt.set(\"\(vipsParamName)\", value: self.image)") + } else { + lines.append("\(indent)opt.set(\"\(vipsParamName)\", value: self)") + } + } + + // Set required parameters + for paramName in details.methodArgs { + let vipsParamName = normalizeVipsParamName(paramName) + let swiftParamName: String + if paramName == "right" { + swiftParamName = "rhs" + } else if paramName == "in" { + swiftParamName = "`in`" + } else { + swiftParamName = swiftizeParam(paramName) + } + + // Special handling for blob parameters + if paramName == blobParamName { + lines.append("\(indent)opt.set(\"\(vipsParamName)\", value: blob)") + } else { + lines.append("\(indent)opt.set(\"\(vipsParamName)\", value: \(swiftParamName))") + } + } + + // Set optional parameters + for paramName in details.optionalInput { + let vipsParamName = normalizeVipsParamName(paramName) + let swiftParamName = swiftizeParam(paramName) + + // Special handling for blob parameters + if paramName == blobParamName { + lines.append("\(indent)if let \(swiftParamName) = \(swiftParamName) {") + lines.append("\(indent) opt.set(\"\(vipsParamName)\", value: blob)") + lines.append("\(indent)}") + } else { + lines.append("\(indent)if let \(swiftParamName) = \(swiftParamName) {") + lines.append("\(indent) opt.set(\"\(vipsParamName)\", value: \(swiftParamName))") + lines.append("\(indent)}") + } + } + + return lines + } +} diff --git a/Sources/VIPSGenerator/FileWriter.swift b/Sources/VIPSGenerator/FileWriter.swift new file mode 100644 index 0000000..92dd6be --- /dev/null +++ b/Sources/VIPSGenerator/FileWriter.swift @@ -0,0 +1,169 @@ +// +// FileWriter.swift +// VIPSGenerator +// +// Handles writing generated Swift code to files +// + +import Foundation + +struct FileWriter { + let outputDirectory: URL + + init(outputDirectory: String) { + self.outputDirectory = URL(fileURLWithPath: outputDirectory) + } + + /// Write methods for a category to a file + /// - Parameters: + /// - category: The category name (e.g., "Arithmetic", "Foreign/JPEG") + /// - methods: Array of tuples with nickname and generated code + func writeCategory(_ category: String, methods: [(nickname: String, code: String)]) throws { + // Determine file path based on category + let (filepath, filename) = getFilePath(for: category) + + // Ensure directory exists + let directory = filepath.deletingLastPathComponent() + try ensureDirectoryExists(directory) + + // Check if any operations need CvipsShim import + let needsCvipsShim = checkNeedsCvipsShim(methods: methods) + + // Separate operations into static and instance methods + let (staticMethods, instanceMethods) = separateMethods(methods) + + // Generate file content + let header = generateHeader(filename: filename, needsCvipsShim: needsCvipsShim) + var content = header + + // Write instance methods + if !instanceMethods.isEmpty { + content += "extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ {\n\n" + + for (_, code) in instanceMethods { + content += code + content += "\n\n" + } + + // Add convenience methods for relational operations in the arithmetic category + if category == "Arithmetic" { + let overloads = OverloadGenerators() + let relationalMethods = overloads.generateRelationalConvenienceMethods() + if !relationalMethods.isEmpty { + content += relationalMethods + content += "\n\n" + } + } + + content += "}\n" + } + + // Write static methods + if !staticMethods.isEmpty { + if !instanceMethods.isEmpty { + content += "\n" + } + content += "extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ {\n\n" + + for (_, code) in staticMethods { + content += code + content += "\n\n" + } + + content += "}\n" + } + + // Write to file + try content.write(to: filepath, atomically: true, encoding: .utf8) + } + + /// Generate the file header + /// - Parameters: + /// - filename: The filename + /// - needsCvipsShim: Whether CvipsShim import is needed + /// - Returns: The header string + func generateHeader(filename: String, needsCvipsShim: Bool) -> String { + var header = "//\n" + header += "// \(filename)\n" + header += "//\n" + header += "// Generated by VIPS Swift Code Generator\n" + header += "// DO NOT EDIT - This file is automatically generated\n" + header += "//\n\n" + header += "import Cvips\n" + if needsCvipsShim { + header += "import CvipsShim\n" + } + header += "\n" + return header + } + + /// Ensure directory exists + /// - Parameter path: The directory path + func ensureDirectoryExists(_ path: URL) throws { + let fileManager = FileManager.default + if !fileManager.fileExists(atPath: path.path) { + try fileManager.createDirectory(at: path, withIntermediateDirectories: true) + } + } + + // MARK: - Public helpers + + /// Get file path and filename for a category + /// - Parameter category: The category name (e.g., "Arithmetic", "Foreign/JPEG") + /// - Returns: Tuple of (filepath, filename) + public func getFilePath(for category: String) -> (URL, String) { + let categoryParts = category.split(separator: "/") + + if categoryParts.count > 1 { + // Subcategory like Foreign/JPEG + let mainCategory = String(categoryParts[0]) + let subCategory = String(categoryParts[1]) + let subDir = outputDirectory.appendingPathComponent(mainCategory) + let filename = "foreign_\(subCategory.lowercased()).generated.swift" + let filepath = subDir.appendingPathComponent(filename) + return (filepath, filename) + } else { + // Top-level category like Arithmetic + let filename = "\(category.lowercased()).generated.swift" + let filepath = outputDirectory.appendingPathComponent(filename) + return (filepath, filename) + } + } + + /// Check if any methods need CvipsShim import + /// - Parameter methods: The methods to check + /// - Returns: true if CvipsShim is needed + private func checkNeedsCvipsShim(methods: [(nickname: String, code: String)]) -> Bool { + for (_, code) in methods { + // Check for various indicators that CvipsShim is needed + if code.contains("vips_blob_copy") || + code.contains("vips_blob_new") || + code.contains("vips_array_double_get") || + code.contains("withVipsBlob") || + code.contains("shim_vips_area") { + return true + } + } + return false + } + + /// Separate methods into static and instance methods + /// - Parameter methods: The methods to separate + /// - Returns: Tuple of (static methods, instance methods) + private func separateMethods(_ methods: [(nickname: String, code: String)]) + -> ([(nickname: String, code: String)], [(nickname: String, code: String)]) + { + var staticMethods: [(nickname: String, code: String)] = [] + var instanceMethods: [(nickname: String, code: String)] = [] + + for method in methods { + if method.code.contains("public static func") { + staticMethods.append(method) + } else { + instanceMethods.append(method) + } + } + + return (staticMethods, instanceMethods) + } +} diff --git a/Sources/VIPSGenerator/OperationAnalysis.swift b/Sources/VIPSGenerator/OperationAnalysis.swift new file mode 100644 index 0000000..d189b95 --- /dev/null +++ b/Sources/VIPSGenerator/OperationAnalysis.swift @@ -0,0 +1,26 @@ +// +// OperationAnalysis.swift +// VIPSGenerator +// +// Helper functions for analyzing VIPS operations +// + +import VIPSIntrospection +import Cvips +import CvipsShim + +/// Check if operation has any blob input parameters +/// - Parameter opInfo: The operation information +/// - Returns: true if any input parameter has VIPS_TYPE_BLOB type +func hasBufferParameter(_ opInfo: VIPSOperationInfo) -> Bool { + // Check all parameters that are input parameters + for param in opInfo.parameters { + if param.isInput { + // Check if the parameter type is VIPS_TYPE_BLOB + if param.parameterType == shim_VIPS_TYPE_BLOB() { + return true + } + } + } + return false +} diff --git a/Sources/VIPSGenerator/OperationCategory.swift b/Sources/VIPSGenerator/OperationCategory.swift new file mode 100644 index 0000000..be6ac4e --- /dev/null +++ b/Sources/VIPSGenerator/OperationCategory.swift @@ -0,0 +1,99 @@ +/// Categorize operation based on its name +func getOperationCategory(_ nickname: String) -> String { + let name = nickname.lowercased() + + // Foreign operations (file I/O) + if name.contains("load") || name.contains("save") { + if name.contains("jpeg") || name.contains("jpg") { + return "Foreign/JPEG" + } else if name.contains("png") { + return "Foreign/PNG" + } else if name.contains("webp") { + return "Foreign/WebP" + } else if name.contains("tiff") || name.contains("tif") { + return "Foreign/TIFF" + } else if name.contains("pdf") { + return "Foreign/PDF" + } else if name.contains("svg") { + return "Foreign/SVG" + } else if name.contains("heif") || name.contains("heic") { + return "Foreign/HEIF" + } else if name.contains("gif") { + return "Foreign/GIF" + } else { + return "Foreign/Other" + } + } + + // Arithmetic operations + let arithmeticOps = ["add", "subtract", "multiply", "divide", "abs", "linear", + "math", "complex", "remainder", "boolean", "relational", + "round", "sign", "avg", "min", "max", "deviate", "sum", + "invert", "stats"] + if arithmeticOps.contains(where: { name.contains($0) }) { + return "Arithmetic" + } + + // Convolution operations + let convOps = ["conv", "sharpen", "blur", "sobel", "canny", "gaussblur"] + if convOps.contains(where: { name.contains($0) }) { + return "Convolution" + } + + // Colour operations + let colourOps = ["colour", "color", "lab", "xyz", "srgb", "rgb", "cmyk", + "hsv", "lch", "yxy", "scrgb", "icc"] + if colourOps.contains(where: { name.contains($0) }) { + return "Colour" + } + + // Conversion operations + let conversionOps = ["resize", "rotate", "flip", "crop", "embed", "extract", + "shrink", "reduce", "zoom", "affine", "similarity", "scale", + "autorot", "rot", "recomb", "bandjoin", "bandrank", + "bandsplit", "cast", "copy", "tilecache", "arrayjoin", + "grid", "transpose", "wrap", "unpremultiply", "premultiply", + "composite", "join", "insert"] + if conversionOps.contains(where: { name.contains($0) }) { + return "Conversion" + } + + // Create operations + let createOps = ["black", "xyz", "grey", "mask", "gaussmat", "logmat", "text", + "gaussnoise", "eye", "zone", "sines", "buildlut", "identity", + "fractsurf", "radload", "tonelut", "worley", "perlin"] + if createOps.contains(where: { name.contains($0) }) { + return "Create" + } + + // Draw operations + if name.contains("draw") { + return "Draw" + } + + // Histogram operations + let histOps = ["hist", "heq", "hough", "profile", "project", "spectrum", "phasecor"] + if histOps.contains(where: { name.contains($0) }) { + return "Histogram" + } + + // Morphology operations + let morphOps = ["morph", "erode", "dilate", "median", "rank", "countlines", "labelregions"] + if morphOps.contains(where: { name.contains($0) }) { + return "Morphology" + } + + // Frequency domain operations + let freqOps = ["fft", "invfft", "freqmult", "spectrum", "phasecor"] + if freqOps.contains(where: { name.contains($0) }) { + return "Freqfilt" + } + + // Resample operations + let resampleOps = ["shrink", "reduce", "resize", "thumbnail", "mapim", "quadratic"] + if resampleOps.contains(where: { name.contains($0) }) { + return "Resample" + } + + return "Misc" +} diff --git a/Sources/VIPSGenerator/OverloadGenerators.swift b/Sources/VIPSGenerator/OverloadGenerators.swift new file mode 100644 index 0000000..75bc6b7 --- /dev/null +++ b/Sources/VIPSGenerator/OverloadGenerators.swift @@ -0,0 +1,615 @@ +// +// OverloadGenerators.swift +// VIPSGenerator +// +// Generate various overloads for VIPS operations +// + +import Cvips +import CvipsShim +import Foundation +import VIPSIntrospection + +/// Generates various overloads for VIPS operations including const overloads, +/// buffer overloads, and convenience methods +struct OverloadGenerators { + + // MARK: - Simple Const Overloads + + /// Generate simple const overloads (Double, Int) for _const operations + /// + /// For operations like `remainder_const` that take a 'c' parameter, + /// this generates convenience overloads that accept single Double or Int values. + /// + /// - Parameters: + /// - baseOp: Name of the base operation (e.g., "remainder") + /// - constOp: Details of the const variant operation (e.g., "remainder_const") + /// - Returns: Array of Swift method strings + func generateSimpleConstOverloads(baseOp: String, constOp: VIPSOperationDetails) -> [String] { + // Skip if operation is deprecated + if constOp.isDeprecated { + return [] + } + + // Only generate for image output operations + let requiredOutput = constOp.requiredOutput.filter { $0 != constOp.memberX } + guard let firstOutput = requiredOutput.first, + let outputParam = constOp.parameters[firstOutput], + outputParam.parameterType == vips_image_get_type() else { + return [] + } + + // Only generate for operations with a 'c' parameter + guard constOp.methodArgs.contains("c") || constOp.optionalInput.contains("c") else { + return [] + } + + var funcName = snakeToCamel(baseOp) + if swiftKeywords.contains(funcName) { + funcName = "`\(funcName)`" + } + + let constFuncName = snakeToCamel(constOp.nickname) + + var overloads: [String] = [] + + // Generate Double overload + var result: [String] = [] + result.append(" /// \(constOp.description.prefix(1).uppercased())\(constOp.description.dropFirst())") + result.append(" ///") + result.append(" /// - Parameters:") + result.append(" /// - value: Constant value") + result.append(" public func \(funcName)(_ value: Double) throws -> Self {") + result.append(" return try \(constFuncName)(c: [value])") + result.append(" }") + overloads.append(result.joined(separator: "\n")) + + // Generate Int overload + result = [] + result.append(" /// \(constOp.description.prefix(1).uppercased())\(constOp.description.dropFirst())") + result.append(" ///") + result.append(" /// - Parameters:") + result.append(" /// - value: Constant value") + result.append(" public func \(funcName)(_ value: Int) throws -> Self {") + result.append(" return try \(constFuncName)(c: [Double(value)])") + result.append(" }") + overloads.append(result.joined(separator: "\n")) + + return overloads + } + + // MARK: - VIPSBlob Overload + + /// Generate VIPSBlob overload for buffer operations + /// + /// Creates an overload that accepts VIPSBlob for buffer-based load operations. + /// + /// - Parameter details: Operation details + /// - Returns: Swift method string, or nil if not applicable + func generateVIPSBlobOverload(for details: VIPSOperationDetails) -> String? { + // Skip deprecated operations + if details.isDeprecated { + return nil + } + + // Find the blob parameter + guard let blobParamName = findBlobParameter(in: details) else { + return nil + } + + // Only generate for image output operations + let requiredOutput = details.requiredOutput.filter { $0 != details.memberX } + guard let firstOutput = requiredOutput.first, + let outputParam = details.parameters[firstOutput], + outputParam.parameterType == vips_image_get_type() else { + return nil + } + + // Filter out deprecated and internal parameters + let optionalInput = details.optionalInput.filter { name in + guard let param = details.parameters[name] else { return false } + return !param.isDeprecated && name != "nickname" && name != "description" + } + + var result: [String] = [] + + // Generate documentation + result.append(" /// \(details.description.prefix(1).uppercased())\(details.description.dropFirst())") + + // Add parameter documentation + let allParams = details.methodArgs + optionalInput + if !allParams.isEmpty { + result.append(" ///") + result.append(" /// - Parameters:") + for name in allParams { + if let param = details.parameters[name] { + let paramName = swiftizeParam(name) + if name == blobParamName { + result.append(" /// - \(paramName): Buffer to load from") + } else { + result.append(" /// - \(paramName): \(param.description)") + } + } + } + } + + // Build function signature + var funcName = snakeToCamel(details.nickname) + + // Remove common suffixes for overloaded methods + let overloadSuffixes = ["Buffer", "Source", "Target", "Mime"] + for suffix in overloadSuffixes { + if funcName.hasSuffix(suffix) { + funcName = String(funcName.dropLast(suffix.count)) + break + } + } + + if swiftKeywords.contains(funcName) { + funcName = "`\(funcName)`" + } + + let isLoadOp = details.nickname.contains("load") + let methodType = isLoadOp ? "public static func" : "public func" + + var signature = " \(methodType) \(funcName)(" + + // Add required parameters + var params: [String] = [] + var isFirstParam = true + for name in details.methodArgs { + if name == details.memberX { + continue + } + + guard let param = details.parameters[name] else { continue } + let paramName = swiftizeParam(name) + + // Use VIPSBlob for the blob parameter + let swiftType = name == blobParamName ? "VIPSBlob" : getSwiftType(param.parameterType) + + // Special handling for parameter labels + if name == "right" { + params.append("_ rhs: \(swiftType)") + } else if name == "in" && isFirstParam { + params.append("_ `in`: \(swiftType)") + } else { + // Remove backticks from function name for comparison + let cleanFuncName = funcName.replacingOccurrences(of: "`", with: "") + if isFirstParam && (paramName == cleanFuncName || cleanFuncName.hasSuffix(paramName.prefix(1).uppercased() + paramName.dropFirst())) { + params.append("_ \(paramName): \(swiftType)") + } else { + params.append("\(paramName): \(swiftType)") + } + } + + isFirstParam = false + } + + // Add optional parameters + for name in optionalInput { + if name == blobParamName { + continue // Skip blob parameter as it's already in required params + } + guard let param = details.parameters[name] else { continue } + let paramName = swiftizeParam(name) + let swiftType = getSwiftType(param.parameterType) + params.append("\(paramName): \(swiftType)? = nil") + } + + signature += params.joined(separator: ", ") + signature += ") throws -> Self {" + + result.append(" @inlinable") + result.append(signature) + + // Generate function body + let blobParamSwift = swiftizeParam(blobParamName) + result.append(" // the operation will retain the blob") + result.append(" try \(blobParamSwift).withVipsBlob { blob in") + result.append(" try Self { out in") + result.append(" var opt = VIPSOption()") + result.append("") + result.append(" opt.set(\"\(blobParamName)\", value: blob)") + + // Set other required parameters + for name in details.methodArgs { + if name == details.memberX || name == blobParamName { + continue + } + let paramName: String + if name == "right" { + paramName = "rhs" + } else if name == "in" { + paramName = "`in`" + } else { + paramName = swiftizeParam(name) + } + result.append(" opt.set(\"\(name)\", value: \(paramName))") + } + + // Set optional parameters + for name in optionalInput { + if name == blobParamName { + continue + } + let paramName = swiftizeParam(name) + result.append(" if let \(paramName) = \(paramName) {") + result.append(" opt.set(\"\(name)\", value: \(paramName))") + result.append(" }") + } + + result.append(" opt.set(\"out\", value: &out)") + result.append("") + result.append(" try Self.call(\"\(details.nickname)\", options: &opt)") + result.append(" }") + result.append(" }") + result.append(" }") + + return result.joined(separator: "\n") + } + + // MARK: - Collection Overload + + /// Generate Collection overload for buffer operations + /// + /// Creates an overload that accepts any Collection of UInt8 for buffer-based operations. + /// + /// - Parameter details: Operation details + /// - Returns: Swift method string, or nil if not applicable + func generateCollectionOverload(for details: VIPSOperationDetails) -> String? { + // Skip deprecated operations + if details.isDeprecated { + return nil + } + + // Find the blob parameter + guard let blobParamName = findBlobParameter(in: details) else { + return nil + } + + // Only generate for load operations that return images + guard details.nickname.contains("load") else { + return nil + } + + let requiredOutput = details.requiredOutput.filter { $0 != details.memberX } + guard let firstOutput = requiredOutput.first, + let outputParam = details.parameters[firstOutput], + outputParam.parameterType == vips_image_get_type() else { + return nil + } + + // Filter out deprecated and internal parameters + let optionalInput = details.optionalInput.filter { name in + guard let param = details.parameters[name] else { return false } + return !param.isDeprecated && name != "nickname" && name != "description" + } + + var result: [String] = [] + + // Generate documentation + result.append(" /// \(details.description.prefix(1).uppercased())\(details.description.dropFirst())") + result.append(" ///") + result.append(" /// - Parameters:") + result.append(" /// - \(swiftizeParam(blobParamName)): Buffer to load from") + + // Add other parameters documentation + for name in details.methodArgs + optionalInput { + if name == blobParamName || name == details.memberX { + continue + } + if let param = details.parameters[name] { + let paramName = swiftizeParam(name) + result.append(" /// - \(paramName): \(param.description)") + } + } + + // Build function signature + var funcName = snakeToCamel(details.nickname) + + // Remove common suffixes for overloaded methods + let overloadSuffixes = ["Buffer", "Source", "Target", "Mime"] + for suffix in overloadSuffixes { + if funcName.hasSuffix(suffix) { + funcName = String(funcName.dropLast(suffix.count)) + break + } + } + + if swiftKeywords.contains(funcName) { + funcName = "`\(funcName)`" + } + + var signature = " public static func \(funcName)(" + + // Add required parameters + var params = ["\(swiftizeParam(blobParamName)): some Collection"] + + // Add other required parameters + for name in details.methodArgs { + if name == details.memberX || name == blobParamName { + continue + } + guard let param = details.parameters[name] else { continue } + let paramName = swiftizeParam(name) + let swiftType = getSwiftType(param.parameterType) + params.append("\(paramName): \(swiftType)") + } + + // Add optional parameters + for name in optionalInput { + guard let param = details.parameters[name] else { continue } + let paramName = swiftizeParam(name) + let swiftType = getSwiftType(param.parameterType) + params.append("\(paramName): \(swiftType)? = nil") + } + + signature += params.joined(separator: ", ") + signature += ") throws -> Self {" + + result.append(" @inlinable") + result.append(signature) + + // Generate function body - create VIPSBlob and call the VIPSBlob version + let blobParamSwift = swiftizeParam(blobParamName) + result.append(" let blob = VIPSBlob(\(blobParamSwift))") + result.append(" return try \(funcName)(") + result.append(" \(blobParamSwift): blob,") + + // Add other required parameters + for name in details.methodArgs { + if name == details.memberX || name == blobParamName { + continue + } + let paramName = swiftizeParam(name) + result.append(" \(paramName): \(paramName),") + } + + // Add optional parameters + for name in optionalInput { + let paramName = swiftizeParam(name) + result.append(" \(paramName): \(paramName),") + } + + // Remove trailing comma from last parameter + if let lastLine = result.last, lastLine.hasSuffix(",") { + result[result.count - 1] = String(lastLine.dropLast()) + } + + result.append(" )") + result.append(" }") + + return result.joined(separator: "\n") + } + + // MARK: - UnsafeRawBufferPointer Overload + + /// Generate UnsafeRawBufferPointer overload for buffer operations + /// + /// Creates a zero-copy overload that accepts UnsafeRawBufferPointer. + /// The caller must ensure the buffer remains valid for the lifetime of the image. + /// + /// - Parameter details: Operation details + /// - Returns: Swift method string, or nil if not applicable + func generateUnsafeBufferOverload(for details: VIPSOperationDetails) -> String? { + // Skip deprecated operations + if details.isDeprecated { + return nil + } + + // Find the blob parameter + guard let blobParamName = findBlobParameter(in: details) else { + return nil + } + + // Only generate for load operations that return images + guard details.nickname.contains("load") else { + return nil + } + + let requiredOutput = details.requiredOutput.filter { $0 != details.memberX } + guard let firstOutput = requiredOutput.first, + let outputParam = details.parameters[firstOutput], + outputParam.parameterType == vips_image_get_type() else { + return nil + } + + // Filter out deprecated and internal parameters + let optionalInput = details.optionalInput.filter { name in + guard let param = details.parameters[name] else { return false } + return !param.isDeprecated && name != "nickname" && name != "description" + } + + var result: [String] = [] + + // Generate documentation + result.append(" /// \(details.description.prefix(1).uppercased())\(details.description.dropFirst()) without copying the data. The caller must ensure the buffer remains valid for") + result.append(" /// the lifetime of the returned image and all its descendants.") + result.append(" ///") + result.append(" /// - Parameters:") + result.append(" /// - \(swiftizeParam(blobParamName)): Buffer to load from") + + // Add other parameters documentation + for name in details.methodArgs + optionalInput { + if name == blobParamName || name == details.memberX { + continue + } + if let param = details.parameters[name] { + let paramName = swiftizeParam(name) + result.append(" /// - \(paramName): \(param.description)") + } + } + + // Build function signature + var funcName = snakeToCamel(details.nickname) + + // Remove common suffixes for overloaded methods + let overloadSuffixes = ["Buffer", "Source", "Target", "Mime"] + for suffix in overloadSuffixes { + if funcName.hasSuffix(suffix) { + funcName = String(funcName.dropLast(suffix.count)) + break + } + } + + if swiftKeywords.contains(funcName) { + funcName = "`\(funcName)`" + } + + var signature = " public static func \(funcName)(" + + // Add required parameters + var params = ["unsafeBuffer \(swiftizeParam(blobParamName)): UnsafeRawBufferPointer"] + + // Add other required parameters + for name in details.methodArgs { + if name == details.memberX || name == blobParamName { + continue + } + guard let param = details.parameters[name] else { continue } + let paramName = swiftizeParam(name) + let swiftType = getSwiftType(param.parameterType) + params.append("\(paramName): \(swiftType)") + } + + // Add optional parameters + for name in optionalInput { + guard let param = details.parameters[name] else { continue } + let paramName = swiftizeParam(name) + let swiftType = getSwiftType(param.parameterType) + params.append("\(paramName): \(swiftType)? = nil") + } + + signature += params.joined(separator: ", ") + signature += ") throws -> Self {" + + result.append(" @inlinable") + result.append(signature) + + // Generate function body - create VIPSBlob with noCopy and call the VIPSBlob version + let blobParamSwift = swiftizeParam(blobParamName) + result.append(" let blob = VIPSBlob(noCopy: \(blobParamSwift))") + result.append(" return try \(funcName)(") + result.append(" \(blobParamSwift): blob,") + + // Add other required parameters + for name in details.methodArgs { + if name == details.memberX || name == blobParamName { + continue + } + let paramName = swiftizeParam(name) + result.append(" \(paramName): \(paramName),") + } + + // Add optional parameters + for name in optionalInput { + let paramName = swiftizeParam(name) + result.append(" \(paramName): \(paramName),") + } + + // Remove trailing comma from last parameter + if let lastLine = result.last, lastLine.hasSuffix(",") { + result[result.count - 1] = String(lastLine.dropLast()) + } + + result.append(" )") + result.append(" }") + + return result.joined(separator: "\n") + } + + // MARK: - Relational Convenience Methods + + /// Generate relational convenience methods (equal, notequal, less, etc.) + /// + /// Creates convenience methods for relational and boolean operations. + /// + /// - Returns: Swift code string with all relational convenience methods + func generateRelationalConvenienceMethods() -> String { + var methods: [String] = [] + + // Define relational operations and their corresponding enum values + let relationalOps: [(String, String, String)] = [ + ("equal", "equal", "Test for equality"), + ("notequal", "noteq", "Test for inequality"), + ("less", "less", "Test for less than"), + ("lesseq", "lesseq", "Test for less than or equal"), + ("more", "more", "Test for greater than"), + ("moreeq", "moreeq", "Test for greater than or equal") + ] + + for (methodName, enumValue, description) in relationalOps { + // Method with VIPSImage parameter - make first param unnamed for operator compatibility + methods.append(" /// \(description)") + methods.append(" ///") + methods.append(" /// - Parameters:") + methods.append(" /// - rhs: Right-hand input image") + methods.append(" public func \(methodName)(_ rhs: some VIPSImageProtocol) throws -> Self {") + methods.append(" return try relational(rhs, relational: .\(enumValue))") + methods.append(" }") + methods.append("") + + // Method with Double parameter + methods.append(" /// \(description)") + methods.append(" ///") + methods.append(" /// - Parameters:") + methods.append(" /// - value: Constant value") + methods.append(" public func \(methodName)(_ value: Double) throws -> Self {") + methods.append(" return try relationalConst(relational: .\(enumValue), c: [value])") + methods.append(" }") + methods.append("") + } + + // Add boolean operations for bitwise operators + let booleanOps: [(String, String, String)] = [ + ("andimage", "and", "Bitwise AND of two images"), + ("orimage", "or", "Bitwise OR of two images"), + ("eorimage", "eor", "Bitwise XOR of two images") + ] + + for (methodName, enumValue, description) in booleanOps { + methods.append(" /// \(description)") + methods.append(" ///") + methods.append(" /// - Parameters:") + methods.append(" /// - rhs: Right-hand input image") + methods.append(" public func \(methodName)(_ rhs: some VIPSImageProtocol) throws -> Self {") + methods.append(" return try boolean(rhs, boolean: .\(enumValue))") + methods.append(" }") + methods.append("") + } + + // Add shift operations (these use boolean operations) + let shiftOps: [(String, String, String)] = [ + ("lshift", "lshift", "Left shift"), + ("rshift", "rshift", "Right shift") + ] + + for (methodName, enumValue, description) in shiftOps { + methods.append(" /// \(description)") + methods.append(" ///") + methods.append(" /// - Parameters:") + methods.append(" /// - amount: Number of bits to shift") + methods.append(" public func \(methodName)(_ amount: Int) throws -> Self {") + methods.append(" return try booleanConst(boolean: .\(enumValue), c: [Double(amount)])") + methods.append(" }") + methods.append("") + } + + return methods.joined(separator: "\n") + } + + // MARK: - Helper Methods + + /// Find the blob parameter in operation details + private func findBlobParameter(in details: VIPSOperationDetails) -> String? { + let allInputParams = details.methodArgs + details.optionalInput + for name in allInputParams { + if let param = details.parameters[name], + param.parameterType == shim_VIPS_TYPE_BLOB() { + return name + } + } + return nil + } +} diff --git a/Sources/VIPSGenerator/StringUtils.swift b/Sources/VIPSGenerator/StringUtils.swift new file mode 100644 index 0000000..7fb2224 --- /dev/null +++ b/Sources/VIPSGenerator/StringUtils.swift @@ -0,0 +1,52 @@ +// +// StringUtils.swift +// VIPSGenerator +// +// String utility functions for code generation +// + +/// Convert snake_case to camelCase +/// - Parameter name: The snake_case string to convert +/// - Returns: camelCase version of the string +/// +/// The first component stays lowercase, subsequent components are capitalized. +/// Example: `extract_area` → `extractArea` +func snakeToCamel(_ name: String) -> String { + let components = name.split(separator: "_") + + if components.isEmpty { + return name + } + + // First component preserves its case, rest are capitalized + return String(components[0]) + components[1...].map { $0.capitalized }.joined() +} + +/// Convert parameter name to Swift-safe version +/// - Parameter name: The parameter name to convert +/// - Returns: Swift-safe parameter name +/// +/// Handles special mappings, replaces hyphens with underscores, +/// converts to camelCase, and escapes Swift keywords with backticks. +/// Example: `in` → `` `in` `` +func swiftizeParam(_ name: String) -> String { + var result = name + + // Handle special parameter name mappings + if result == "Q" { + return "quality" + } + + // Replace hyphens with underscores + result = result.replacingOccurrences(of: "-", with: "_") + + // Convert to camelCase + result = snakeToCamel(result) + + // Escape if it's a keyword + if swiftKeywords.contains(result) { + return "`\(result)`" + } + + return result +} diff --git a/Sources/VIPSGenerator/SwiftKeywords.swift b/Sources/VIPSGenerator/SwiftKeywords.swift new file mode 100644 index 0000000..6659dad --- /dev/null +++ b/Sources/VIPSGenerator/SwiftKeywords.swift @@ -0,0 +1,19 @@ +// +// SwiftKeywords.swift +// VIPSGenerator +// +// Swift reserved keywords that need backtick escaping +// + +/// Set of Swift reserved keywords that need backtick escaping when used as identifiers +let swiftKeywords: Set = [ + "in", "out", "var", "let", "func", "class", "struct", "enum", "protocol", + "extension", "import", "typealias", "operator", "return", "if", "else", + "for", "while", "do", "switch", "case", "default", "break", "continue", + "fallthrough", "where", "guard", "defer", "repeat", "try", "catch", "throw", + "throws", "rethrows", "as", "is", "nil", "true", "false", "self", "super", + "init", "deinit", "get", "set", "willSet", "didSet", "static", "public", + "private", "internal", "fileprivate", "open", "final", "lazy", "weak", + "unowned", "inout", "associatedtype", "indirect", "prefix", "postfix", + "infix", "left", "right", "none", "precedence", "Type" +] diff --git a/Sources/VIPSGenerator/TypeMapping.swift b/Sources/VIPSGenerator/TypeMapping.swift new file mode 100644 index 0000000..e0b63b7 --- /dev/null +++ b/Sources/VIPSGenerator/TypeMapping.swift @@ -0,0 +1,62 @@ +// +// TypeMapping.swift +// VIPSGenerator +// +// GType to Swift type mapping for code generation +// + +import Cvips +import CvipsShim + +/// Maps a GType to its corresponding Swift type name +/// - Parameter gtype: The GType value to map +/// - Returns: Swift type name as a string +func getSwiftType(_ gtype: UInt) -> String { + // Direct type mappings + if gtype == shim_g_type_boolean() { + return "Bool" + } else if gtype == shim_G_TYPE_INT() { + return "Int" + } else if gtype == shim_G_TYPE_DOUBLE() { + return "Double" + } else if gtype == shim_G_TYPE_STRING() { + return "String" + } else if gtype == vips_ref_string_get_type() { + return "String" + } else if gtype == vips_image_get_type() { + return "some VIPSImageProtocol" + } else if gtype == vips_source_get_type() { + return "VIPSSource" + } else if gtype == vips_target_get_type() { + return "VIPSTarget" + } else if gtype == g_type_from_name("guint64") { + return "UInt64" + } else if gtype == vips_interpolate_get_type() { + return "VIPSInterpolate" + } else if gtype == shim_VIPS_TYPE_ARRAY_INT() { + return "[Int]" + } else if gtype == shim_VIPS_TYPE_ARRAY_DOUBLE() { + return "[Double]" + } else if gtype == vips_array_image_get_type() { + return "[VIPSImage]" + } else if gtype == shim_VIPS_TYPE_BLOB() { + return "VIPSBlob" + } + + // Check for enum types + if shim_gtype_is_enum(gtype) != 0 { + if let typeName = shim_gtype_name(gtype) { + return String(cString: typeName) + } + } + + // Check for flags types + if shim_gtype_is_flags(gtype) != 0 { + if let typeName = shim_gtype_name(gtype) { + return String(cString: typeName) + } + } + + // Unknown type + return "Any" +} diff --git a/Sources/VIPSGenerator/VersionRequirements.swift b/Sources/VIPSGenerator/VersionRequirements.swift new file mode 100644 index 0000000..98647b3 --- /dev/null +++ b/Sources/VIPSGenerator/VersionRequirements.swift @@ -0,0 +1,25 @@ +// +// VersionRequirements.swift +// VIPSGenerator +// +// Operations that require specific libvips versions +// + +/// Maps version strings to operations that require that version +let versionRequirements: [String: [String]] = [ + "8.13": ["premultiply", "unpremultiply"], + "8.16": ["addalpha"], + "8.17": ["sdf_shape", "sdf"] +] + +/// Get the version guard for an operation if it requires a specific version +/// - Parameter nickname: The operation nickname +/// - Returns: The preprocessor guard string (e.g., "#if SHIM_VIPS_VERSION_8_16") or nil +func getOperationVersionGuard(_ nickname: String) -> String? { + for (version, operations) in versionRequirements { + if operations.contains(nickname) { + return "#if SHIM_VIPS_VERSION_\(version.replacingOccurrences(of: ".", with: "_"))" + } + } + return nil +} diff --git a/Sources/VIPSGenerator/main.swift b/Sources/VIPSGenerator/main.swift new file mode 100644 index 0000000..2c263f2 --- /dev/null +++ b/Sources/VIPSGenerator/main.swift @@ -0,0 +1,307 @@ +// +// main.swift +// VIPSGenerator +// +// Swift-based VIPS operation wrapper generator +// + +import VIPSIntrospection +import Foundation +import Subprocess + +// MARK: - Command Line Arguments + +struct Arguments { + var outputDir: String = "Sources/VIPS/Generated" + var dryRun: Bool = false + var verbose: Bool = false + var operation: String? = nil + var listOutputs: Bool = false +} + +func parseArguments() -> Arguments { + var args = Arguments() + let commandLineArgs = CommandLine.arguments + var i = 1 + + while i < commandLineArgs.count { + let arg = commandLineArgs[i] + + switch arg { + case "--output-dir", "-o": + i += 1 + if i < commandLineArgs.count { + args.outputDir = commandLineArgs[i] + } + case "--dry-run": + args.dryRun = true + case "--verbose": + args.verbose = true + case "--operation": + i += 1 + if i < commandLineArgs.count { + args.operation = commandLineArgs[i] + } + case "--list-outputs": + args.listOutputs = true + case "--help", "-h": + printHelp() + exit(0) + default: + if arg.hasPrefix("-") { + print("Unknown option: \(arg)") + printHelp() + exit(1) + } + } + + i += 1 + } + + return args +} + +func printHelp() { + print(""" + VIPS Swift Code Generator + + Usage: vips-generator [options] + + Options: + --output-dir, -o Output directory (default: Sources/VIPS/Generated) + --dry-run Print what would be generated without writing + --verbose Print progress information + --operation Generate single operation (for testing) + --list-outputs List output file paths (one per line) and exit + --help, -h Show this help message + """) +} + +// MARK: - Formatting + +/// Format generated Swift files using swift format +func formatGeneratedFiles(outputDirectory: String, verbose: Bool) async { + do { + // Run swift format on all files in the output directory + // Collect stderr in case of errors + let result = try await run( + .name("swift"), + arguments: [ + "format", + "--in-place", + "--recursive", + "--parallel", + outputDirectory + ], + output: .discarded, + error: .string(limit: 16384) + ) + + if result.terminationStatus.isSuccess { + if verbose { + print(" āœ… Formatted all generated files") + } + } else { + print(" āš ļø swift format exited with status \(result.terminationStatus)") + if let stderr = result.standardError, !stderr.isEmpty { + print(" Error output:") + for line in stderr.split(separator: "\n") { + print(" \(line)") + } + } + } + } catch { + // swift format might not be available in older toolchains + if verbose { + print(" āš ļø Failed to run swift format: \(error)") + print(" ā„¹ļø Formatting requires Swift 6.0 or later") + } + } +} + +// MARK: - Main Function + +func main() async { + let args = parseArguments() + + do { + if args.verbose { + print("Initializing VIPS library...") + } + try VIPSIntrospection.initialize() + defer { VIPSIntrospection.shutdown() } + + if args.verbose { + print("Discovering VIPS operations...") + } + var operations = try VIPSIntrospection.getAllOperations() + + // Note: Don't add "crop" as synonym - it would duplicate "extract_area" + // The Python generator adds it but handles deduplication differently + + if !args.listOutputs { + print("Found \(operations.count) operations") + } + + // Filter to single operation if requested + if let singleOp = args.operation { + operations = operations.filter { $0 == singleOp } + if operations.isEmpty { + print("Error: Operation '\(singleOp)' not found") + exit(1) + } + print("Generating single operation: \(singleOp)") + } + + let generator = CodeGenerator() + let overloads = OverloadGenerators() + var categorizedMethods: [String: [(nickname: String, code: String)]] = [:] + + // Operations to exclude (matching Python generator) + let excludedOperations = Set([ + "avifsave_target", + "magicksave_bmp", + "magicksave_bmp_buffer", + "pbmsave_target", + "pfmsave_target", + "pgmsave_target", + "pnmsave_target", + "linear", // Has manual implementation with multiple overloads + "project", // Has manual implementation with tuple return type + "profile" // Has manual implementation with tuple return type + ]) + + // Const variant mapping + let constVariants = ["remainder": "remainder_const"] + + if args.verbose && !args.listOutputs { + print("Generating wrappers...") + } + + for nickname in operations { + // Skip excluded operations + if excludedOperations.contains(nickname) { + continue + } + + // Get operation details - skip abstract types that fail introspection + let details: VIPSOperationDetails + do { + details = try VIPSIntrospection.getOperationDetails(nickname) + } catch { + // Can fail for abstract types, skip them + if args.verbose && !args.listOutputs { + print(" Skipping \(nickname) (abstract type)") + } + continue + } + + // Generate main wrapper + if let wrapper = generator.generateWrapper(for: details) { + let category = getOperationCategory(nickname) + + // Apply version guards if needed + var code = wrapper + if let versionGuard = getOperationVersionGuard(nickname) { + code = "\(versionGuard)\n\(code)\n#endif" + } + + categorizedMethods[category, default: []].append((nickname, code)) + + if args.verbose && !args.listOutputs { + print(" Generated \(nickname) -> \(category)") + } + } + + // Generate UnsafeRawBufferPointer overload if this operation has blob parameters + if let unsafeBufferOverload = overloads.generateUnsafeBufferOverload(for: details) { + let category = getOperationCategory(nickname) + var code = unsafeBufferOverload + if let versionGuard = getOperationVersionGuard(nickname) { + code = "\(versionGuard)\n\(code)\n#endif" + } + categorizedMethods[category, default: []].append(( + nickname: "\(nickname)_unsafe_buffer_overload", + code: code + )) + } + + // Generate const overloads if this operation has them + if let constOpName = constVariants[nickname] { + let constDetails = try VIPSIntrospection.getOperationDetails(constOpName) + let constOverloads = overloads.generateSimpleConstOverloads( + baseOp: nickname, + constOp: constDetails + ) + + let category = getOperationCategory(nickname) + for (i, overloadCode) in constOverloads.enumerated() { + var code = overloadCode + if let versionGuard = getOperationVersionGuard(nickname) { + code = "\(versionGuard)\n\(code)\n#endif" + } + categorizedMethods[category, default: []].append(( + nickname: "\(nickname)_overload_\(i)", + code: code + )) + } + } + } + + if args.dryRun { + print("\nOperations by category:") + for category in categorizedMethods.keys.sorted() { + let methods = categorizedMethods[category]! + print(" \(category): \(methods.count) operations") + for (nickname, _) in methods.prefix(3) { + print(" - \(nickname)") + } + if methods.count > 3 { + print(" ... and \(methods.count - 3) more") + } + } + return + } + + // If --list-outputs, just print the file paths and exit + if args.listOutputs { + let writer = FileWriter(outputDirectory: args.outputDir) + for category in categorizedMethods.keys.sorted() { + let (filepath, _) = writer.getFilePath(for: category) + print(filepath.path()) + } + return + } + + // Write files + if args.verbose { + print("\nWriting files to \(args.outputDir)...") + } + + let writer = FileWriter(outputDirectory: args.outputDir) + for category in categorizedMethods.keys.sorted() { + let methods = categorizedMethods[category]! + try writer.writeCategory(category, methods: methods) + print(" āœ… Generated \(category.lowercased().replacingOccurrences(of: "/", with: "_")).generated.swift (\(methods.count) operations)") + } + + print("\nGeneration complete!") + + // Format generated files with swift format + if args.verbose { + print("\nFormatting generated files...") + } + await formatGeneratedFiles(outputDirectory: args.outputDir, verbose: args.verbose) + + print("\nSummary:") + let totalOperations = categorizedMethods.values.reduce(0) { $0 + $1.count } + print(" Total operations: \(totalOperations)") + print(" Total categories: \(categorizedMethods.count)") + + } catch { + print("Error: \(error)") + exit(1) + } +} + +await main() diff --git a/Sources/VIPSIntrospection/VIPSIntrospection.swift b/Sources/VIPSIntrospection/VIPSIntrospection.swift new file mode 100644 index 0000000..3ffabaa --- /dev/null +++ b/Sources/VIPSIntrospection/VIPSIntrospection.swift @@ -0,0 +1,271 @@ +// +// VIPSIntrospection.swift +// VIPSIntrospection +// +// Swift API for libvips GObject introspection +// + +#if canImport(Darwin) +import Darwin +#elseif canImport(Glibc) +import Glibc +#endif +import Cvips +import CvipsShim +import Foundation + +/// Information about a VIPS operation +public struct VIPSOperationInfo { + public let nickname: String + public let description: String + public let operationType: UInt // GType as UInt + public let flags: Int32 + public let parameters: [VIPSParameterInfo] + + /// Check if the operation is deprecated + public var isDeprecated: Bool { + return (UInt32(flags) & VIPS_OPERATION_DEPRECATED.rawValue) != 0 + } +} + +/// Information about a VIPS operation parameter +public struct VIPSParameterInfo { + public let name: String + public let description: String + public let parameterType: UInt // GType as UInt + public let flags: Int32 + public let priority: Int32 + + /// Check if this parameter is required + public var isRequired: Bool { + return (UInt32(flags) & VIPS_ARGUMENT_REQUIRED.rawValue) != 0 + } + + /// Check if this parameter is input + public var isInput: Bool { + return (UInt32(flags) & VIPS_ARGUMENT_INPUT.rawValue) != 0 + } + + /// Check if this parameter is output + public var isOutput: Bool { + return (UInt32(flags) & VIPS_ARGUMENT_OUTPUT.rawValue) != 0 + } + + /// Check if this parameter is deprecated + public var isDeprecated: Bool { + return (UInt32(flags) & VIPS_ARGUMENT_DEPRECATED.rawValue) != 0 + } +} + +/// Extended operation details with classified parameters +public struct VIPSOperationDetails { + public let nickname: String + public let description: String + public let flags: Int32 + public let memberX: String? // The "self" parameter (first required input image) + public let methodArgs: [String] // Required inputs (excluding memberX) + public let optionalInput: [String] // Optional input parameters + public let requiredOutput: [String] // Required output parameters + public let optionalOutput: [String] // Optional output parameters + public let parameters: [String: VIPSParameterInfo] // All parameters by name + + public var isDeprecated: Bool { + return (UInt32(flags) & VIPS_OPERATION_DEPRECATED.rawValue) != 0 + } +} + +/// Swift wrapper for GType information +public struct VIPSGType { + public let gtype: UInt + + public init(_ gtype: UInt) { + self.gtype = gtype + } + + /// Get the type name + public var name: String { + guard let cString = shim_gtype_name(gtype) else { return "" } + return String(cString: cString) + } + + /// Get the fundamental type + public var fundamental: VIPSGType { + return VIPSGType(shim_gtype_fundamental(gtype)) + } + + /// Check if this is an enum type + public var isEnum: Bool { + return shim_gtype_is_enum(gtype) != 0 + } + + /// Check if this is a flags type + public var isFlags: Bool { + return shim_gtype_is_flags(gtype) != 0 + } +} + +/// Main introspection interface +public class VIPSIntrospection { + + /// Initialize VIPS library for introspection + public static func initialize() throws { + // Force English locale for consistent code generation + setenv("LANG", "C", 1) + setenv("LC_ALL", "C", 1) + + if vips_init("swift-vips-introspection") != 0 { + throw VIPSIntrospectionError.initializationFailed + } + } + + /// Shutdown VIPS library + public static func shutdown() { + vips_shutdown() + } + + /// Get all available VIPS operations + public static func getAllOperations() throws -> [String] { + var count: Int32 = 0 + guard let types = shim_get_all_operation_types(&count) else { + throw VIPSIntrospectionError.failedToGetOperations + } + defer { shim_free_operation_types(types) } + + var nicknames = Set() + for i in 0.. VIPSOperationInfo { + guard let info = shim_get_operation_info(nickname) else { + throw VIPSIntrospectionError.operationNotFound(nickname) + } + defer { shim_free_operation_info(info) } + + // Get parameters + var paramCount: Int32 = 0 + guard let params = shim_get_operation_parameters(nickname, ¶mCount) else { + throw VIPSIntrospectionError.failedToGetParameters(nickname) + } + defer { shim_free_parameter_info(params) } + + var parameters: [VIPSParameterInfo] = [] + for i in 0.. VIPSOperationDetails { + // Get basic operation info and parameters + let info = try getOperationInfo(nickname) + + // Get the VipsImage GType for comparison + let imageType = vips_image_get_type() + + // Sort parameters by priority (lower priority first) + let sortedParams = info.parameters.sorted { $0.priority < $1.priority } + + // Create parameter dictionary for quick lookup + var paramDict: [String: VIPSParameterInfo] = [:] + for param in info.parameters { + paramDict[param.name] = param + } + + // Classify parameters + var memberX: String? = nil + var methodArgs: [String] = [] + var optionalInput: [String] = [] + var requiredOutput: [String] = [] + var optionalOutput: [String] = [] + + for param in sortedParams { + // Skip deprecated parameters + if param.isDeprecated { + continue + } + + // Skip internal parameters + if param.name == "nickname" || param.name == "description" { + continue + } + + // Classify based on flags + // IMPORTANT: Check for outputs FIRST, because "out" parameter has both INPUT and OUTPUT flags + if param.isOutput && param.isRequired { + requiredOutput.append(param.name) + } else if param.isOutput && !param.isRequired { + optionalOutput.append(param.name) + } else if param.isRequired && param.isInput { + // If memberX is nil AND parameter type is VipsImage, this is memberX + if memberX == nil && param.parameterType == imageType { + memberX = param.name + } else { + methodArgs.append(param.name) + } + } else if !param.isRequired && param.isInput { + optionalInput.append(param.name) + } + } + + return VIPSOperationDetails( + nickname: info.nickname, + description: info.description, + flags: info.flags, + memberX: memberX, + methodArgs: methodArgs, + optionalInput: optionalInput, + requiredOutput: requiredOutput, + optionalOutput: optionalOutput, + parameters: paramDict + ) + } + + /// Get type information for a GType + public static func getTypeInfo(_ gtype: UInt) -> VIPSGType { + return VIPSGType(gtype) + } +} + +/// Errors that can occur during introspection +public enum VIPSIntrospectionError: Error, CustomStringConvertible { + case initializationFailed + case failedToGetOperations + case operationNotFound(String) + case failedToGetParameters(String) + + public var description: String { + switch self { + case .initializationFailed: + return "Failed to initialize VIPS library" + case .failedToGetOperations: + return "Failed to get operation list" + case .operationNotFound(let nickname): + return "Operation '\(nickname)' not found" + case .failedToGetParameters(let nickname): + return "Failed to get parameters for operation '\(nickname)'" + } + } +} diff --git a/docs/VIPS.md b/docs/VIPS.md index 39cd332..13d62ff 100644 --- a/docs/VIPS.md +++ b/docs/VIPS.md @@ -25,8 +25,24 @@ | func | `vipsFindLoader(path:)` | | typealias | `VIPSProgress` | | typealias | `VipsAccess` | +| typealias | `VipsAlign` | +| typealias | `VipsAngle` | +| typealias | `VipsAngle45` | +| typealias | `VipsArgumentFlags` | | typealias | `VipsBandFormat` | +| typealias | `VipsBlendMode` | +| typealias | `VipsCoding` | +| typealias | `VipsCombine` | +| typealias | `VipsCombineMode` | +| typealias | `VipsCompassDirection` | +| typealias | `VipsDemandStyle` | +| typealias | `VipsDirection` | +| typealias | `VipsExtend` | +| typealias | `VipsFailOn` | +| typealias | `VipsForeignFlags` | | typealias | `VipsForeignKeep` | +| typealias | `VipsForeignSubsample` | +| typealias | `VipsImageType` | | typealias | `VipsIntent` | | typealias | `VipsInteresting` | | typealias | `VipsInterpretation` | @@ -35,13 +51,17 @@ | typealias | `VipsOperationComplex` | | typealias | `VipsOperationComplex2` | | typealias | `VipsOperationComplexget` | +| typealias | `VipsOperationFlags` | | typealias | `VipsOperationMath` | | typealias | `VipsOperationMath2` | +| typealias | `VipsOperationMorphology` | | typealias | `VipsOperationRelational` | | typealias | `VipsOperationRound` | | typealias | `VipsPCS` | | typealias | `VipsPrecision` | +| typealias | `VipsRegionShrink` | | typealias | `VipsSize` | +| typealias | `VipsTextWrap` | | Array extension | `Array` | | Collection extension | `Collection` | @@ -415,6 +435,9 @@ public final class VIPSImage: PointerWrapper, VIPSImageProtocol, VIPSObjectProto /// Calculate hyperbolic cosine of image values public func cosh() throws -> VIPSImage + /// Alias for extractArea - crop an image + public func crop(left: Int, top: Int, width: Int, height: Int) throws -> VIPSImage + /// Bitwise XOR of image with a constant (integer overload) public func eorimage(_ value: Int) throws -> VIPSImage @@ -1105,7 +1128,7 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public static func grey(width: Int, height: Int, uchar: Bool? = nil) throws -> Self - /// Make a 1d image where pixel values are indexes + /// Make a 1D image where pixel values are indexes /// public static func identity(bands: Int? = nil, ushort: Bool? = nil, size: Int? = nil) throws -> Self @@ -1159,11 +1182,11 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public static func perlin(width: Int, height: Int, cellSize: Int? = nil, uchar: Bool? = nil, seed: Int? = nil) throws -> Self - /// Load named icc profile + /// Load named ICC profile /// public static func profileLoad(name: String) throws -> VIPSBlob - /// Make a 2d sine wave + /// Make a 2D sine wave /// public static func sines(width: Int, height: Int, uchar: Bool? = nil, hfreq: Double? = nil, vfreq: Double? = nil) throws -> Self @@ -1191,63 +1214,63 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public static func zone(width: Int, height: Int, uchar: Bool? = nil) throws -> Self - /// Transform lch to cmc + /// Transform LCh to CMC public func CMC2LCh() throws -> Self - /// Transform cmyk to xyz + /// Transform CMYK to XYZ public func CMYK2XYZ() throws -> Self - /// Transform hsv to srgb + /// Transform HSV to sRGB public func HSV2sRGB() throws -> Self - /// Transform lch to cmc + /// Transform LCh to CMC public func LCh2CMC() throws -> Self - /// Transform lch to lab + /// Transform LCh to Lab public func LCh2Lab() throws -> Self - /// Transform lab to lch + /// Transform Lab to LCh public func Lab2LCh() throws -> Self - /// Transform float lab to labq coding + /// Transform float Lab to LabQ coding public func Lab2LabQ() throws -> Self - /// Transform float lab to signed short + /// Transform float Lab to signed short public func Lab2LabS() throws -> Self - /// Transform cielab to xyz + /// Transform CIELAB to XYZ /// public func Lab2XYZ(temp: [Double]? = nil) throws -> Self - /// Unpack a labq image to float lab + /// Unpack a LabQ image to float Lab public func LabQ2Lab() throws -> Self - /// Unpack a labq image to short lab + /// Unpack a LabQ image to short Lab public func LabQ2LabS() throws -> Self - /// Convert a labq image to srgb + /// Convert a LabQ image to sRGB public func LabQ2sRGB() throws -> Self - /// Transform signed short lab to float + /// Transform signed short Lab to float public func LabS2Lab() throws -> Self - /// Transform short lab to labq coding + /// Transform short Lab to LabQ coding public func LabS2LabQ() throws -> Self - /// Transform xyz to cmyk + /// Transform XYZ to CMYK public func XYZ2CMYK() throws -> Self - /// Transform xyz to lab + /// Transform XYZ to Lab /// public func XYZ2Lab(temp: [Double]? = nil) throws -> Self - /// Transform xyz to yxy + /// Transform XYZ to Yxy public func XYZ2Yxy() throws -> Self - /// Transform xyz to scrgb + /// Transform XYZ to scRGB public func XYZ2scRGB() throws -> Self - /// Transform yxy to xyz + /// Transform Yxy to XYZ public func Yxy2XYZ() throws -> Self /// Absolute value of an image @@ -1323,19 +1346,15 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// returns it. public func copyMemory() throws -> Self - /// Extract an area from an image - /// - public func crop(left: Int, top: Int, width: Int, height: Int) throws -> Self - - /// Calculate de00 + /// Calculate dE00 /// public func dE00(_ rhs: some VIPSImageProtocol) throws -> Self - /// Calculate de76 + /// Calculate dE76 /// public func dE76(_ rhs: some VIPSImageProtocol) throws -> Self - /// Calculate decmc + /// Calculate dECMC /// public func dECMC(_ rhs: some VIPSImageProtocol) throws -> Self @@ -1380,14 +1399,14 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public func flatten(background: [Double]? = nil, maxAlpha: Double? = nil) throws -> Self - /// Transform float rgb to radiance coding + /// Transform float RGB to Radiance coding public func float2rad() throws -> Self /// Frequency-domain filtering /// public func freqmult(mask: some VIPSImageProtocol) throws -> Self - /// Forward fft + /// Forward FFT public func fwfft() throws -> Self /// Gamma an image @@ -1464,7 +1483,7 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public func invertlut(size: Int? = nil) throws -> Self - /// Inverse fft + /// Inverse FFT /// public func invfft(real: Bool? = nil) throws -> Self @@ -1559,7 +1578,7 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public func quadratic(coeff: some VIPSImageProtocol, interpolate: VIPSInterpolate? = nil) throws -> Self - /// Unpack radiance coding to float rgb + /// Unpack Radiance coding to float RGB public func rad2float() throws -> Self /// Rank filter @@ -1594,20 +1613,20 @@ public protocol VIPSImageProtocol : VIPSObjectProtocol, ~Copyable, ~Escapable { /// public func rshift(_ amount: Int) throws -> Self - /// Transform srgb to hsv + /// Transform sRGB to HSV public func sRGB2HSV() throws -> Self - /// Convert an srgb image to scrgb + /// Convert an sRGB image to scRGB public func sRGB2scRGB() throws -> Self - /// Convert scrgb to bw + /// Convert scRGB to BW /// public func scRGB2BW(depth: Int? = nil) throws -> Self - /// Transform scrgb to xyz + /// Transform scRGB to XYZ public func scRGB2XYZ() throws -> Self - /// Convert scrgb to srgb + /// Convert scRGB to sRGB /// public func scRGB2sRGB(depth: Int? = nil) throws -> Self @@ -1745,10 +1764,42 @@ public typealias VIPSProgress = Cvips.VipsProgress public typealias VipsAccess = Cvips.VipsAccess +public typealias VipsAlign = Cvips.VipsAlign + +public typealias VipsAngle = Cvips.VipsAngle + +public typealias VipsAngle45 = Cvips.VipsAngle45 + +public typealias VipsArgumentFlags = Cvips.VipsArgumentFlags + public typealias VipsBandFormat = Cvips.VipsBandFormat +public typealias VipsBlendMode = Cvips.VipsBlendMode + +public typealias VipsCoding = Cvips.VipsCoding + +public typealias VipsCombine = Cvips.VipsCombine + +public typealias VipsCombineMode = Cvips.VipsCombineMode + +public typealias VipsCompassDirection = Cvips.VipsCompassDirection + +public typealias VipsDemandStyle = Cvips.VipsDemandStyle + +public typealias VipsDirection = Cvips.VipsDirection + +public typealias VipsExtend = Cvips.VipsExtend + +public typealias VipsFailOn = Cvips.VipsFailOn + +public typealias VipsForeignFlags = Cvips.VipsForeignFlags + public typealias VipsForeignKeep = Cvips.VipsForeignKeep +public typealias VipsForeignSubsample = Cvips.VipsForeignSubsample + +public typealias VipsImageType = Cvips.VipsImageType + public typealias VipsIntent = Cvips.VipsIntent public typealias VipsInteresting = Cvips.VipsInteresting @@ -1765,10 +1816,14 @@ public typealias VipsOperationComplex2 = Cvips.VipsOperationComplex2 public typealias VipsOperationComplexget = Cvips.VipsOperationComplexget +public typealias VipsOperationFlags = Cvips.VipsOperationFlags + public typealias VipsOperationMath = Cvips.VipsOperationMath public typealias VipsOperationMath2 = Cvips.VipsOperationMath2 +public typealias VipsOperationMorphology = Cvips.VipsOperationMorphology + public typealias VipsOperationRelational = Cvips.VipsOperationRelational public typealias VipsOperationRound = Cvips.VipsOperationRound @@ -1777,7 +1832,11 @@ public typealias VipsPCS = Cvips.VipsPCS public typealias VipsPrecision = Cvips.VipsPrecision +public typealias VipsRegionShrink = Cvips.VipsRegionShrink + public typealias VipsSize = Cvips.VipsSize + +public typealias VipsTextWrap = Cvips.VipsTextWrap ``` - + diff --git a/docs/VIPSIntrospection.md b/docs/VIPSIntrospection.md new file mode 100644 index 0000000..d85cb35 --- /dev/null +++ b/docs/VIPSIntrospection.md @@ -0,0 +1,180 @@ +## Module `VIPSIntrospection` + +### Table of Contents + +| Type | Name | +| --- | --- | +| class | `VIPSIntrospection` | +| struct | `VIPSGType` | +| struct | `VIPSOperationDetails` | +| struct | `VIPSOperationInfo` | +| struct | `VIPSParameterInfo` | +| enum | `VIPSIntrospectionError` | + +### Public interface + +#### class VIPSIntrospection + +```swift +/// Main introspection interface +public class VIPSIntrospection { + /// Get all available VIPS operations + public static func getAllOperations() throws -> [String] + + /// Get detailed operation information with classified parameters + public static func getOperationDetails(_ nickname: String) throws -> VIPSOperationDetails + + /// Get detailed information about a specific operation + public static func getOperationInfo(_ nickname: String) throws -> VIPSOperationInfo + + /// Get type information for a GType + public static func getTypeInfo(_ gtype: UInt) -> VIPSGType + + /// Initialize VIPS library for introspection + public static func initialize() throws + + /// Shutdown VIPS library + public static func shutdown() +} +``` + +#### struct VIPSGType + +```swift +/// Swift wrapper for GType information +public struct VIPSGType { + /// Get the fundamental type + public var fundamental: VIPSGType { get } + + public let gtype: UInt + + /// Check if this is an enum type + public var isEnum: Bool { get } + + /// Check if this is a flags type + public var isFlags: Bool { get } + + /// Get the type name + public var name: String { get } + + public init(_ gtype: UInt) +} +``` + +#### struct VIPSOperationDetails + +```swift +/// Extended operation details with classified parameters +public struct VIPSOperationDetails { + public let description: String + + public let flags: Int32 + + public var isDeprecated: Bool { get } + + public let memberX: String? + + public let methodArgs: [String] + + public let nickname: String + + public let optionalInput: [String] + + public let optionalOutput: [String] + + public let parameters: [String : VIPSParameterInfo] + + public let requiredOutput: [String] +} +``` + +#### struct VIPSOperationInfo + +```swift +/// Information about a VIPS operation +public struct VIPSOperationInfo { + public let description: String + + public let flags: Int32 + + /// Check if the operation is deprecated + public var isDeprecated: Bool { get } + + public let nickname: String + + public let operationType: UInt + + public let parameters: [VIPSParameterInfo] +} +``` + +#### struct VIPSParameterInfo + +```swift +/// Information about a VIPS operation parameter +public struct VIPSParameterInfo { + public let description: String + + public let flags: Int32 + + /// Check if this parameter is deprecated + public var isDeprecated: Bool { get } + + /// Check if this parameter is input + public var isInput: Bool { get } + + /// Check if this parameter is output + public var isOutput: Bool { get } + + /// Check if this parameter is required + public var isRequired: Bool { get } + + public let name: String + + public let parameterType: UInt + + public let priority: Int32 +} +``` + +#### enum VIPSIntrospectionError + +```swift +/// Errors that can occur during introspection +public enum VIPSIntrospectionError: Error, Sendable, SendableMetatype { + /// A textual representation of this instance. + /// + /// Calling this property directly is discouraged. Instead, convert an + /// instance of any type to a string by using the `String(describing:)` + /// initializer. This initializer works with any type, and uses the custom + /// `description` property for types that conform to + /// `CustomStringConvertible`: + /// + /// struct Point: CustomStringConvertible { + /// let x: Int, y: Int + /// + /// var description: String { + /// return "(\(x), \(y))" + /// } + /// } + /// + /// let p = Point(x: 21, y: 30) + /// let s = String(describing: p) + /// print(s) + /// // Prints "(21, 30)" + /// + /// The conversion of `p` to a string in the assignment to `s` uses the + /// `Point` type's `description` property. + public var description: String { get } + + public case failedToGetOperations + + public case failedToGetParameters(String) + + public case initializationFailed + + public case operationNotFound(String) +} +``` + + diff --git a/tools/generate-swift-wrappers.py b/tools/generate-swift-wrappers.py deleted file mode 100644 index 39da304..0000000 --- a/tools/generate-swift-wrappers.py +++ /dev/null @@ -1,1489 +0,0 @@ -#!/usr/bin/env python3 - -""" -Swift wrapper generator for libvips using GObject introspection. - -This script uses PyVIPS to introspect libvips operations and generate -Swift wrapper code following the conventions of the swift-vips project. - -Requirements: - pip install pyvips - -Usage: - python3 tools/generate-swift-wrappers.py -""" - -import os -import sys -import argparse -import locale -import re -import glob -import subprocess -from collections import defaultdict -from pathlib import Path - -# Force English locale for consistent code generation -# This ensures all libvips descriptions and documentation are in English -locale.setlocale(locale.LC_ALL, 'C') -os.environ['LANG'] = 'C' -os.environ['LC_ALL'] = 'C' - -try: - from pyvips import Introspect, Operation, GValue, Error, \ - ffi, gobject_lib, type_map, type_from_name, nickname_find, type_name -except ImportError: - print("Error: pyvips not found. Please install it with: pip install pyvips") - sys.exit(1) - -# Map GType to Swift types -gtype_to_swift = { - GValue.gbool_type: 'Bool', - GValue.gint_type: 'Int', - GValue.gdouble_type: 'Double', - GValue.gstr_type: 'String', - GValue.refstr_type: 'String', - GValue.image_type: 'some VIPSImageProtocol', - GValue.source_type: 'VIPSSource', - GValue.target_type: 'VIPSTarget', - GValue.guint64_type: 'UInt64', - type_from_name('VipsInterpolate'): 'VIPSInterpolate', - GValue.array_int_type: '[Int]', - GValue.array_double_type: '[Double]', - GValue.array_image_type: '[VIPSImage]', - GValue.blob_type: 'VIPSBlob' -} - -# Swift reserved keywords that need escaping -swift_keywords = { - 'in', 'out', 'var', 'let', 'func', 'class', 'struct', 'enum', 'protocol', - 'extension', 'import', 'typealias', 'operator', 'return', 'if', 'else', - 'for', 'while', 'do', 'switch', 'case', 'default', 'break', 'continue', - 'fallthrough', 'where', 'guard', 'defer', 'repeat', 'try', 'catch', 'throw', - 'throws', 'rethrows', 'as', 'is', 'nil', 'true', 'false', 'self', 'super', - 'init', 'deinit', 'get', 'set', 'willSet', 'didSet', 'static', 'public', - 'private', 'internal', 'fileprivate', 'open', 'final', 'lazy', 'weak', - 'unowned', 'inout', 'associatedtype', 'indirect', 'prefix', 'postfix', - 'infix', 'left', 'right', 'none', 'precedence', 'Type' -} - -# VipsArgumentFlags values -_REQUIRED = 1 -_INPUT = 16 -_OUTPUT = 32 -_DEPRECATED = 64 -_MODIFY = 128 - -# VipsOperationFlags -_OPERATION_DEPRECATED = 8 - -# Version requirements for operations (version string -> list of operations) -VERSION_REQUIREMENTS = { - '8.13': ['premultiply', 'unpremultiply'], - '8.16': ['addalpha'], - '8.17': ['sdf_shape', 'sdf'] -} - -def get_swift_type(gtype): - """Map a GType to Swift type name.""" - if gtype in gtype_to_swift: - return gtype_to_swift[gtype] - - fundamental = gobject_lib.g_type_fundamental(gtype) - - # Enum/flag types - if fundamental == GValue.genum_type or fundamental == GValue.gflags_type: - # Convert C enum name to Swift style - name = type_name(gtype) - if name: - # VipsIntent -> VipsIntent, VipsBandFormat -> VipsBandFormat - return name - - if fundamental in gtype_to_swift: - return gtype_to_swift[fundamental] - - return 'Any' - -def snake_to_camel(name): - """Convert snake_case to camelCase.""" - components = name.split('_') - if len(components) == 0: - return name - # First component stays lowercase, rest are capitalized - return components[0] + ''.join(x.capitalize() for x in components[1:]) - -def swiftize_param(name): - """Convert parameter name to Swift-safe version.""" - # Handle special parameter name mappings - if name == 'Q': - return 'quality' - - # Replace hyphens with underscores - name = name.replace('-', '_') - # Convert to camelCase - name = snake_to_camel(name) - # Escape if it's a keyword - if name in swift_keywords: - return f"`{name}`" - return name - -def get_operation_category(nickname): - """Categorize operation based on its name.""" - name = nickname.lower() - - # Foreign operations (file I/O) - if 'load' in name or 'save' in name: - if 'jpeg' in name or 'jpg' in name: - return 'Foreign/JPEG' - elif 'png' in name: - return 'Foreign/PNG' - elif 'webp' in name: - return 'Foreign/WebP' - elif 'tiff' in name or 'tif' in name: - return 'Foreign/TIFF' - elif 'pdf' in name: - return 'Foreign/PDF' - elif 'svg' in name: - return 'Foreign/SVG' - elif 'heif' in name or 'heic' in name: - return 'Foreign/HEIF' - elif 'gif' in name: - return 'Foreign/GIF' - else: - return 'Foreign/Other' - - # Arithmetic operations - arithmetic_ops = ['add', 'subtract', 'multiply', 'divide', 'abs', 'linear', - 'math', 'complex', 'remainder', 'boolean', 'relational', - 'round', 'sign', 'avg', 'min', 'max', 'deviate', 'sum', - 'invert', 'stats'] - if any(op in name for op in arithmetic_ops): - return 'Arithmetic' - - # Convolution operations - conv_ops = ['conv', 'sharpen', 'blur', 'sobel', 'canny', 'gaussblur'] - if any(op in name for op in conv_ops): - return 'Convolution' - - # Colour operations - colour_ops = ['colour', 'color', 'lab', 'xyz', 'srgb', 'rgb', 'cmyk', - 'hsv', 'lch', 'yxy', 'scrgb', 'icc'] - if any(op in name for op in colour_ops): - return 'Colour' - - # Conversion operations - conversion_ops = ['resize', 'rotate', 'flip', 'crop', 'embed', 'extract', - 'shrink', 'reduce', 'zoom', 'affine', 'similarity', 'scale', - 'autorot', 'rot', 'recomb', 'bandjoin', 'bandrank', - 'bandsplit', 'cast', 'copy', 'tilecache', 'arrayjoin', - 'grid', 'transpose', 'wrap', 'unpremultiply', 'premultiply', - 'composite', 'join', 'insert'] - if any(op in name for op in conversion_ops): - return 'Conversion' - - # Create operations - create_ops = ['black', 'xyz', 'grey', 'mask', 'gaussmat', 'logmat', 'text', - 'gaussnoise', 'eye', 'zone', 'sines', 'buildlut', 'identity', - 'fractsurf', 'radload', 'tonelut', 'worley', 'perlin'] - if any(op in name for op in create_ops): - return 'Create' - - # Draw operations - if 'draw' in name: - return 'Draw' - - # Histogram operations - hist_ops = ['hist', 'heq', 'hough', 'profile', 'project', 'spectrum', 'phasecor'] - if any(op in name for op in hist_ops): - return 'Histogram' - - # Morphology operations - morph_ops = ['morph', 'erode', 'dilate', 'median', 'rank', 'countlines', 'labelregions'] - if any(op in name for op in morph_ops): - return 'Morphology' - - # Frequency domain operations - freq_ops = ['fft', 'invfft', 'freqmult', 'spectrum', 'phasecor'] - if any(op in name for op in freq_ops): - return 'Freqfilt' - - # Resample operations - resample_ops = ['shrink', 'reduce', 'resize', 'thumbnail', 'mapim', 'quadratic'] - if any(op in name for op in resample_ops): - return 'Resample' - - return 'Misc' - -def has_buffer_parameter(intro): - """Check if operation has any blob input parameters.""" - all_input_params = intro.method_args + intro.optional_input - for name in all_input_params: - if name in intro.details: - param_type = intro.details[name]['type'] - if param_type == GValue.blob_type: - return True - return False - - - -def generate_simple_const_overloads(base_operation_name, const_operation_name): - """Generate simple const overloads for common operations.""" - try: - const_intro = Introspect.get(const_operation_name) - base_intro = Introspect.get(base_operation_name) - except Error: - return [] - - # Skip if either operation is deprecated - if const_intro.flags & _OPERATION_DEPRECATED or base_intro.flags & _OPERATION_DEPRECATED: - return [] - - # Only generate for image output operations - required_output = [name for name in const_intro.required_output if name != const_intro.member_x] - if not required_output or const_intro.details[required_output[0]]['type'] != GValue.image_type: - return [] - - func_name = snake_to_camel(base_operation_name) - if func_name in swift_keywords: - func_name = f"`{func_name}`" - - overloads = [] - - # For operations like remainder_const that take a 'c' parameter - if 'c' in const_intro.method_args: - # Generate Double overload - result = [] - result.append(f" /// {const_intro.description.capitalize()}") - result.append(" ///") - result.append(" /// - Parameters:") - result.append(" /// - value: Constant value") - result.append(f" public func {func_name}(_ value: Double) throws -> Self {{") - result.append(f" return try {snake_to_camel(const_operation_name)}(c: [value])") - result.append(" }") - overloads.append("\n".join(result)) - - # Generate Int overload - result = [] - result.append(f" /// {const_intro.description.capitalize()}") - result.append(" ///") - result.append(" /// - Parameters:") - result.append(" /// - value: Constant value") - result.append(f" public func {func_name}(_ value: Int) throws -> Self {{") - result.append(f" return try {snake_to_camel(const_operation_name)}(c: [Double(value)])") - result.append(" }") - overloads.append("\n".join(result)) - - return overloads - -def generate_const_overload(base_operation_name, const_operation_name): - """Generate a const variant overload for an operation.""" - try: - const_intro = Introspect.get(const_operation_name) - base_intro = Introspect.get(base_operation_name) - except Error: - return None - - # Skip if either operation is deprecated - if const_intro.flags & _OPERATION_DEPRECATED or base_intro.flags & _OPERATION_DEPRECATED: - return None - - # Only generate for image output operations - required_output = [name for name in const_intro.required_output if name != const_intro.member_x] - if not required_output or const_intro.details[required_output[0]]['type'] != GValue.image_type: - return None - - # Find the constant parameter (usually 'c' for array of doubles or a single value parameter) - const_param = None - const_param_type = None - - for name in const_intro.optional_input: - if name == 'c': # Most common constant parameter name - const_param = name - const_param_type = const_intro.details[name]['type'] - break - - # Handle special cases where the constant parameter has a different name - if not const_param: - # Look for other likely constant parameter names - for name in const_intro.optional_input: - param_type = const_intro.details[name]['type'] - if param_type in [GValue.gdouble_type, GValue.gint_type, GValue.array_double_type, GValue.array_int_type]: - # Skip if this parameter also exists in the base operation (it's not the "const" replacement) - if name not in base_intro.optional_input and name not in base_intro.method_args: - const_param = name - const_param_type = param_type - break - - if not const_param: - return None # Couldn't find the constant parameter - - # Generate the overloaded method - result = [] - - func_name = snake_to_camel(base_operation_name) - if func_name in swift_keywords: - func_name = f"`{func_name}`" - - # Determine the Swift type for the constant parameter - if const_param_type == GValue.array_double_type: - swift_const_type = "[Double]" - default_value = "[]" - elif const_param_type == GValue.array_int_type: - swift_const_type = "[Int]" - default_value = "[]" - elif const_param_type == GValue.gdouble_type: - swift_const_type = "Double" - default_value = "0.0" - elif const_param_type == GValue.gint_type: - swift_const_type = "Int" - default_value = "0" - else: - return None # Unsupported constant type - - # Generate documentation - result.append(f" /// {const_intro.description.capitalize()}") - result.append(" ///") - result.append(" /// - Parameters:") - if const_param_type in [GValue.array_double_type, GValue.array_int_type]: - result.append(f" /// - value: Array of constant values") - else: - result.append(f" /// - value: Constant value") - - # Add other optional parameters documentation - for name in const_intro.optional_input: - if name != const_param and name in const_intro.details: - details = const_intro.details[name] - param_name = swiftize_param(name) - result.append(f" /// - {param_name}: {details['blurb']}") - - # Build method signature - signature = f" public func {func_name}(_ value: {swift_const_type}" - - # Add other optional parameters - params = [] - for name in const_intro.optional_input: - if name == const_param: - continue - details = const_intro.details[name] - param_name = swiftize_param(name) - swift_type = get_swift_type(details['type']) - params.append(f"{param_name}: {swift_type}? = nil") - - if params: - signature += f", {', '.join(params)}" - - signature += ") throws -> Self {" - result.append(signature) - - # Generate method body - call the const operation directly - result.append(" return try Self { out in") - result.append(" var opt = VIPSOption()") - result.append("") - result.append(f' opt.set("{const_intro.member_x}", value: self)') - result.append(f' opt.set("{const_param}", value: value)') - - # Set other optional parameters - for name in const_intro.optional_input: - if name == const_param: - continue - param_name = swiftize_param(name) - result.append(f" if let {param_name} = {param_name} {{") - result.append(f' opt.set("{name}", value: {param_name})') - result.append(" }") - - result.append(' opt.set("out", value: &out)') - result.append("") - result.append(f' try Self.call("{const_operation_name}", options: &opt)') - result.append(" }") - result.append(" }") - - return "\n".join(result) - -def generate_unsafe_buffer_overload(operation_name): - """Generate an UnsafeRawBufferPointer overload for operations that have blob parameters.""" - try: - intro = Introspect.get(operation_name) - except Error: - return None - - # Skip deprecated operations - if intro.flags & _OPERATION_DEPRECATED: - return None - - # Check if this operation has blob parameters - if not has_buffer_parameter(intro): - return None - - # Only generate for load operations that return images - if 'load' not in operation_name: - return None - - required_output = [name for name in intro.required_output if name != intro.member_x] - if not required_output or intro.details[required_output[0]]['type'] != GValue.image_type: - return None - - # Find the first blob parameter - blob_param_name = None - all_input_params = intro.method_args + intro.optional_input - for name in all_input_params: - if name in intro.details and intro.details[name]['type'] == GValue.blob_type: - blob_param_name = name - break - - if not blob_param_name: - return None - - # Filter out deprecated and internal parameters for optional inputs - optional_input = [] - for name in intro.optional_input: - if intro.details[name]['flags'] & _DEPRECATED == 0: - if name not in ['nickname', 'description']: - optional_input.append(name) - - result = [] - - # Generate documentation - result.append(f" /// {intro.description.capitalize()} without copying the data. The caller must ensure the buffer remains valid for") - result.append(" /// the lifetime of the returned image and all its descendants.") - result.append(" ///") - result.append(" /// - Parameters:") - result.append(f" /// - {swiftize_param(blob_param_name)}: Buffer to load from") - - # Add other parameters documentation - for name in intro.method_args + optional_input: - if name == blob_param_name or name == intro.member_x: - continue - if name in intro.details: - details = intro.details[name] - param_name = swiftize_param(name) - result.append(f" /// - {param_name}: {details['blurb']}") - - # Build function signature - func_name = snake_to_camel(operation_name) - - # Remove common suffixes for overloaded methods - overload_suffixes = ['Buffer', 'Source', 'Target', 'Mime'] - for suffix in overload_suffixes: - if func_name.endswith(suffix): - func_name = func_name[:-len(suffix)] - break - - # Escape function name if it's a Swift keyword - if func_name in swift_keywords: - func_name = f"`{func_name}`" - - signature = f" public static func {func_name}(" - - # Add required parameters - params = [f"unsafeBuffer {swiftize_param(blob_param_name)}: UnsafeRawBufferPointer"] - - # Add other required parameters (excluding member_x and blob param) - for name in intro.method_args: - if name == intro.member_x or name == blob_param_name: - continue - details = intro.details[name] - param_name = swiftize_param(name) - swift_type = get_swift_type(details['type']) - params.append(f"{param_name}: {swift_type}") - - # Add optional parameters - for name in optional_input: - details = intro.details[name] - param_name = swiftize_param(name) - swift_type = get_swift_type(details['type']) - params.append(f"{param_name}: {swift_type}? = nil") - - signature += f"{', '.join(params)}) throws -> Self {{" - - # Add @inlinable decorator - result.append(" @inlinable") - result.append(signature) - - # Generate function body - create VIPSBlob with noCopy and call the VIPSBlob version - blob_param_swift = swiftize_param(blob_param_name) - result.append(f" let blob = VIPSBlob(noCopy: {blob_param_swift})") - result.append(f" return try {func_name}(") - - # Add blob parameter - result.append(f" {blob_param_swift}: blob,") - - # Add other required parameters - for name in intro.method_args: - if name == intro.member_x or name == blob_param_name: - continue - param_name = swiftize_param(name) - result.append(f" {param_name}: {param_name},") - - # Add optional parameters - for name in optional_input: - param_name = swiftize_param(name) - result.append(f" {param_name}: {param_name},") - - # Remove trailing comma from last parameter - if result[-1].endswith(","): - result[-1] = result[-1][:-1] - - result.append(" )") - result.append(" }") - - return "\n".join(result) - - -def generate_collection_uint8_overload(operation_name): - """Generate a Collection overload for operations that have blob parameters.""" - try: - intro = Introspect.get(operation_name) - except Error: - return None - - # Skip deprecated operations - if intro.flags & _OPERATION_DEPRECATED: - return None - - # Check if this operation has blob parameters - if not has_buffer_parameter(intro): - return None - - # Only generate for load operations that return images - if 'load' not in operation_name: - return None - - required_output = [name for name in intro.required_output if name != intro.member_x] - if not required_output or intro.details[required_output[0]]['type'] != GValue.image_type: - return None - - # Find the first blob parameter - blob_param_name = None - all_input_params = intro.method_args + intro.optional_input - for name in all_input_params: - if name in intro.details and intro.details[name]['type'] == GValue.blob_type: - blob_param_name = name - break - - if not blob_param_name: - return None - - # Filter out deprecated and internal parameters for optional inputs - optional_input = [] - for name in intro.optional_input: - if intro.details[name]['flags'] & _DEPRECATED == 0: - if name not in ['nickname', 'description']: - optional_input.append(name) - - result = [] - - # Generate documentation - result.append(f" /// {intro.description.capitalize()}") - result.append(" ///") - result.append(" /// - Parameters:") - result.append(f" /// - {swiftize_param(blob_param_name)}: Buffer to load from") - - # Add other parameters documentation - for name in intro.method_args + optional_input: - if name == blob_param_name or name == intro.member_x: - continue - if name in intro.details: - details = intro.details[name] - param_name = swiftize_param(name) - result.append(f" /// - {param_name}: {details['blurb']}") - - # Build function signature - func_name = snake_to_camel(operation_name) - - # Remove common suffixes for overloaded methods - overload_suffixes = ['Buffer', 'Source', 'Target', 'Mime'] - for suffix in overload_suffixes: - if func_name.endswith(suffix): - func_name = func_name[:-len(suffix)] - break - - # Escape function name if it's a Swift keyword - if func_name in swift_keywords: - func_name = f"`{func_name}`" - - signature = f" public static func {func_name}(" - - # Add required parameters - params = [f"{swiftize_param(blob_param_name)}: some Collection"] - - # Add other required parameters (excluding member_x and blob param) - for name in intro.method_args: - if name == intro.member_x or name == blob_param_name: - continue - details = intro.details[name] - param_name = swiftize_param(name) - swift_type = get_swift_type(details['type']) - params.append(f"{param_name}: {swift_type}") - - # Add optional parameters - for name in optional_input: - details = intro.details[name] - param_name = swiftize_param(name) - swift_type = get_swift_type(details['type']) - params.append(f"{param_name}: {swift_type}? = nil") - - signature += f"{', '.join(params)}) throws -> Self {{" - - # Add @inlinable decorator - result.append(" @inlinable") - result.append(signature) - - # Generate function body - create VIPSBlob and call the VIPSBlob version - blob_param_swift = swiftize_param(blob_param_name) - result.append(f" let blob = VIPSBlob({blob_param_swift})") - result.append(f" return try {func_name}(") - - # Add blob parameter - result.append(f" {blob_param_swift}: blob,") - - # Add other required parameters - for name in intro.method_args: - if name == intro.member_x or name == blob_param_name: - continue - param_name = swiftize_param(name) - result.append(f" {param_name}: {param_name},") - - # Add optional parameters - for name in optional_input: - param_name = swiftize_param(name) - result.append(f" {param_name}: {param_name},") - - # Remove trailing comma from last parameter - if result[-1].endswith(","): - result[-1] = result[-1][:-1] - - result.append(" )") - result.append(" }") - - return "\n".join(result) - - -def generate_vipsblob_overload(operation_name): - """Generate a VIPSBlob overload for operations that have blob parameters.""" - try: - intro = Introspect.get(operation_name) - except Error: - return None - - # Skip deprecated operations - if intro.flags & _OPERATION_DEPRECATED: - return None - - # Check if this operation has blob parameters - if not has_buffer_parameter(intro): - return None - - # Get required and optional parameters - required_output = [name for name in intro.required_output if name != intro.member_x] - - # Filter out deprecated and internal parameters - optional_input = [] - for name in intro.optional_input: - if intro.details[name]['flags'] & _DEPRECATED == 0: - if name not in ['nickname', 'description']: - optional_input.append(name) - - has_output = len(required_output) >= 1 - has_image_output = has_output and intro.details[required_output[0]]['type'] == GValue.image_type - - # Only generate for image output operations - if not has_image_output: - return None - - # Find the first blob parameter - blob_param_name = None - all_input_params = intro.method_args + optional_input - for name in all_input_params: - if name in intro.details and intro.details[name]['type'] == GValue.blob_type: - blob_param_name = name - break - - if not blob_param_name: - return None - - result = [] - - # Generate documentation - result.append(f" /// {intro.description.capitalize()}") - - # Add parameter documentation - all_params = intro.method_args + optional_input - if all_params: - result.append(" ///") - result.append(" /// - Parameters:") - for name in all_params: - if name in intro.details: - details = intro.details[name] - param_name = swiftize_param(name) - # Special documentation for the blob parameter - if name == blob_param_name: - result.append(f" /// - {param_name}: Buffer to load from") - else: - result.append(f" /// - {param_name}: {details['blurb']}") - - # Build function signature - func_name = snake_to_camel(operation_name) - - # Remove common suffixes for overloaded methods - overload_suffixes = ['Buffer', 'Source', 'Target', 'Mime'] - for suffix in overload_suffixes: - if func_name.endswith(suffix): - func_name = func_name[:-len(suffix)] - break - - # Escape function name if it's a Swift keyword - if func_name in swift_keywords: - func_name = f"`{func_name}`" - - if 'load' in operation_name: - signature = f" public static func {func_name}(" - else: - signature = f" public func {func_name}(" - - # Add required parameters - params = [] - is_first_param = True - for name in intro.method_args: - if name == intro.member_x: - continue - details = intro.details[name] - param_name = swiftize_param(name) - - # Use VIPSBlob for the blob parameter - if name == blob_param_name: - swift_type = "VIPSBlob" - else: - swift_type = get_swift_type(details['type']) - - # Special handling for "right" parameter - rename to "rhs" and hide label - if name == "right": - params.append(f"_ rhs: {swift_type}") - # Special handling for "in" parameter when it's the first parameter - hide label - elif name == "in" and is_first_param: - params.append(f"_ `in`: {swift_type}") - else: - # Check if first parameter name matches function name (omit label if so) - clean_func_name = func_name.strip('`') - if is_first_param and (param_name == clean_func_name or clean_func_name.endswith(param_name.capitalize())): - params.append(f"_ {param_name}: {swift_type}") - else: - params.append(f"{param_name}: {swift_type}") - - is_first_param = False - - # Add optional parameters - for name in optional_input: - if name == blob_param_name: - continue # Skip blob parameter as it's already in required params - details = intro.details[name] - param_name = swiftize_param(name) - swift_type = get_swift_type(details['type']) - swift_type = f"{swift_type}?" - params.append(f"{param_name}: {swift_type} = nil") - - signature += ", ".join(params) - signature += ") throws -> Self {" - - # Add @inlinable decorator - result.append(" @inlinable") - result.append(signature) - - # Generate function body - blob_param_swift = swiftize_param(blob_param_name) - - result.append(" // the operation will retain the blob") - result.append(f" try {blob_param_swift}.withVipsBlob {{ blob in") - result.append(" try Self { out in") - result.append(" var opt = VIPSOption()") - result.append("") - result.append(f' opt.set("{blob_param_name}", value: blob)') - - # Set other required parameters - for name in intro.method_args: - if name == intro.member_x or name == blob_param_name: - continue - if name == "right": - param_name = "rhs" - elif name == "in": - param_name = "`in`" - else: - param_name = swiftize_param(name) - result.append(f' opt.set("{name}", value: {param_name})') - - # Set optional parameters - for name in optional_input: - if name == blob_param_name: - continue - param_name = swiftize_param(name) - result.append(f" if let {param_name} = {param_name} {{") - result.append(f' opt.set("{name}", value: {param_name})') - result.append(" }") - - result.append(' opt.set("out", value: &out)') - result.append("") - result.append(f' try Self.call("{operation_name}", options: &opt)') - result.append(" }") - result.append(" }") - result.append(" }") - - return "\n".join(result) - -def generate_swift_operation(operation_name): - """Generate Swift code for a single operation.""" - try: - intro = Introspect.get(operation_name) - except Error: - return None - - # Skip deprecated operations - if intro.flags & _OPERATION_DEPRECATED: - return None - - # Get required and optional parameters - required_output = [name for name in intro.required_output if name != intro.member_x] - - # Filter out deprecated and internal parameters - optional_input = [] - for name in intro.optional_input: - if intro.details[name]['flags'] & _DEPRECATED == 0: - # Skip internal parameters like 'nickname' and 'description' - if name not in ['nickname', 'description']: - optional_input.append(name) - - has_output = len(required_output) >= 1 - has_image_output = has_output and intro.details[required_output[0]]['type'] == GValue.image_type - - # Skip operations without proper outputs (unless it's a save operation) - if not has_output and 'save' not in operation_name: - return None - - - # Collect all Swift object parameters that need to be kept alive - swift_object_params = [] - all_input_params = intro.method_args + optional_input - for name in all_input_params: - if name != intro.member_x and name in intro.details: - param_type = intro.details[name]['type'] - if param_type == GValue.image_type: - swift_object_params.append(name) - elif param_type == GValue.array_image_type: - # Array of images also needs to be handled - swift_object_params.append(name) - elif param_type == type_from_name('VipsInterpolate'): - # VIPSInterpolate also needs to be kept alive - swift_object_params.append(name) - elif param_type == GValue.source_type: - # VIPSSource also needs to be kept alive - swift_object_params.append(name) - elif param_type == GValue.target_type: - # VIPSTarget also needs to be kept alive - swift_object_params.append(name) - elif param_type == GValue.blob_type: - # VIPSBlob also needs to be kept alive - swift_object_params.append(name) - - result = [] - - # Generate documentation - result.append(f" /// {intro.description.capitalize()}") - - # Add parameter documentation if there are any - all_params = intro.method_args + optional_input - if all_params: - result.append(" ///") - result.append(" /// - Parameters:") - for name in all_params: - if name in intro.details: - details = intro.details[name] - param_name = swiftize_param(name) - result.append(f" /// - {param_name}: {details['blurb']}") - - # Determine if this is an instance method or static method - is_instance_method = intro.member_x is not None - - # Build function signature - func_name = snake_to_camel(operation_name) - - # Remove common suffixes for overloaded methods, but preserve 'Mime' for save operations - # that output to stdout to differentiate them from regular save operations - overload_suffixes = ['Buffer', 'Source', 'Target'] - if not (operation_name.endswith('_mime') and 'save' in operation_name): - overload_suffixes.append('Mime') - - for suffix in overload_suffixes: - if func_name.endswith(suffix): - func_name = func_name[:-len(suffix)] - break - - # Escape function name if it's a Swift keyword - if func_name in swift_keywords: - func_name = f"`{func_name}`" - - if 'load' in operation_name: - signature = f" public static func {func_name}(" - elif is_instance_method: - signature = f" public func {func_name}(" - else: - signature = f" public static func {func_name}(" - - # Check if this operation has buffer parameters - has_buffer_param = has_buffer_parameter(intro) - - # Add required parameters - params = [] - is_first_param = True - for name in intro.method_args: - if name == intro.member_x: - continue # Skip the input image parameter (it's self) - details = intro.details[name] - param_name = swiftize_param(name) - - swift_type = get_swift_type(details['type']) - - # Special handling for "right" parameter - rename to "rhs" and hide label - if name == "right": - params.append(f"_ rhs: {swift_type}") - # Special handling for "in" parameter when it's the first parameter - hide label - elif name == "in" and is_first_param: - params.append(f"_ `in`: {swift_type}") - else: - # Check if first parameter name matches function name (omit label if so) - # Strip backticks from function name for comparison - clean_func_name = func_name.strip('`') - if is_first_param and (param_name == clean_func_name or clean_func_name.endswith(param_name.capitalize())): - params.append(f"_ {param_name}: {swift_type}") - else: - params.append(f"{param_name}: {swift_type}") - - is_first_param = False - - # Add optional parameters - for name in optional_input: - details = intro.details[name] - param_name = swiftize_param(name) - - swift_type = get_swift_type(details['type']) - # All optional parameters should be Swift optionals with nil default - swift_type = f"{swift_type}?" - params.append(f"{param_name}: {swift_type} = nil") - - signature += ", ".join(params) - signature += ") throws" - - # Add return type - if has_image_output: - signature += " -> Self" - elif has_output: - # Handle other output types - output_type = get_swift_type(intro.details[required_output[0]]['type']) - # Special handling for blob outputs - they should return VIPSBlob - if intro.details[required_output[0]]['type'] == GValue.blob_type: - signature += " -> VIPSBlob" - else: - signature += f" -> {output_type}" - elif 'save' in operation_name: - # Save operations don't return anything - pass - else: - # Operations without outputs - pass - - signature += " {" - - # Add @inlinable decorator for buffer operations - if has_buffer_param: - result.append(" @inlinable") - - result.append(signature) - - # Generate function body - if has_image_output: - # Check if we have blob parameters that need special handling - has_blob_params = any(name in intro.details and intro.details[name]['type'] == GValue.blob_type - for name in intro.method_args + optional_input) - - if has_blob_params: - # Find the first blob parameter - blob_param_name = None - for name in intro.method_args + optional_input: - if name in intro.details and intro.details[name]['type'] == GValue.blob_type: - blob_param_name = name - break - - if blob_param_name: - blob_param_swift = swiftize_param(blob_param_name) - result.append(f" // the operation will retain the blob") - result.append(f" try {blob_param_swift}.withVipsBlob {{ blob in") - result.append(" try Self { out in") - result.append(" var opt = VIPSOption()") - result.append("") - else: - result.append(" return try Self { out in") - result.append(" var opt = VIPSOption()") - result.append("") - elif has_output and not has_image_output: - # Operations that return non-image outputs (like avg, min, max, save_buffer) - result.append(" var opt = VIPSOption()") - result.append("") - - # Initialize output variable - output_name = required_output[0] - output_type = get_swift_type(intro.details[output_name]['type']) - output_gtype = intro.details[output_name]['type'] - - if output_type == 'Double': - result.append(" var out: Double = 0.0") - elif output_type == 'Int': - result.append(" var out: Int = 0") - elif output_type == 'Bool': - result.append(" var out: Bool = false") - elif output_type == 'String': - result.append(' var out: String = ""') - elif output_type == '[Double]': - result.append(" var out: UnsafeMutablePointer! = .allocate(capacity: 1)") - elif output_type == '[Int]': - result.append(" var out: [Int] = []") - elif output_gtype == GValue.blob_type: - # Special handling for blob outputs - result.append(" let out: UnsafeMutablePointer?> = .allocate(capacity: 1)") - result.append(" out.initialize(to: nil)") - result.append(" defer {") - result.append(" out.deallocate()") - result.append(" }") - else: - # For other types, we'll need to handle them as needed - result.append(f" var out: {output_type} = /* TODO: initialize {output_type} */") - result.append("") - elif 'save' in operation_name and is_instance_method: - # Save operations that don't return anything - result.append(" var opt = VIPSOption()") - result.append("") - else: - # Other operations without outputs - result.append(" var opt = VIPSOption()") - result.append("") - - # Set the input image if this is an instance method - if is_instance_method and intro.member_x: - # For non-image outputs, we need to use self.image - if has_output and not has_image_output: - result.append(f' opt.set("{intro.member_x}", value: self.image)') - else: - result.append(f' opt.set("{intro.member_x}", value: self)') - - # Set required parameters - for name in intro.method_args: - if name == intro.member_x: - continue - if name == "right": - param_name = "rhs" - elif name == "in": - param_name = "`in`" - else: - param_name = swiftize_param(name) - - # Special handling for blob parameters - use the blob pointer from withVipsBlob - if name in intro.details and intro.details[name]['type'] == GValue.blob_type: - result.append(f' opt.set("{name}", value: blob)') - else: - # VIPSOption handles Swift wrapper objects directly, so we can pass them as-is - result.append(f' opt.set("{name}", value: {param_name})') - - # Set optional parameters - for name in optional_input: - param_name = swiftize_param(name) - details = intro.details[name] - swift_type = get_swift_type(details['type']) - - # Special handling for optional blob parameters - use the blob pointer from withVipsBlob - if details['type'] == GValue.blob_type: - result.append(f" if let {param_name} = {param_name} {{") - result.append(f' opt.set("{name}", value: blob)') - result.append(" }") - else: - # All optional parameters are now Swift optionals, so we use if-let - result.append(f" if let {param_name} = {param_name} {{") - result.append(f' opt.set("{name}", value: {param_name})') - result.append(" }") - - # Set output parameters - if has_output: - # Check if we have blob parameters for correct indentation - has_blob_params = any(name in intro.details and intro.details[name]['type'] == GValue.blob_type - for name in intro.method_args + optional_input) - indent = " " if has_blob_params else " " - - for i, name in enumerate(required_output): - if i == 0: - # For blob outputs, use "out" directly instead of "&out" - output_gtype = intro.details[name]['type'] - if output_gtype == GValue.blob_type: - result.append(f'{indent}opt.set("{name}", value: out)') - else: - result.append(f'{indent}opt.set("{name}", value: &out)') - else: - # Handle additional outputs if needed - pass - - result.append("") - result.append(f' try Self.call("{operation_name}", options: &opt)') - - if has_image_output: - # Check if we have blob parameters that need special closing - has_blob_params = any(name in intro.details and intro.details[name]['type'] == GValue.blob_type - for name in intro.method_args + optional_input) - - if has_blob_params: - result.append(" }") - result.append(" }") - else: - result.append(" }") - elif has_output and not has_image_output: - # For non-image outputs, we need to return the output value - result.append("") - # Check if this is a blob output or array output - output_name = required_output[0] - output_gtype = intro.details[output_name]['type'] - output_type = get_swift_type(output_gtype) - - if output_gtype == GValue.blob_type: - # For blob outputs, we need to wrap in VIPSBlob and handle the error case - result.append(" guard let vipsBlob = out.pointee else {") - result.append(f' throw VIPSError("Failed to get buffer from {operation_name}")') - result.append(" }") - result.append("") - result.append(" return VIPSBlob(vipsBlob)") - elif output_type == '[Double]': - # For double array outputs, we need to extract the array from VipsArrayDouble - result.append(" guard let out else {") - result.append(f' throw VIPSError("{operation_name}: no output")') - result.append(" }") - result.append("") - result.append(" defer {") - result.append(" vips_area_unref(shim_vips_area(out))") - result.append(" }") - result.append(" ") - result.append(" var length = Int32(0)") - result.append(" let doubles = vips_array_double_get(out, &length)") - result.append(" let buffer = UnsafeBufferPointer(start: doubles, count: Int(length))") - result.append(" return Array(buffer)") - else: - result.append(" return out") - - result.append(" }") - - return "\n".join(result) - -def get_default_check(swift_type): - """Get the default value check for a Swift type.""" - if swift_type == 'Bool': - return 'false' - elif swift_type == 'Int': - return '0' - elif swift_type == 'Double': - return '0.0' - elif swift_type == 'String': - return '""' - elif swift_type.startswith('['): - return '[]' - else: - return 'nil' - -def get_operation_version_guard(nickname): - """Get the version guard for an operation if it requires a specific version.""" - for version, operations in VERSION_REQUIREMENTS.items(): - if nickname in operations: - return f"#if SHIM_VIPS_VERSION_{version.replace('.', '_')}" - return None - -def generate_all_operations(): - """Discover and generate code for all operations.""" - all_nicknames = [] - - # Operations to exclude from the API - excluded_operations = [ - 'avifsave_target', - 'magicksave_bmp', - 'magicksave_bmp_buffer', - 'pbmsave_target', - 'pfmsave_target', - 'pgmsave_target', - 'pnmsave_target', - 'linear', # Has manual implementation with multiple overloads - 'project', # Has manual implementation with tuple return type - 'profile', # Has manual implementation with tuple return type - ] - - # Operations that should have their _const variants automatically generated as overloads - const_variant_operations = { - 'remainder': 'remainder_const', - } - - def add_nickname(gtype, a, b): - nickname = nickname_find(gtype) - try: - # Can fail for abstract types - _ = Introspect.get(nickname) - all_nicknames.append(nickname) - except Error: - pass - - type_map(gtype, add_nickname) - return ffi.NULL - - type_map(type_from_name('VipsOperation'), add_nickname) - - # Add missing synonyms - all_nicknames.append('crop') - - # Make list unique and sort - all_nicknames = list(set(all_nicknames) - set(excluded_operations)) - all_nicknames.sort() - - # Group operations by category - operations_by_category = defaultdict(list) - - for nickname in all_nicknames: - code = generate_swift_operation(nickname) - if code: - category = get_operation_category(nickname) - - # Check if this operation needs version guards - version_guard = get_operation_version_guard(nickname) - if version_guard: - code = f"{version_guard}\n{code}\n#endif" - - operations_by_category[category].append((nickname, code)) - - # VIPSBlob overload is no longer needed since the main method now uses VIPSBlob directly - - # Generate UnsafeRawBufferPointer overload if this operation has blob parameters - unsafe_buffer_overload = generate_unsafe_buffer_overload(nickname) - if unsafe_buffer_overload: - if version_guard: - unsafe_buffer_overload = f"{version_guard}\n{unsafe_buffer_overload}\n#endif" - operations_by_category[category].append((f"{nickname}_unsafe_buffer_overload", unsafe_buffer_overload)) - - - # Generate const overloads if this operation has them - if nickname in const_variant_operations: - const_op_name = const_variant_operations[nickname] - overloads = generate_simple_const_overloads(nickname, const_op_name) - for i, overload_code in enumerate(overloads): - # Apply version guards to overloads too if needed - version_guard = get_operation_version_guard(nickname) - if version_guard: - overload_code = f"{version_guard}\n{overload_code}\n#endif" - - # Add each overload right after the main operation - operations_by_category[category].append((f"{nickname}_overload_{i}", overload_code)) - - return operations_by_category - -def write_category_file(category, operations, output_dir): - """Write Swift code for a category to a file.""" - # Create output directory if needed - category_parts = category.split('/') - if len(category_parts) > 1: - sub_dir = output_dir / category_parts[0] - sub_dir.mkdir(parents=True, exist_ok=True) - filename = f"{category.replace('/', '_').lower()}.generated.swift" - filepath = sub_dir / filename - else: - filename = f"{category.lower()}.generated.swift" - filepath = output_dir / filename - - # Check if any operations use buffer parameters or double array outputs - has_buffer_operations = False - for nickname, code in operations: - if ('vips_blob_copy' in code or 'vips_blob_new' in code or - 'vips_array_double_get' in code or - 'withVipsBlob' in code or 'shim_vips_area' in code): - has_buffer_operations = True - break - - # Separate operations into static and instance methods - static_operations = [] - instance_operations = [] - for nickname, code in operations: - if 'public static func' in code: - static_operations.append((nickname, code)) - else: - instance_operations.append((nickname, code)) - - with open(filepath, 'w') as f: - f.write("//\n") - f.write(f"// {filename}\n") - f.write("//\n") - f.write("// Generated by VIPS Swift Code Generator\n") - f.write("// DO NOT EDIT - This file is automatically generated\n") - f.write("//\n\n") - f.write("import Cvips\n") - if has_buffer_operations: - f.write("import CvipsShim\n") - f.write("\n") - - # Write instance methods in protocol extension - if instance_operations: - f.write("extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ {\n\n") - - for nickname, code in instance_operations: - f.write(code) - f.write("\n\n") - - # Add convenience methods for relational operations in the arithmetic category - if category == 'Arithmetic': - relational_methods = generate_relational_convenience_methods() - if relational_methods: - f.write(relational_methods) - f.write("\n\n") - - f.write("}\n") - - # Write static methods in concrete class extension - if static_operations: - if instance_operations: - f.write("\n") - f.write("extension VIPSImageProtocol where Self: ~Copyable /*, Self: ~Escapable */ {\n\n") - - for nickname, code in static_operations: - f.write(code) - f.write("\n\n") - - f.write("}\n") - - # Format the file using swift format - try: - subprocess.run(['swift', 'format', '--in-place', str(filepath)], - check=True, capture_output=True, text=True) - except subprocess.CalledProcessError as e: - print(f" āš ļø Warning: Failed to format {filepath}: {e}") - except FileNotFoundError: - print(f" āš ļø Warning: swift format not found, skipping formatting for {filepath}") - - return filepath - -def generate_relational_convenience_methods(): - """Generate convenience methods for relational operations.""" - methods = [] - - # Define relational operations and their corresponding enum values - relational_ops = [ - ('equal', 'equal', 'Test for equality'), - ('notequal', 'noteq', 'Test for inequality'), - ('less', 'less', 'Test for less than'), - ('lesseq', 'lesseq', 'Test for less than or equal'), - ('more', 'more', 'Test for greater than'), - ('moreeq', 'moreeq', 'Test for greater than or equal') - ] - - for method_name, enum_value, description in relational_ops: - # Method with VIPSImage parameter - make first param unnamed for operator compatibility - methods.append(f" /// {description}") - methods.append(f" ///") - methods.append(f" /// - Parameters:") - methods.append(f" /// - rhs: Right-hand input image") - methods.append(f" public func {method_name}(_ rhs: some VIPSImageProtocol) throws -> Self {{") - methods.append(f" return try relational(rhs, relational: .{enum_value})") - methods.append(f" }}") - methods.append(f"") - - # Method with Double parameter - methods.append(f" /// {description}") - methods.append(f" ///") - methods.append(f" /// - Parameters:") - methods.append(f" /// - value: Constant value") - methods.append(f" public func {method_name}(_ value: Double) throws -> Self {{") - methods.append(f" return try relationalConst(relational: .{enum_value}, c: [value])") - methods.append(f" }}") - methods.append(f"") - - # Add boolean operations for bitwise operators - boolean_ops = [ - ('andimage', 'and', 'Bitwise AND of two images'), - ('orimage', 'or', 'Bitwise OR of two images'), - ('eorimage', 'eor', 'Bitwise XOR of two images') - ] - - for method_name, enum_value, description in boolean_ops: - methods.append(f" /// {description}") - methods.append(f" ///") - methods.append(f" /// - Parameters:") - methods.append(f" /// - rhs: Right-hand input image") - methods.append(f" public func {method_name}(_ rhs: some VIPSImageProtocol) throws -> Self {{") - methods.append(f" return try boolean(rhs, boolean: .{enum_value})") - methods.append(f" }}") - methods.append(f"") - - # Add shift operations (these use boolean operations) - shift_ops = [ - ('lshift', 'lshift', 'Left shift'), - ('rshift', 'rshift', 'Right shift') - ] - - for method_name, enum_value, description in shift_ops: - methods.append(f" /// {description}") - methods.append(f" ///") - methods.append(f" /// - Parameters:") - methods.append(f" /// - amount: Number of bits to shift") - methods.append(f" public func {method_name}(_ amount: Int) throws -> Self {{") - methods.append(f" return try booleanConst(boolean: .{enum_value}, c: [Double(amount)])") - methods.append(f" }}") - methods.append(f"") - - return "\n".join(methods) if methods else "" - -def main(): - parser = argparse.ArgumentParser( - description='Generate Swift wrappers for VIPS operations using GObject introspection' - ) - parser.add_argument( - '--output-dir', '-o', - default='Sources/VIPS/Generated', - help='Output directory for generated files (default: %(default)s)' - ) - parser.add_argument( - '--dry-run', - action='store_true', - help='Print what would be generated without writing files' - ) - - args = parser.parse_args() - - print("šŸ” Discovering VIPS operations using GObject introspection...") - - operations_by_category = generate_all_operations() - - total_operations = sum(len(ops) for ops in operations_by_category.values()) - print(f"āœ… Found {total_operations} operations in {len(operations_by_category)} categories") - - if args.dry_run: - print("\nšŸ“Š Operations by category:") - for category in sorted(operations_by_category.keys()): - operations = operations_by_category[category] - print(f" {category}: {len(operations)} operations") - for nickname, _ in operations[:3]: - print(f" - {nickname}") - if len(operations) > 3: - print(f" ... and {len(operations) - 3} more") - return - - # Create output directory - output_dir = Path(args.output_dir) - output_dir.mkdir(parents=True, exist_ok=True) - - print(f"\nšŸ“ Generating Swift code in {output_dir}...") - - # Write files for each category - for category in sorted(operations_by_category.keys()): - operations = operations_by_category[category] - filepath = write_category_file(category, operations, output_dir) - print(f" āœ… Generated {filepath} ({len(operations)} operations)") - - print("\nšŸŽ‰ Code generation complete!") - print(f"\nšŸ“Š Summary:") - print(f" Total operations: {total_operations}") - print(f" Total categories: {len(operations_by_category)}") - -if __name__ == '__main__': - main() \ No newline at end of file