2013-02-17 2 views
3

Мне нужно найти самый большой центрированный квадрат из портрета или пейзажного изображения, масштабированного до размера. . если я получаю изображение размером 1200x800, и мне нужно получить центрированный квадрат размером до 300x300.Нахождение самой большой центрированной площади от пейзажа или портрета UIImage и масштабирования до размера

ответ

15

Я нашел ответ на этот вопрос в stackoverflow, который был широко скопирован. Однако этот ответ неверен, так хочется, чтобы отправить правильный ответ, который выглядит следующим образом:

+ (UIImage*) cropBiggestCenteredSquareImageFromImage:(UIImage*)image withSide:(CGFloat)side 
{ 
    // Get size of current image 
    CGSize size = [image size]; 
    if(size.width == size.height && size.width == side){ 
    return image; 
    } 

    CGSize newSize = CGSizeMake(side, side); 
    double ratio; 
    double delta; 
    CGPoint offset; 

    //make a new square size, that is the resized imaged width 
    CGSize sz = CGSizeMake(newSize.width, newSize.width); 

    //figure out if the picture is landscape or portrait, then 
    //calculate scale factor and offset 
    if (image.size.width > image.size.height) { 
    ratio = newSize.height/image.size.height; 
    delta = ratio*(image.size.width - image.size.height); 
    offset = CGPointMake(delta/2, 0); 
    } else { 
    ratio = newSize.width/image.size.width; 
    delta = ratio*(image.size.height - image.size.width); 
    offset = CGPointMake(0, delta/2); 
    } 

    //make the final clipping rect based on the calculated values 
    CGRect clipRect = CGRectMake(-offset.x, -offset.y, 
           (ratio * image.size.width), 
           (ratio * image.size.height)); 

    //start a new context, with scale factor 0.0 so retina displays get 
    //high quality image 
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { 
    UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0); 
    } else { 
    UIGraphicsBeginImageContext(sz); 
    } 
    UIRectClip(clipRect); 
    [image drawInRect:clipRect]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return newImage; 
} 

неправильный ответ, который я нашел ранее, следующим образом:

+ (UIImage*) cropBiggestCenteredSquareImageFromImage:(UIImage*)image withSide:(CGFloat)side 
{ 
    // Get size of current image 
    CGSize size = [image size]; 
    if(size.width == size.height && size.width == side){ 
    return image; 
    } 

    CGSize newSize = CGSizeMake(side, side); 
    double ratio; 
    double delta; 
    CGPoint offset; 

    //make a new square size, that is the resized imaged width 
    CGSize sz = CGSizeMake(newSize.width, newSize.width); 

    //figure out if the picture is landscape or portrait, then 
    //calculate scale factor and offset 
    if (image.size.width > image.size.height) { 
    ratio = newSize.width/image.size.width; 
    delta = (ratio*image.size.width - ratio*image.size.height); 
    offset = CGPointMake(delta/2, 0); 
    } else { 
    ratio = newSize.width/image.size.height; 
    delta = (ratio*image.size.height - ratio*image.size.width); 
    offset = CGPointMake(0, delta/2); 
    } 

    //make the final clipping rect based on the calculated values 
    CGRect clipRect = CGRectMake(-offset.x, -offset.y, 
           (ratio * image.size.width) + delta, 
           (ratio * image.size.height) + delta); 


    //start a new context, with scale factor 0.0 so retina displays get 
    //high quality image 
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { 
    UIGraphicsBeginImageContextWithOptions(sz, YES, 0.0); 
    } else { 
    UIGraphicsBeginImageContext(sz); 
    } 
    UIRectClip(clipRect); 
    [image drawInRect:clipRect]; 
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return newImage; 
} 

Проблема с этим кодом является то, что ему неправильно растёт.

Оба эти коды можно попробовать на следующем изображении: https://s3.amazonaws.com/anandprakash/ImageWithPixelGrid.jpg

Правильный Algo генерирует следующие изображения на приведенном выше базовом URL: https://s3.amazonaws.com/anandprakash/ScreenshotCorrectAlgo.png

Неправильный Algo генерирует следующее изображение на приведенном выше базовом URL - обратите внимание на дополнительные 50 пикселей по ширине с каждой стороны. https://s3.amazonaws.com/anandprakash/ScreenshotWrongAlgo.png

0

Тот же ответ выше как Swift расширения на UIImage:

private extension UIImage { 
    func cropBiggestCenteredSquareImage(withSide side: CGFloat) -> UIImage { 
     if self.size.height == side && self.size.width == side { 
      return self 
     } 
     let newSize = CGSizeMake(side, side) 
     let ratio: CGFloat 
     let delta: CGFloat 
     let offset: CGPoint 
     if self.size.width > self.size.height { 
      ratio = newSize.height/self.size.height 
      delta = ratio * (self.size.width - self.size.height) 
      offset = CGPointMake(delta/2, 0) 
     } 
     else { 
      ratio = newSize.width/self.size.width 
      delta = ratio * (self.size.height - self.size.width) 
      offset = CGPointMake(0, delta/2) 
     } 
     let clipRect = CGRectMake(-offset.x, -offset.y, ratio * self.size.width, ratio * self.size.height) 
     if UIScreen.mainScreen().respondsToSelector(#selector(NSDecimalNumberBehaviors.scale)) { 
      UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0) 
     } else { 
      UIGraphicsBeginImageContext(newSize); 
     } 
     UIRectClip(clipRect) 
     self.drawInRect(clipRect) 
     let newImage = UIGraphicsGetImageFromCurrentImageContext() 
     UIGraphicsEndImageContext() 
     return newImage 
    } 
}