Мне нужно найти самый большой центрированный квадрат из портрета или пейзажного изображения, масштабированного до размера. . если я получаю изображение размером 1200x800, и мне нужно получить центрированный квадрат размером до 300x300.Нахождение самой большой центрированной площади от пейзажа или портрета UIImage и масштабирования до размера
ответ
Я нашел ответ на этот вопрос в 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
Тот же ответ выше как 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
}
}