Finding the largest centered area from a landscape or UIImage portrait and scaling it to size

I need to find the largest centered square from a portrait or landscape image scaled to size. For example. if i get a 1200x800 image and i need to get a centered square up to 300x300.

+3


source to share


2 answers


I found the answer to this question on stackoverflow which has been copied widely. However, this answer is not correct, so you want to post the correct answer, which looks like this:

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

      

The incorrect answer I found earlier looks like this:

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

      



The problem with this code is that it is not being trimmed correctly.

Both codes can be tried in the following image: https://s3.amazonaws.com/anandprakash/ImageWithPixelGrid.jpg

Correct Algo generates the following image on the above base url: https://s3.amazonaws.com/anandprakash/ScreenshotCorrectAlgo.png

The wrong Algo generates the following image at the above base url - note the extra 50px wide on each side. https://s3.amazonaws.com/anandprakash/ScreenshotWrongAlgo.png

+15


source


Same answer above as Swift extension to 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
    }
}

      

0


source







All Articles