2013-10-04 2 views
1

Я думаю, что у меня может быть странный запрос, однако, надеюсь, кто-то может помочь. Я использую хорошо известный UIScrollView + UIImageView для увеличения и уменьшения изображения, а также панорамирования. Это отлично работает и денди, но в текущем проекте у нас есть возможность обрезать изображение, но также включать черные полосы по бокам, если изображение меньше прямоугольника обрезки. См. Изображения ниже.Обрезать часть UIImage из большего UIImage и включать части изображения, не содержащие изображения

Мы хотим захватить все внутри синего квадрата, включая белый (который будет черным, поскольку непрозрачный установлен на YES).

Это отлично подходит для изображений, которые полностью уменьшены (белый - просто дополнительное пространство UIImageView). enter image description here

Однако проблема возникает, когда мы пытаемся масштабировать изображение и снимаем только ту часть, плюс пустое пространство. enter image description here

Это приводит к следующему изображению enter image description here

Проблема, которую мы видим, что мы должны быть в состоянии создать изображение, которое является именно то, что находится в Rect Crop, независимо от того, есть часть изображение там или нет. Другая проблема заключается в том, что мы хотим иметь возможность динамически изменять разрешение вывода. Соотношение сторон составляет 16: 9, и для этого примера kMaxWidth = 1136 и kMaxHeight = 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; 
} 

Любая помощь будет принята с благодарностью.

ответ

3

В итоге я просто сделал снимок экрана и обрезал это. Кажется, он работает достаточно хорошо.

- (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:

+0

Вы ответили и приняли свой вопрос? лол – Rich86man

0

Я думаю, что переведенный прямоугольник для изображения не рассчитан правильно. Поскольку 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; 
} 

Edit: Да ... Я забыл упомянуть, что обрезание должно быть сделано в (0,1) координатного пространства. Я изменил функцию crop для вас, поэтому он обрезает изображение на основе всех параметров, которые вы предоставили, UIImageView внутри UIScrollView и изображения.

-(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; 
} 
+0

Я использовал вашу функцию как '[само cropImage: self.image inRect: [self.scrollView convertRect: self.scrollView.bounds toView: imageView]]. Однако это не сработало. –

+0

Можете ли вы рассказать мне, что такое ценность, которую вы получаете? – Mercurial

+0

@Muller - Я отредактировал свой ответ. – Mercurial

Смежные вопросы