【问题标题】:Crop a Portion of UIImage from Larger UIImage, and include non-image parts从较大的 UIImage 中裁剪一部分 UIImage,并包括非图像部分
【发布时间】:2013-10-11 19:20:40
【问题描述】:

我想我可能有一个奇怪的要求,但希望有人能提供帮助。我正在使用众所周知的UIScrollView + UIImageView 来放大和缩小图像以及平移。这很好用,但我们当前的项目需要能够裁剪图像,但如果图像小于裁剪矩形,还包括侧面的黑条。请参阅下面的图片。

我们希望捕获蓝色框内的所有内容,包括白色(将是黑色,因为 opaque 设置为 YES)。

这对于完全缩小的图像非常有用(白色只是 UIImageView 的额外空间)。

但是,当我们尝试放大图像并仅捕获该部分以及空白区域时,就会出现问题。

这会产生以下图像

我们看到的问题是我们需要能够创建一个与裁剪矩形中完全相同的图像,无论那里是否有图像的一部分。另一个问题是我们希望能够动态改变输出分辨率。纵横比为 16:9,对于本示例为 kMaxWidth = 1136kMaxHeight = 639,但是将来我们可能希望请求更大或更小的 16:9 分辨率。

以下是我目前拥有的功能:

- (UIImage *)createCroppedImageFromImage:(UIImage *)image {
    CGSize newRect = CGSizeMake(kMaxWidth, kMaxHeight);
    UIGraphicsBeginImageContextWithOptions(newRect, YES, 0.0);

    // 0 is the edge of the screen, to help with zooming
    CGFloat xDisplacement = ((abs(0 - imageView.frame.origin.x) * kMaxWidth) / (self.cropSize.width / self.scrollView.zoomScale) / self.scrollView.zoomScale);

    CGFloat yDisplacement = ((abs(self.cropImageView.frame.origin.y - imageView.frame.origin.y) * kMaxHeight) / (self.cropSize.height / self.scrollView.zoomScale) / self.scrollView.zoomScale);

    CGFloat newImageWidth = (self.image.size.width * kMaxWidth) / (self.cropSize.width / self.scrollView.zoomScale);
    CGFloat newImageHeight = (self.image.size.height * kMaxHeight) / (self.cropSize.height / self.scrollView.zoomScale);    
   [image drawInRect:CGRectMake(xDisplacement, 0, newImageWidth, newImageHeight)];
    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return croppedImage;
}

任何帮助将不胜感激。

【问题讨论】:

    标签: ios uiscrollview uiimage ios7 crop


    【解决方案1】:

    我最终只是截取了屏幕截图,然后进行了裁剪。它似乎工作得很好。

    - (UIImage *)cropImage {
        CGRect cropRect = self.cropOverlay.cropRect;
        UIGraphicsBeginImageContext(self.view.frame.size);
    
        [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *fullScreenshot = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        CGImageRef croppedImage = CGImageCreateWithImageInRect(fullScreenshot.CGImage, cropRect);
        UIImage *crop = [[UIImage imageWithCGImage:croppedImage] resizedImage:self.outputSize interpolationQuality:kCGInterpolationHigh];
        CGImageRelease(croppedImage);
        return crop;
    }
    

    如果使用 iOS 7,您将使用 drawViewHierarchyInRect:afterScreenUpdates:,而不是 renderInContext:

    【讨论】:

      【解决方案2】:

      我认为图像视图的翻译矩形计算不正确。由于 UIImageView 是 UIScrollView 内部的子视图,因此您应该能够通过调用 [scrollView convertRect:scrollView.bounds toView:imageView]; 来计算可见矩形。那将是您的图像视图的可见矩形。你现在需要做的就是裁剪它。

      -(UIImage*)cropImage:(UIImage*)img inRect:(CGRect)rect{
          CGImageRef cropped = CGImageCreateWithImageInRect(img.CGImage, rect);
          UIImage *image =  [UIImage imageWithCGImage:cropped];
      
          CGImageRelease(cropped);
          return image;
      }
      

      编辑: 是的……我忘了说裁剪应该在 (0,1) 坐标空间中进行。我已经为您修改了裁剪功能,因此它会根据您提供的所有参数、UIScrollView 中的 UIImageView 和图像来裁剪图像。

      -(UIImage*)cropImage:(UIImage*)image inImageView:(UIImageView*)imageView scrollView:(UIScrollView*)scrollView{
          // get visible rect from image scrollview
          CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:imageView];
          UIImage* rCroppedImage;
      
          CALayer* maskLayer= [[CALayer alloc] init];
      
          maskLayer.contents= (id)image.CGImage;
          maskLayer.frame= CGRectMake(0, 0, visibleRect.size.width, visibleRect.size.height);
      
          CGRect rect= CGRectMake(visibleRect.origin.x / image.size.width,
                                  visibleRect.origin.y / image.size.height,
                                  visibleRect.size.width / image.size.width,
                                  visibleRect.size.height / image.size.height);
          maskLayer.contentsRect= rect;
          UIGraphicsBeginImageContext(visibleRect.size);
      
          CGContextRef context= UIGraphicsGetCurrentContext();
      
          [maskLayer renderInContext:context];
      
          rCroppedImage= UIGraphicsGetImageFromCurrentImageContext();
          UIGraphicsEndImageContext();
      
          return rCroppedImage;
      }
      

      【讨论】:

      • 我使用了[self cropImage:self.image inRect:[self.scrollView convertRect:self.scrollView.bounds toView:imageView]] 之类的函数,但它根本不起作用。
      • 你能告诉我你得到的 rect 的价值是多少吗?
      • 一些事情。 1. 这需要使用UIGraphicsBeginImageContextWithOptions,将 opaque 设置为 YES 给我们左右的黑条(这是强制性的)。 2. 将此与 opaque = YES 一起使用会使手机崩溃,而不仅仅是应用程序。 3. 没有使用kMaxWidthkMaxHeight 来指定输出图像的大小。
      • 使用UIGraphicsBeginImageContextWithOptions(visibleRect.size, YES, scrollView.zoomScale); 有助于使UIImage 不会导致崩溃,但是图像不是我想要的。它是屏幕的大小,我只在其中寻找 Crop Rect,它也是整个图像。
      猜你喜欢
      • 2017-06-20
      • 2017-01-15
      • 2016-03-31
      • 2017-06-13
      • 2018-01-25
      • 1970-01-01
      • 1970-01-01
      • 2012-05-15
      相关资源
      最近更新 更多