具有指定大小的 renderInContext 图像绘制

Posted

技术标签:

【中文标题】具有指定大小的 renderInContext 图像绘制【英文标题】:renderInContext image drawing with specified size 【发布时间】:2013-07-31 09:11:45 【问题描述】:

如何在不使用 CGAffineTransform 的情况下绘制小于上下文大小的图像?

UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// center image
CGContextTranslateCTM(context, placement.origin.x, placement.origin.y);
[imageView.layer renderInContext:context];

问题在于,如果imageView.image.size 大于size,它将居中绘制,但在边界处剪切(图像大于绘图区域)。我希望图像适合,所以想减小imageView.image.size 的大小。有没有办法使用renderInContext 来实现这一点?

【问题讨论】:

【参考方案1】:

通过[imageView.layer renderInContext:context];,您无法更改大小(或者我没有找到方法)。这样做的唯一选择是现在使用 drawImage 创建图像(根据请求的大小),分配新的 UIImageView 并绘制其图层。

UIImage *resizedImage = [self createNewImageFrom:currentImage withSize:size];
UIImageView *imageView = [[UIImageView alloc] initWithImage:resizedImage];
// ...
[imageView.layer renderInContext:context];


- (UIImage*)createNewImageFrom:(UIImage*)image withSize:(CGSize)size 
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0.0f, size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), image.CGImage);
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return outputImage;

【讨论】:

对否决票有什么意见,或者只是到处乱说?如果我做错了什么,最好告知是什么。 我正在寻找一些方法将图层渲染为不同的大小,最后我找到了方法,您的回答可能会误导其他与我相似的人。【参考方案2】:

为什么要在不改变上下文的情况下这样做?这是完成这项工作的最佳工具!

这里最简单的方法是调用CGContextScaleCTM 将比例因子应用于上下文。该比例因子将影响到上下文的所有绘图,包括对-renderIntoContext: 的调用。

【讨论】:

因为上下文已经被转换,我需要它保持原样 - 使用 saveCGState n Restore 也会产生问题。无论如何,我已经找到了解决我的问题的方法并在这里进行了描述,明天会接受这个答案(不能更早)。 如果 CGContextSaveGState/CGContextRestoreGState 没有恢复上下文的 CTM,那么你做错了什么。您的方法至少使用两倍的内存,并且执行时间至少是转换上下文的两倍。就像我说的:转换上下文是准确适合这项工作的工具。【参考方案3】:

这是缩放尺寸的版本,只需将 scale 替换为 size.width 和 size.height 即可获得任何目标尺寸。

对于 UIView:

-(UIImage*)convertViewToImage:(UIView*)v withScale:(float)scale
    //create bitmap context with scaled size
    CGSize s = v.bounds.size;
    s.width *= scale;
    s.height *= scale;
    UIGraphicsBeginImageContextWithOptions(s, NO, [UIScreen mainScreen].scale);

    //scale CTM to render and resotre CTM
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    CGContextScaleCTM(context, scale, scale);
    [v.layer renderInContext: context];
    CGContextRestoreGState(context);

    UIImage*image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;

对于 UIScrollView

-(UIImage*)convertScrollContentToImage:(UIScrollView*)sv withScale:(float)scale
    //create bitmap context with scaled size
    CGSize s = sv.contentSize;
    s.width *= scale;
    s.height *= scale;
    UIGraphicsBeginImageContextWithOptions(s, NO, [UIScreen mainScreen].scale);


    
        //set scroll.frame.size to contentSize, and contentOffset to 0
        CGPoint savedContentOffset = sv.contentOffset;
        CGRect savedFrame = sv.frame;

        sv.contentOffset = CGPointZero;
        sv.frame = CGRectMake(0, 0, sv.contentSize.width, sv.contentSize.height);

        //scale CTM to render and resotre CTM
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSaveGState(context);
        CGContextScaleCTM(context, scale, scale);
        [sv.layer renderInContext: context];
        CGContextRestoreGState(context);

        //set scroll.frame.size and ContentOffset back
        sv.contentOffset = savedContentOffset;
        sv.frame = savedFrame;

    

    UIImage*image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;

【讨论】:

CGContextSaveGState 非常消耗内存。我看不出这段代码比我的有任何优势,你能提供任何评论吗?

以上是关于具有指定大小的 renderInContext 图像绘制的主要内容,如果未能解决你的问题,请参考以下文章

将转换后的图像层应用于 renderInContext:

警告:“未找到 '-renderInContext' 方法”

为啥 renderInContext 比绘制到屏幕慢得多?

renderInContext在背景线程上创建黑色背景

iOS:renderInContext 和横向方向问题

带有阴影的 UIView - 应用 renderInContext 时速度很慢