应用图层蒙版后,我的图像缩小

时间:2013-12-09 22:21:57

标签: ios objective-c uiimageview calayer mask

我正在尝试使用UIImageUIBezierPath切割成不规则形状。 这就是我掩饰包含我感兴趣的UIImageView的{​​{1}}的方式:

UIImage

这是按预期工作的,我得到了正确的屏蔽- (void)maskImageView:(UIImageView *)image { UIBezierPath *path = [self getPath]; CGRect rect = CGRectZero; rect.size = image.image.size; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = CGRectMake(0, 0,image.frame.size.width, image.frame.size.height); shapeLayer.path = path.CGPath; shapeLayer.fillColor = [[UIColor whiteColor] CGColor]; shapeLayer.backgroundColor = [[UIColor clearColor] CGColor]; [image.layer setMask:shapeLayer]; } 。但是,我希望获得基础UIImageView,以便我可以在另一个图像上绘制它。这就是我得到UIImage

的方法
UIImage

然后我绘制图像并将其保存到相机胶卷中:

-(UIImage *)getCroppedImageForView:(UIImageView *)view{
    CGSize size = view.layer.bounds.size;
    UIGraphicsBeginImageContext(size);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

当我查看保存的图像时,我可以看到它比原始图像小,即使我在图像边缘周围绘制-(UIImage *)drawImage:(UIImage*)image { UIGraphicsBeginImageContext(image.size); [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)]; UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); UIImageWriteToSavedPhotosAlbum(finalImage, nil, nil, nil); return finalImage; } (没有真正裁剪它)。 我使用相同的方法绘制和保存其他图像,它们正确出来,所以我很确定问题出在UIBezierPath方法。 有人能指出我正确的方向吗?

修改

使用设备的相机拍摄图像,因此对于iPhone 5,尺寸为:3264x2448 包含图片的getCroppedImageForView的尺寸为:320x568,其UIImageViewcontentMode。 我想要实现的是获得全尺寸(3264x2448)裁剪后的图像,然后将其绘制在另一个图像(尺寸相同)之上。

1 个答案:

答案 0 :(得分:1)

有几点想法:

  1. 您注意到图像视图为320x568点,但图像本身为3264x2448像素。关键观察是UIGraphicsBeginImageContext...函数通过呈现UIImage来创建UIImageView,因此,生成的图片的大小将与UIKit的大小相关联控制并且与实际原始UIImage的大小关系不大。

  2. getCroppedImageForView中,您没有考虑设备的scale,特别是没有处理视网膜分辨率(生成320x568像素的图像)。通常你会做类似以下的事情:

    - (UIImage *)imageForView:(UIView *)view
    {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0);
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    

    通过UIGraphicsBeginImageContextWithOptions使用0作为最后一个选项,它将反映设备的比例,并且在视网膜屏幕上,它将生成640x1136像素的图像。

  3. maskImageView的一个小简化:默认情况下,添加子图层时,它将使用与图像视图相同的框架,因此您可以完全取消frame变量的设置,屈服:

    - (void)maskImageView:(UIImageView *)imageView
    {
        UIBezierPath *path = [self getPath];
        CAShapeLayer *shapeLayer = [CAShapeLayer layer];
        shapeLayer.path = path.CGPath;
        shapeLayer.fillColor = [[UIColor whiteColor] CGColor];
        shapeLayer.backgroundColor = [[UIColor clearColor] CGColor];
        [imageView.layer setMask:shapeLayer];
    }
    
  4. drawImage中,无需重新渲染图像。您已经拥有image。所以直接使用UIImage

    - (void)writeToSavedPhotosAlbum:(UIImage*)image
    {
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
    }
    

    但如果你真的想重新渲染图像,你可以使用我在上面第2点中说明的相同UIGraphicsBeginImageContextWithOptions语法,享受视网膜设备提供的额外分辨率。

    < / LI>

    虽然上述更改会使图像变大,但仍然比原始图像的3268x2448像素小得多。如果你真的想要创建一个3268x2448像素的最终图像,有两个选项可以跳出来:

    1. 一种选择是使图像视图与图像的大小相同(或者更准确地说,相同的大小除以屏幕比例)。您可能希望将此图像视图放在滚动视图上并适当设置缩放比例。

    2. 另一种选择是放弃UIKit来渲染图像,然后转移到Core Image(代码的主要重构)。

    3. 顺便提一下,请注意这些大图像会慢很多并且消耗更多内存。内部未压缩的尺寸各超过30 mb。