Обрезка UIImage - PullRequest
       155

Обрезка UIImage

204 голосов
/ 01 октября 2008

У меня есть некоторый код, который изменяет размеры изображения, чтобы я мог получить масштабированный фрагмент центра изображения - я использую это, чтобы взять UIImage и вернуть маленькое квадратное представление изображения, подобное тому, что видно в альбомном представлении приложения "Фотографии". (Я знаю, что мог бы использовать UIImageView и настроить режим кадрирования для достижения тех же результатов, но эти изображения иногда отображаются в UIWebViews).

Я начал замечать некоторые сбои в этом коде, и я немного озадачен. У меня есть две разные теории, и мне интересно, есть ли одна из них на базе.

Теория 1) Обрезку я получаю, рисуя в контексте закадрового изображения моего целевого размера. Так как я хочу получить центральную часть изображения, я установил аргумент CGRect, переданный drawInRect, что-то большее, чем границы моего контекста изображения. Я надеялся, что это было кошерно, но вместо этого я пытаюсь привлечь другое воспоминание, которого я не должен касаться?

Теория 2) Я делаю все это в фоновом потоке. Я знаю, что есть части UIKit, которые ограничены основным потоком. Я предполагал / надеялся, что рисование за пределами экрана не было одним из них. Я не прав?

(Ох, как я скучаю по NSImage's drawInRect:fromRect:operation:fraction: методу.)

Ответы [ 23 ]

0 голосов
/ 10 января 2014

Я не был удовлетворен другими решениями, потому что они либо рисуют несколько раз (используя больше энергии, чем необходимо), либо имеют проблемы с ориентацией. Вот что я использовал для масштабированного квадратного обрезанного изображения из изображения UIImage *.

CGFloat minimumSide = fminf(image.size.width, image.size.height);
CGFloat finalSquareSize = 600.;

//create new drawing context for right size
CGRect rect = CGRectMake(0, 0, finalSquareSize, finalSquareSize);
CGFloat scalingRatio = 640.0/minimumSide;
UIGraphicsBeginImageContext(rect.size);

//draw
[image drawInRect:CGRectMake((minimumSide - photo.size.width)*scalingRatio/2., (minimumSide - photo.size.height)*scalingRatio/2., photo.size.width*scalingRatio, photo.size.height*scalingRatio)];

UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();
0 голосов
/ 28 октября 2016

Посмотрите на https://github.com/vvbogdan/BVCropPhoto

- (UIImage *)croppedImage {
    CGFloat scale = self.sourceImage.size.width / self.scrollView.contentSize.width;

    UIImage *finalImage = nil;
    CGRect targetFrame = CGRectMake((self.scrollView.contentInset.left + self.scrollView.contentOffset.x) * scale,
            (self.scrollView.contentInset.top + self.scrollView.contentOffset.y) * scale,
            self.cropSize.width * scale,
            self.cropSize.height * scale);

    CGImageRef contextImage = CGImageCreateWithImageInRect([[self imageWithRotation:self.sourceImage] CGImage], targetFrame);

    if (contextImage != NULL) {
        finalImage = [UIImage imageWithCGImage:contextImage
                                         scale:self.sourceImage.scale
                                   orientation:UIImageOrientationUp];

        CGImageRelease(contextImage);
    }

    return finalImage;
}


- (UIImage *)imageWithRotation:(UIImage *)image {


    if (image.imageOrientation == UIImageOrientationUp) return image;
    CGAffineTransform transform = CGAffineTransformIdentity;

    switch (image.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, image.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationUpMirrored:
            break;
    }

    switch (image.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationUp:
        case UIImageOrientationDown:
        case UIImageOrientationLeft:
        case UIImageOrientationRight:
            break;
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
            CGImageGetBitsPerComponent(image.CGImage), 0,
            CGImageGetColorSpace(image.CGImage),
            CGImageGetBitmapInfo(image.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.height, image.size.width), image.CGImage);
            break;

        default:
            CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
            break;
    }

    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;

}
0 голосов
/ 29 января 2016

Я использую метод ниже.

  -(UIImage *)getNeedImageFrom:(UIImage*)image cropRect:(CGRect)rect
  {
    CGSize cropSize = rect.size;
    CGFloat widthScale =  
    image.size.width/self.imageViewOriginal.bounds.size.width;
    CGFloat heightScale = 
    image.size.height/self.imageViewOriginal.bounds.size.height;
    cropSize = CGSizeMake(rect.size.width*widthScale,  
    rect.size.height*heightScale);
    CGPoint  pointCrop = CGPointMake(rect.origin.x*widthScale, 
    rect.origin.y*heightScale);
    rect = CGRectMake(pointCrop.x, pointCrop.y, cropSize.width, 
    cropSize.height);
    CGImageRef subImage = CGImageCreateWithImageInRect(image.CGImage, rect);
    UIImage *croppedImage = [UIImage imageWithCGImage:subImage];
    CGImageRelease(subImage);
    return croppedImage;

}

...