3

サイズに合わせて拡大縮小されたポートレートまたはランドスケープ画像から、最大の中心付き四角数を見つける必要があります。たとえば、1200x800のサイズの画像を取得し、中心付き四角数を300x300のサイズに縮小する必要がある場合です。

4

2 に答える 2

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

間違ったアルゴは、上記のベースURLに次の画像を生成します-両側の幅に余分な50pxがあることに注意してください。 https://s3.amazonaws.com/anandprakash/ScreenshotWrongAlgo.png

于 2013-02-17T20:35:46.120 に答える
0

上記のUIImageのSwift拡張機能と同じ答え:

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
    }
}
于 2016-04-25T04:19:36.123 に答える