fix: provide a software image context for OCR compatibility

This commit is contained in:
Codex committed 2026-10-12 12:41:09 +00:00
1 parent b22eaf9715
commit ff576ad166
4 files changed
+34 -7

No files matched your search

+1
View File
@@ -4472,6 +4472,7 @@ dependencies = [
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-image",
"objc2-core-ml",
"objc2-foundation",
"objc2-image-io",
+2
View File
@@ -38,6 +38,7 @@ core-foundation = "0.10"
security-framework = "3"
objc2 = "0.6"
objc2-core-foundation = "0.3"
objc2-core-image = { version = "0.3", features = ["CIContext"] }
objc2-core-ml = { version = "0.3", features = ["MLCPUComputeDevice", "MLComputeDeviceProtocol"] }
objc2-image-io = { version = "0.3", features = ["CGImageSource"] }
objc2-app-kit = { version = "0.3", features = [
@@ -60,6 +61,7 @@ objc2-foundation = { version = "0.3", features = [
"NSDictionary",
"NSError",
"NSObject",
"NSValue",
] }
objc2-vision = { version = "0.3", features = [
"objc2-core-graphics",
@@ -3,6 +3,7 @@ import Foundation
import ImageIO
import Vision
import CoreML
import CoreImage
let file = URL(fileURLWithPath: CommandLine.arguments[1])
let data = try Data(contentsOf: file)
@@ -51,15 +52,20 @@ let profiles: [(String, (VNRecognizeTextRequest) throws -> Void)] = [
}),
]
for (name, configure) in profiles {
for software in [false, true] {
do {
let request = VNRecognizeTextRequest()
try configure(request)
let handler = VNImageRequestHandler(cgImage: image, options: [:])
let options: [VNImageOption: Any] = software
? [.ciContext: CIContext(options: [.useSoftwareRenderer: true])]
: [:]
let handler = VNImageRequestHandler(cgImage: image, options: options)
try handler.perform([request])
let text = request.results?.compactMap { $0.topCandidates(1).first?.string }.joined(separator: "\n") ?? ""
print("\(name): OK \(text)")
print("\(name) software=\(software): OK \(text)")
} catch {
let error = error as NSError
print("\(name): ERROR domain=\(error.domain) code=\(error.code) details=\(error.userInfo)")
print("\(name) software=\(software): ERROR domain=\(error.domain) code=\(error.code) details=\(error.userInfo)")
}
}
}
+22 -4
View File
@@ -6,11 +6,15 @@
#![cfg(target_os = "macos")]
use objc2::rc::{autoreleasepool, Retained};
use objc2::{AnyThread, ClassType};
use objc2::{AnyObject, AnyThread, ClassType};
use objc2_core_graphics::CGImage;
use objc2_core_image::{kCIContextUseSoftwareRenderer, CIContext};
use objc2_core_ml::MLCPUComputeDevice;
use objc2_foundation::{NSArray, NSObjectProtocol, NSString};
use objc2_vision::{VNImageRequestHandler, VNRecognizeTextRequest, VNRequestTextRecognitionLevel};
use objc2_foundation::{NSArray, NSDictionary, NSNumber, NSObjectProtocol, NSString};
use objc2_vision::{
VNImageOptionCIContext, VNImageRequestHandler, VNRecognizeTextRequest,
VNRequestTextRecognitionLevel,
};
/// 对指定图片文件路径执行 OCR,返回识别文本(按行拼接)。
pub fn recognize_file(path: &str) -> Result<String, String> {
@@ -46,11 +50,25 @@ pub(super) fn recognize_once(image: &CGImage, compatibility: bool) -> Result<Str
let request: Retained<VNRecognizeTextRequest> = VNRecognizeTextRequest::new();
configure_request(&request, compatibility)?;
let options = if compatibility || objc2::available!(macos = 27.0) {
let software = NSNumber::numberWithBool(true);
let values: [&AnyObject; 1] = [&software];
let context_options =
NSDictionary::from_slices(&[kCIContextUseSoftwareRenderer], &values);
let context = CIContext::contextWithOptions(Some(&context_options));
let values: [&AnyObject; 1] = [&context];
// CPU 模型选择不控制图像缩放器。显式软件 CIContext 避开
// 新系统后台/虚拟环境中不可用的硬件图像处理路径。
NSDictionary::from_slices(&[VNImageOptionCIContext], &values)
} else {
NSDictionary::new()
};
// 直接提供已规范化的 CGImage,避免 Vision 再走压缩数据解码路径。
let handler = VNImageRequestHandler::initWithCGImage_options(
VNImageRequestHandler::alloc(),
image,
&objc2_foundation::NSDictionary::new(),
&options,
);
let requests = NSArray::from_retained_slice(&[Retained::into_super(Retained::into_super(