我的目的是编写一个可以提取较大图像的旋转矩形部分的函数。该旋转的矩形部分用中心点(从0到完整图像宽度/高度)的尺寸和旋转角度来描述。
我担心我不了解CGContexts。我知道旋转后,我的坐标空间会旋转。
如果角度为0,此功能始终有效,如果角度较小,则此功能似乎正确。但是,随着角度的增加,一切都不正确地抵消了。
我正在使用类似于图像变换的仿射变换来计算左上角,以避免任何不准确。我还尝试通过对其应用图像变换来进一步更改左上角,以及图像变换的反转(就像随机想法一样)。
这种方法有效吗?我在某个地方错过了空间转换吗?
注意:通过绘制完整图像,然后使用正确的大小和旋转在正确的位置绘制黑色矩形,可以非常轻松地将图像区域遮挡。鉴于此,我知道我的输入是正确的。
可视化:
这表示完整的图像,以及我试图采样的旋转的rect:
此图像表示此功能的所需输出:
- (UIImage*) croppedImage:(UIImage*) image center:(CGPoint) rotationCenter size:(CGSize) size rotation:(CGFloat) rotation
{
CGFloat fullWidth = image.size.width;
CGFloat fullHeight = image.size.height;
CGRect imageRect = CGRectMake(0, 0, fullWidth, fullHeight);
//must convert UI space to CG space, in this case that just means adjusting the y coordinate
rotationCenter.y = fullHeight - rotationCenter.y;
CGFloat width = size.width;
CGFloat height = size.height;
int flags = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
CGContextRef btx = CGBitmapContextCreate(NULL, width, height, 8, 0, CGColorSpaceCreateDeviceRGB(), flags);
CGContextSetAllowsAntialiasing(btx, YES);
CGContextSetShouldAntialias(btx, YES);
//use a transformation to rotate at the center of the request area
CGAffineTransform imageTransform = CGAffineTransformIdentity;
imageTransform = CGAffineTransformTranslate(imageTransform, rotationCenter.x, rotationCenter.y);
imageTransform = CGAffineTransformRotate(imageTransform, rotation);
imageTransform = CGAffineTransformTranslate(imageTransform, -rotationCenter.x, -rotationCenter.y);
//use a transformation to determine the top-left coordinate of the rect
CGAffineTransform ptTransform = CGAffineTransformIdentity;
ptTransform = CGAffineTransformTranslate(ptTransform, rotationCenter.x, rotationCenter.y);
ptTransform = CGAffineTransformRotate(ptTransform, rotation);
ptTransform = CGAffineTransformTranslate(ptTransform, -width/2.0, -height/2.0);
//this gets me the position of the top-left corner of the image no matter the rotation
CGPoint topleft = CGPointApplyAffineTransform(CGPointZero, ptTransform);
CGContextConcatCTM(btx, imageTransform);
//move the image away from the origin, to align origin with where i want my image sampled from
CGContextTranslateCTM(btx, -topleft.x,
-topleft.y);
//Close... but wrong
CGContextDrawImage(btx, imageRect, image.CGImage);
CGImageRef img = CGBitmapContextCreateImage(btx);
UIImage* uiimage = [UIImage imageWithCGImage:img scale:image.scale orientation:image.imageOrientation];
CGContextRelease(btx);
CGImageRelease(img);
return uiimage;
}
答案 0 :(得分:1)
我相信,你所描述的是这样的事情:
这是一个实际运行的iOS应用程序,所以你可以看到我做了什么:在第一张图片中,我用蓝色绘制了我打算捕捉的矩形,并在图像视图中显示结果;在第二张图片中,我捕获了它,并在图像视图中显示结果。
正如您所看到的那样,仔细观察第二张图像的边缘,我们已经准确地捕捉到了蓝色矩形内容。
所以现在我想你想知道我是怎么做到的?使用三条信息绘制蓝色矩形:矩形的左上角topLeft
,矩形的大小size
和旋转rot
。为了简化事情,我忽略了你对“中心”的讨论;我绕左上角旋转。
然后通过创建大小为size
的图形上下文,将其旋转为rot
的负片,并以topLeft
的负片绘制完整的原始图像来捕获第二个图像。实际绘图部分只有两行代码(对不起,我现在在Swift中编写并思考,但我相信你可以翻译):
CGContextRotateCTM(context, -rot)
im.drawAtPoint(CGPointMake(-topLeft.x, -topLeft.y))
所以我猜我的答案最终是:这很容易,并且正如您所期望的那样工作,如果您将转换您想要做的原始描述,以便有topLeft
而不是中心。