CGImageCreateWithImageInRect无法正确裁剪

4

使用CGImageCreateWithImageInRect裁剪照片让我头疼不已。我的应用程序允许用户移动/放大图像,直到填满316 x 316的视图,然后我想将其裁剪掉超出框外的任何区域,并将图像保存为UIImage。我通过取x和y imageview原点的绝对值来确定裁剪原点,因为这会将我带回包含imageview的视图/框的0,0位置。以下是代码:

    CGRect croppedRect = CGRectMake(fabs(widthDistanceToOrigin), fabs(HeightDistanceToOrigin), 316, 316);
    CGImageRef croppedImageRef = CGImageCreateWithImageInRect(image.CGImage, croppedRect); 
    UIImage *croppedImage = [UIImage imageWithCGImage: croppedImageRef scale: 1 / (imageScale) orientation: image.imageOrientation];
    CGImageRelease(croppedImageRef); 

这真的让我疯了,我就是无法把它裁剪成我想要的区域。虽然我已经成功地缩放了它,但问题似乎出在裁剪矩形的x和y原点上,它与应该取的区域相差很大(有时会得到奇怪的结果)。
此外,对于使用手机相机拍摄的图片,我必须将裁剪矩形中的所有内容乘以2才能得到正确的大小。非常奇怪。
所以我想知道,有没有人知道如何解决这个问题,或者有没有更好的裁剪方法(请记住,我需要裁剪照片中的某个区域)。谢谢!

请在答案中提供您的解决方案,并在系统允许时接受它。 - Tim Post
3个回答

4
有关此主题的帖子非常多,它们都有完全相同的答案,即使用:CGImageCreateWithImageInRect,但是它们都没有完全解决试图裁剪的位置错误的问题。
然而,只有一个线程(深深地埋在内部),有一个细节是其他人都错过了... 如何在“适应”模式下将UIImageView裁剪为新的UIImage? 传递给CGImageCreateWithImageInRect(image.CGImage,croppedRect)的'rect'参数需要表示(取自)UIImage,而不是UIImageView。
这应该解决坐标系上位置不正确的问题。
 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:   (NSDictionary *)info
 {
        oImage = [info valueForKey:UIImagePickerControllerOriginalImage];
        NSLog(@"Original Image size width: %f x height: %f", oImage.size.width, oImage.size.height);


        // crop image according to what the image picker view is displaying
        CGRect rect = CGRectMake(0, 40, 960.0f, 960.0f); // note: 960 x 1280 is what natively comes from capturing and image
        nImage = [BGViewModifiers cropImage:oImage inRect:rect];

        // scale image down for display and creating kombie
        CGSize size = CGSizeMake(320.0f, 320.0f);
        nImage = [BGViewModifiers imageFromImage:nImage scaledToSize:size];

        NSLog(@"New Image size width: %f x height: %f", [nImage size].width, [nImage size].height);
 }

 //ref: https://dev59.com/vnVC5IYBdhLWcg3w4VNy#25293588
 + (UIImage *)cropImage:(UIImage*)image inRect:(CGRect)rect
 {
    double (^rad)(double) = ^(double deg) {
       return deg / 180.0 * M_PI;
    };

    CGAffineTransform rectTransform;
    switch (image.imageOrientation) {
      case UIImageOrientationLeft:
          rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
          break;
      case UIImageOrientationRight:
          rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
          break;
      case UIImageOrientationDown:
          rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
          break;
      default:
          rectTransform = CGAffineTransformIdentity;
  };
  rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);

  CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectApplyAffineTransform(rect, rectTransform));
  UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
  CGImageRelease(imageRef);

  return result;
 }

 + (UIImage*)imageFromImage:(UIImage*)image scaledToSize:(CGSize)newSize
 {
    UIGraphicsBeginImageContext( newSize );
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
 }

1
我希望根据我的经验提供更多信息/答案。
从UIImage(因此也是CGImageCreateWithImageInRect:)的角度来看,(0,0)在左下角。 在确定裁剪正方形时,您可以基于标准纵向方向计算正方形,然后使用@greenhouse答案中的方法(为了清晰起见再次发布,并更改为使用CGFloat以修复强制转换错误)。
- (UIImage *)cropImage:(UIImage*)image toRect:(CGRect)rect {
    CGFloat (^rad)(CGFloat) = ^CGFloat(CGFloat deg) {
        return deg / 180.0f * (CGFloat) M_PI;
    };

    // determine the orientation of the image and apply a transformation to the crop rectangle to shift it to the correct position
    CGAffineTransform rectTransform;
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
            break;
        case UIImageOrientationRight:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
            break;
        case UIImageOrientationDown:
            rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
            break;
        default:
            rectTransform = CGAffineTransformIdentity;
    };

    // adjust the transformation scale based on the image scale
    rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);

    // apply the transformation to the rect to create a new, shifted rect
    CGRect transformedCropSquare = CGRectApplyAffineTransform(rect, rectTransform);
    // use the rect to crop the image
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, transformedCropSquare);
    // create a new UIImage and set the scale and orientation appropriately
    UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
    // memory cleanup
    CGImageRelease(imageRef);

    return result;
}

这段代码将裁剪框移动到正确的相对位置。

对我来说完美地工作了。 - user1762670

0

我找到了问题所在。我试图在缩放图像之前抓取裁剪区域。现在必须想办法在执行“CGImageCreateWithImageInRect”之前缩小图像。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接