4

我想从像 instagram 这样的应用程序中拍一张方形照片。但是我不知道该怎么做。我知道y,图像仍然需要裁剪,并且相机一直在捕捉整个图像,只是我在视图中“实时”裁剪它。当图像被捕获时,它仍然是整个图像,仍然需要裁剪。只有用户看不到它的发生,因为这一切都是在后台完成的。使用设备相机捕获图像后,将其放入 UIImage 的实例中,然后编写一个方法,该方法将采用该 UIIMage 并使用 CGRefImageContext 调整其大小,然后如果不再需要原始 UIImage 实例,则覆盖您的原始 UIImage 实例。我不明白如何做到这一点。有没有显示如何做到这一点的网站?或者有没有更简单的方法来做到这一点。

4

1 回答 1

10

First, you need to take the photo with the camera, so add this code where you want to take the picture.

UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];

if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
{
    pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
    pickerController.delegate = self;
    [self presentViewController:pickerController 
                       animated:YES
                     completion:nil];
}

Then, you need to implement delegate methods. Your class must conform to UIImagePickerControllerDelegate, documented here. In the imagePickerController: didFinishPickingMediaWithInfo: method, you can take the taken photo in a UIImage with:

UIImage *imageTaked = info[UIImagePickerControllerOriginalImage]; 

If you want, at this point you can take the metadata of the taken photo with

info [UIImagePickerControllerMediaMetadata];

Finally, when you have your photo in a UIImage, you can crop the image as follows:

CGFloat x, y, side; //We will see how to calculate those values later.
UIImage* imageCropped;
CGRect cropRect = CGRectMake(x,y,side,side);
CGImageRef imageRef = CGImageCreateWithImageInRect([imageTaked CGImage], cropRect);
imageCropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);

So, the important thing here is how to calculate the cropRect to cut the centre square of the UIImage. To do that, you can calculate x, y and side as follows:

side = MIN(imageTaked.size.width, imageTaked.size.height
x = imageTaked.size.width / 2 - side / 2;
y = imageTaked.size.height / 2 - side / 2;

Ok, so, to summarise, all the code inside the imagePickerController: didFinishPickingMediaWithInfo: method results in:

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *imageTaked = info[UIImagePickerControllerOriginalImage]; 
    //You can take the metadata here => info [UIImagePickerControllerMediaMetadata];

    UIImage* imageCropped;

    CGFloat side = MIN(imageTaked.size.width, imageTaked.size.height);
    CGFloat x = imageTaked.size.width / 2 - side / 2;
    CGFloat y = imageTaked.size.height / 2 - side / 2;

    CGRect cropRect = CGRectMake(x,y,side,side);
    CGImageRef imageRef = CGImageCreateWithImageInRect([imageTaked CGImage], cropRect);
    imageCropped = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
}

EDIT

If you want to send your photo to another device, probably the photo will be rotated. That's because Apple uses exif metadata for images, but other platforms don't. To solve this problem, just use this method to set appropriate metadata info:

-(UIImage*)getImageWithCorrectFiltersFromOriginalImage:(UIImage *)originalImage
{
    UIImageOrientation orientation = UIImageOrientationUp;
    NSNumber* orientationValue = [originalImage valueForProperty:@"ALAssetPropertyOrientation"];
    if (orientationValue) {
        orientation = [orientationValue intValue];
    }

    ALAssetRepresentation *assetRep = [originalImage defaultRepresentation];
    CGImageRef imageRef = [assetRep fullResolutionImage];
    return [UIImage imageWithCGImage:imageRef scale:[assetRep scale] orientation:orientation];
}

Hope it helps! and let me know if something goes wrong during copy-paste process, it's 2:00AM here, and i'm a zombie man right now!

于 2013-08-03T04:45:07.643 回答