4

原始图像:在此处输入图像描述 过滤后的图像:在此处输入图像描述

我正在尝试将 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 上发现了这个问题:在这个 CGBitmapContextCreate 中,为什么 bytesPerRow 为 0?它提示我尝试将 bytesPerRow 参数设置为 0。事实证明这消除了错误,但我的裁剪例程在与之前发生此错误时相同的情况下无法正常工作。这可能需要一个特别的人来回答,但是有没有人对图像过滤有足够的了解来猜测为什么这个代码会以某种方式对面向肖像、相机+过滤的照片进行不同的处理?由于问题略有变化,我已经更新了标题。

编辑2

我在上面的代码中添加了示例图像,最后,在任何必要的旋转之后,最终裁剪的图像如下所示:

与原始图像:在此处输入图像描述- 完美!

过滤后的图像:在此处输入图像描述- 可怕!

用于创建这些最终的、被认为是裁剪图像的代码是这样的:

CGContextDrawImage(bitmap, CGRectMake(0, 0, dimension, dimension), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
image = [UIImage imageWithCGImage:ref];
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
4

2 回答 2

2

简而言之-由于某种原因,相机+过滤图像的imageOrientation值与原始图像不同。不知何故,这个事实导致了这样的一行:

imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake((image.size.height-dimension)/2, 0, dimension, dimension));

根据 的不同表现imageOrientation不同image。因此,虽然原始图像(其图像方向为rightleft)被这条线旋转到其一侧(这就是为什么我在纵向和横向尺寸中都使用 x 偏移量进行裁剪),但过滤后的图像的方向是向上的. 因此,我没有得到预期的旋转,因此过滤后的图像被拉伸了。为了解决这个问题,我在调用 之前检查图像的方向CGImageCreateWithImageInRect,如果它是纵向尺寸但具有向上方向,我会使用 y 偏移量而不是 x 进行裁剪(就像下面 David H 提到的代码行)。

我的猜测是调用 [image CGImage] 将图像旋转到相对向上的位置......所以如果方向是正确的,图像会逆时针旋转 90 度,但如果方向是向上的,它不会旋转一点也不。我仍然不明白为什么过滤后的图像最终的方向与原始图像不同,但我认为这只是 camera+ 过滤代码中的某种副作用。所有这些方向的东西可能会简单得多,但这似乎是目前的解决方案。

于 2012-08-14T18:49:39.197 回答
1

几点评论:

1)您希望在除以 2 时对值的十六进制值进行四舍五入,以免进入小数像素边界(用户 roundf())

2)你不处理两个维度相同的情况

3)在第一次创建中,您设置的是 x 偏移而不是 y - 使用此修改后的行:

imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectMake(0, (image.size.height-dimension)/2, dimension, dimension));
于 2012-08-11T01:13:13.527 回答