原图: 过滤后的图像:
我正在尝试将 UIImages(手机相机胶卷中的照片)裁剪成正方形。这是我正在使用的部分代码,其中“图像”是正在裁剪的图像:
if( image.size.height > image.size.width )
{
dimension = image.size.width;
imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.height-dimension)/2, 0, dimension, dimension));
如果我使用的是原始图像,此时它看起来像这样:
这很好,也是我所期望的 - 我有一个此处未显示的旋转算法来解决这个问题。
如果我使用过滤后的图像,它看起来像这样:
...不是正方形裁剪,而是奇怪地放大了。 所以这似乎是问题所在,我不知道为什么这些过滤后的图像表现不同。
}
else
{
dimension = image.size.height;
imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.width-dimension)/2, 0, dimension, dimension));
}
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
CGContextRef bitmap;
bitmap = CGBitmapContextCreate(NULL, dimension, dimension, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
我的问题是在最后一行,CGBitmapContextCreate,我有时会收到以下错误:
<Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 7744 for 8 integer bits/component, 3 components, kCGImageAlphaNoneSkipLast.
奇怪的是,通常不会发生这种情况 - 到目前为止,我只在原始图像的高度大于宽度时遇到此错误,并且它已被另一个应用程序过滤称为 Camera+...过滤前完全相同的照片没有问题,过滤后的风景照片似乎也没有问题。
任何人都可以在这里指导我或帮助我解释实际发生的事情吗?我从错误消息中了解到,如果我将 CGImageGetBytesPerRow(imageRef) 替换为大于 7744 的任意数字,错误将不再发生,但我对 CGImage 的理解还不够知道这实际上对任何事情有什么影响,而且在我看来这并不是一个实际的解决方案。此代码基于我在网络上看到的其他裁剪示例,因此我对这些位图功能的理解有限。
如有任何想法,我们将不胜感激!
编辑
我在 SO: In this CGBitmapContextCreate, why is bytesPerRow 0? 上发现了这个问题,它提示我尝试将 bytesPerRow 参数设置为 0。事实证明这消除了错误,但我的裁剪例程在与发生此错误时相同的情况下无法正常工作前。这可能需要一个特殊的人来回答,但是有没有人对图像过滤有足够的了解来猜测为什么这个代码以某种方式对纵向、相机+过滤的照片进行不同的处理?由于问题略有变化,我更新了标题。
EDIT2
我在上面的代码中添加了示例图像,最后,经过必要的旋转后,最终裁剪后的图像如下所示:
原始图像: - 完美!
过滤后的图像: - 太糟糕了!
用于创建这些最终的、据称经过裁剪的图像的代码是这样的:
CGContextDrawImage(bitmap, CGRectMake(0, 0, dimension, dimension), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
image = [UIImage imageWithCGImage:ref];
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
最佳答案
简而言之 - 由于某种原因,相机+过滤后的图像与原始图像相比具有不同的 imageOrientation
值。不知何故,这个事实导致了这样一行:
imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.height-dimension)/2, 0, dimension, dimension));
根据 image
的 imageOrientation
表现不同。因此,当图像方向为右或左的原始图像被这条线旋转到它的一侧时(这就是我使用 x 偏移裁剪的原因在纵向和横向尺寸中),过滤后的图像的方向是向上。因此,我没有得到预期的旋转,因此过滤后的图像被拉伸(stretch)了。为了解决这个问题,我在调用 CGImageCreateWithImageInRect
之前检查了图像的方向,如果它是纵向大小但方向是向上,我将使用 y 偏移而不是x(就像 David H 在下面提到的代码行)。
我的猜测是调用 [image CGImage] 将图像旋转到相对向上位置...因此如果方向是正确,图像将旋转 90 度逆时针方向,但如果方向是向上,则根本不会旋转。我仍然不明白为什么过滤后的图像最终会与原始图像的方向不同,但我认为这只是 camera+ 过滤代码中的某种副作用。所有这些定向内容本来可以简单得多,但这似乎是目前的解决方案。
关于iphone - "CGBitmapContextCreate: invalid data bytes/row"... 为什么 camera+ 过滤会打乱我的图像裁剪程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11907666/