iOS,尝试使用 UIGraphicsGetImageFromCurrentImageContext 呈现“变换缩放”视图时出现意外结果

Posted

技术标签:

【中文标题】iOS,尝试使用 UIGraphicsGetImageFromCurrentImageContext 呈现“变换缩放”视图时出现意外结果【英文标题】:iOS, Unexpected results when trying to render "transform scaled" view using UIGraphicsGetImageFromCurrentImageContext 【发布时间】:2013-02-27 07:05:49 【问题描述】:

我正在尝试在使用 UIGraphicsGetImageFromCurrentImageContext 进行转换后呈现视图及其内容。即使视图按比例缩小,但当我渲染它时,图像大小是正确的,但内容会以其原始大小呈现(在这种情况下,它们被裁剪而不是按预期适合视图。

这是一个简单的示例项目:http://owolf.net/uploads/***/ParentChildTransformTester.zip

进一步解释:我创建了一个父视图和一个子视图,将子视图添加为子视图。然后我转换缩放父视图,它也调整了子视图的大小(就像我想要的那样)。然后我以父视图的当前帧大小创建一个图像上下文,并进行渲染。代码如下。

//create views
UIView *parentView = [[UIView alloc]initWithFrame:self.view.bounds];
[parentView setBackgroundColor:[UIColor orangeColor]];
[self.view addSubview:parentView];

UIView *childView = [[UIView alloc]initWithFrame:CGRectMake(10, 10, 100, 100)];
[childView setBackgroundColor:[UIColor redColor]];
[parentView addSubview:childView];

//log parent view size : result is device screen size
NSLog(@"parentView.frame.size, BEFORE tran: %f x %f", parentView.frame.size.width, parentView.frame.size.height);

float scaleFactor = 0.2;
CGAffineTransform trans = CGAffineTransformScale(CGAffineTransformIdentity, scaleFactor, scaleFactor);
parentView.transform = trans;

//log parent view size after transform :  result is device screen size * 0.2
NSLog(@"parentView.frame.size, AFTER tran: %f x %f", parentView.frame.size.width, parentView.frame.size.height);


//attemt to render and save scaled parent view.
CGSize renderSize = CGSizeMake(parentView.frame.size.width, parentView.frame.size.height);
UIGraphicsBeginImageContext(CGSizeMake(renderSize.width, renderSize.height));

[[parentView layer] renderInContext:UIGraphicsGetCurrentContext()];

UIImage *renderedImage;
renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImageWriteToSavedPhotosAlbum(renderedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

【问题讨论】:

【参考方案1】:

您需要在渲染图层之前将变换应用于当前变换矩阵:

...
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextConcatCTM(ctx, [[parentView layer] affineTransform]);

[[parentView layer] renderInContext:ctx];
...

【讨论】:

谢谢!渲染后是否需要重置当前的变换矩阵? 不,最简单的方法是:CGContextSaveGStateCGContextConcatCTM、渲染、CGContextRestoreGState,然后继续绘制而不将转换应用于当前 CTM。【参考方案2】:

这行得通:根据上面 Graver 的回答进行了修改。

UIGraphicsBeginImageContext(parentView.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextConcatCTM(ctx, [[parentView layer] affineTransform]);
[[parentView layer] renderInContext:UIGraphicsGetCurrentContext()];
renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(renderedImage, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

【讨论】:

以上是关于iOS,尝试使用 UIGraphicsGetImageFromCurrentImageContext 呈现“变换缩放”视图时出现意外结果的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 socket.io 时出错

尝试使用meteor run ios运行iOS模拟器时没有这样的文件/目录消息

socket.io 不断尝试在错误的地址上使用轮询

尝试在 iOS 13 或 tvOS 13 中使用 AVPictureInPictureController 时出错

iOS,尝试使用 UIGraphicsGetImageFromCurrentImageContext 呈现“变换缩放”视图时出现意外结果

尝试在 iOS 上使用 Restkit - XCode