无法使用 GPUImage 在 iOS7 上缩放 UIImage
Cannot use GPUImage to scale UIImage on iOS7
我已经编写了一年多的代码,成功地缩放、旋转并将 UIImage 转换为 1bpp(黑白)。它在我的 iPhone 5s、我测试过的 iPad 等上运行良好。但是,我的 iPhone 4 运行 iOS 7.1.2 崩溃了。
我的代码(UIImage 上的一个类别)是:
- (void) prepareImageForOCRWithCompletionHandler:(void (^) (UIImage *image))completion {
if (!completion) return; // no sense in doing anything if nobody listens for the completion
int width = self.size.width;
int height = self.size.height;
DLog(@"width=%d, height=%d", width, height);
if (width > height) {
int temp = width;
width = height;
height = temp;
}
int scaledWidth = 1728; // class F tiffs should be 1728, 2048 or 2483 pixels wide http://www.libtiff.org/support.html
int scaledHeight = scaledWidth * height / width;
DLog(@"width=%d, height=%d, scaledWidth=%d, scaledHeight=%d", width, height, scaledWidth, scaledHeight);
GPUImagePicture *source = [[GPUImagePicture alloc] initWithImage:self];
GPUImageFilter *rotateFilter = [[GPUImageFilter alloc] init];
[rotateFilter setInputRotation:kGPUImageRotateRight atIndex:0];
GPUImageTransformFilter *scaleFilter = [[GPUImageTransformFilter alloc] init];
[scaleFilter forceProcessingAtSizeRespectingAspectRatio:CGSizeMake(scaledWidth, scaledHeight)];
GPUImageAdaptiveThresholdFilter *thresholdFilter = [[GPUImageAdaptiveThresholdFilter alloc] init];
[source addTarget:rotateFilter];
[rotateFilter addTarget:scaleFilter];
[scaleFilter addTarget:thresholdFilter];
[source processImageWithCompletionHandler:^{
UIImage *result = [thresholdFilter imageFromCurrentlyProcessedOutput];
completion(result);
}];
}
在 Xcode 控制台中使用此消息调用 GPUImage 完成处理程序之前应用程序崩溃:
2015-02-05 13:39:10.131 MyApp[345:60b] -[UIImage(BJM) prepareImageForOCRWithCompletionHandler:] [Line 54] width=1936, height=2592
2015-02-05 13:39:10.133 MyApp[345:60b] -[UIImage(BJM) prepareImageForOCRWithCompletionHandler:] [Line 65] width=1936, height=2592, scaledWidth=1728, scaledHeight=2313
2015-02-05 13:39:12.328 MyApp[345:7273] *** Assertion failure in -[GPUImageTransformFilter createFilterFBOofSize:], /Users/brian/repos/GPUImage/framework/Source/GPUImageFilter.m:380
2015-02-05 13:39:12.364 MyApp[345:7273] void uncaughtExceptionHandler(NSException *__strong) [Line 75] uncaught exception: Incomplete filter FBO: 36054
2015-02-05 13:39:12.366 MyApp[345:7273] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Incomplete filter FBO: 36054'
*** First throw call stack:
(0x30560f83 0x3ad11ccf 0x30560e5d 0x30f0ed5b 0x2a7adf 0x2aa82d 0x2a73a7 0x2a7c77 0x2a7daf 0x2b0265 0x2a80d5 0x2a9285 0x2acd49 0x3b1f9833 0x3b1f9ded 0x3b1fa297 0x3b20c88d 0x3b20cb21 0x3b33bbd3 0x3b33ba98)
libc++abi.dylib: terminating with uncaught exception of type NSException
如果我从管道中删除 GPUImageTransformFilter,它就可以工作。如果我恢复变换过滤器但将 1728 更改为 1000,它也可以工作。这似乎是原始图像太小的问题。然而,原来的是 1936x2592。我还将我的宽度和高度整数更改为 CGFloats,认为舍入错误导致了问题。运气不好。
这真是一个令人羞愧的问题。谢谢你的时间。
您的问题与图片大小有关。在错误读数中,我看到您在图像中使用的高度为 2592。
对于 iPhone 4 及更早的设备,它们的 GPU 在任一维度上的纹理大小限制为 2048。尝试创建大于宽度或高度的纹理将导致失败,这是我提出的断言。
遗憾的是,我目前不支持大于您正在使用的任何 GPU 的纹理限制的图像。您需要找到另一种方法来在这些旧设备上将这些图像调整为大于 2048x2048 的大小。我在框架内的几个地方这样做(例如,处理在 iPhone 4 上拍摄的照片),但不是在所有地方。
我已经编写了一年多的代码,成功地缩放、旋转并将 UIImage 转换为 1bpp(黑白)。它在我的 iPhone 5s、我测试过的 iPad 等上运行良好。但是,我的 iPhone 4 运行 iOS 7.1.2 崩溃了。
我的代码(UIImage 上的一个类别)是:
- (void) prepareImageForOCRWithCompletionHandler:(void (^) (UIImage *image))completion {
if (!completion) return; // no sense in doing anything if nobody listens for the completion
int width = self.size.width;
int height = self.size.height;
DLog(@"width=%d, height=%d", width, height);
if (width > height) {
int temp = width;
width = height;
height = temp;
}
int scaledWidth = 1728; // class F tiffs should be 1728, 2048 or 2483 pixels wide http://www.libtiff.org/support.html
int scaledHeight = scaledWidth * height / width;
DLog(@"width=%d, height=%d, scaledWidth=%d, scaledHeight=%d", width, height, scaledWidth, scaledHeight);
GPUImagePicture *source = [[GPUImagePicture alloc] initWithImage:self];
GPUImageFilter *rotateFilter = [[GPUImageFilter alloc] init];
[rotateFilter setInputRotation:kGPUImageRotateRight atIndex:0];
GPUImageTransformFilter *scaleFilter = [[GPUImageTransformFilter alloc] init];
[scaleFilter forceProcessingAtSizeRespectingAspectRatio:CGSizeMake(scaledWidth, scaledHeight)];
GPUImageAdaptiveThresholdFilter *thresholdFilter = [[GPUImageAdaptiveThresholdFilter alloc] init];
[source addTarget:rotateFilter];
[rotateFilter addTarget:scaleFilter];
[scaleFilter addTarget:thresholdFilter];
[source processImageWithCompletionHandler:^{
UIImage *result = [thresholdFilter imageFromCurrentlyProcessedOutput];
completion(result);
}];
}
在 Xcode 控制台中使用此消息调用 GPUImage 完成处理程序之前应用程序崩溃:
2015-02-05 13:39:10.131 MyApp[345:60b] -[UIImage(BJM) prepareImageForOCRWithCompletionHandler:] [Line 54] width=1936, height=2592
2015-02-05 13:39:10.133 MyApp[345:60b] -[UIImage(BJM) prepareImageForOCRWithCompletionHandler:] [Line 65] width=1936, height=2592, scaledWidth=1728, scaledHeight=2313
2015-02-05 13:39:12.328 MyApp[345:7273] *** Assertion failure in -[GPUImageTransformFilter createFilterFBOofSize:], /Users/brian/repos/GPUImage/framework/Source/GPUImageFilter.m:380
2015-02-05 13:39:12.364 MyApp[345:7273] void uncaughtExceptionHandler(NSException *__strong) [Line 75] uncaught exception: Incomplete filter FBO: 36054
2015-02-05 13:39:12.366 MyApp[345:7273] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Incomplete filter FBO: 36054'
*** First throw call stack:
(0x30560f83 0x3ad11ccf 0x30560e5d 0x30f0ed5b 0x2a7adf 0x2aa82d 0x2a73a7 0x2a7c77 0x2a7daf 0x2b0265 0x2a80d5 0x2a9285 0x2acd49 0x3b1f9833 0x3b1f9ded 0x3b1fa297 0x3b20c88d 0x3b20cb21 0x3b33bbd3 0x3b33ba98)
libc++abi.dylib: terminating with uncaught exception of type NSException
如果我从管道中删除 GPUImageTransformFilter,它就可以工作。如果我恢复变换过滤器但将 1728 更改为 1000,它也可以工作。这似乎是原始图像太小的问题。然而,原来的是 1936x2592。我还将我的宽度和高度整数更改为 CGFloats,认为舍入错误导致了问题。运气不好。
这真是一个令人羞愧的问题。谢谢你的时间。
您的问题与图片大小有关。在错误读数中,我看到您在图像中使用的高度为 2592。
对于 iPhone 4 及更早的设备,它们的 GPU 在任一维度上的纹理大小限制为 2048。尝试创建大于宽度或高度的纹理将导致失败,这是我提出的断言。
遗憾的是,我目前不支持大于您正在使用的任何 GPU 的纹理限制的图像。您需要找到另一种方法来在这些旧设备上将这些图像调整为大于 2048x2048 的大小。我在框架内的几个地方这样做(例如,处理在 iPhone 4 上拍摄的照片),但不是在所有地方。