Как улучшить резкость при изменении размера UIImage?
В моем приложении мне нужно загружать фотографии на сервер, поэтому перед этим я хочу изменить их размер и сжать до приемлемого размера. Я попытался изменить их размер двумя способами, и первый из них:
// image is an instance of original UIImage that I want to resize
let width : Int = 640
let height : Int = 640
let bitsPerComponent = CGImageGetBitsPerComponent(image.CGImage)
let bytesPerRow = CGImageGetBytesPerRow(image.CGImage)
let colorSpace = CGImageGetColorSpace(image.CGImage)
let bitmapInfo = CGImageGetBitmapInfo(image.CGImage)
let context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo)
CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
CGContextDrawImage(context, CGRect(origin: CGPointZero, size: CGSize(width: CGFloat(width), height: CGFloat(height))), image.CGImage)
image = UIImage(CGImage: CGBitmapContextCreateImage(context))
Другой способ:
image = RBResizeImage(image, targetSize: CGSizeMake(640, 640))
func RBResizeImage(image: UIImage?, targetSize: CGSize) -> UIImage? {
if let image = image {
let size = image.size
let widthRatio = targetSize.width / image.size.width
let heightRatio = targetSize.height / image.size.height
// Figure out what our orientation is, and use that to form the rectangle
var newSize: CGSize
if(widthRatio > heightRatio) {
newSize = CGSizeMake(size.width heightRatio, size.height heightRatio)
} else {
newSize = CGSizeMake(size.width widthRatio, size.height widthRatio)
}
// This is the rect that we've calculated out and this is what is actually used below
let rect = CGRectMake(0, 0, newSize.width, newSize.height)
// Actually do the resizing to the rect using the ImageContext stuff
UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
image.drawInRect(rect)
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
} else {
return nil
}
}
После этого я использую UIImageJPEGRepresentation
сжать UIImage, но даже если compressionQuality
1, фотография по-прежнему размыта (это видно по краям объекта в основном, возможно, это не имеет большого значения, но фотография в три-пять раз больше той же фотографии из Instagram, например, но не имеет такой же резкости). Конечно, для 0.5 это еще хуже, а фотография все еще больше (в килобайтах), чем та же фотография из Instagram.
Фото из моего приложения. Качество сжатия - 1, края размыты, размер - 341 КБ.
Фото из Instagram, края острые, а размер составляет 136 КБ
РЕДАКТИРОВАТЬ:
Хорошо, но я немного запутался сейчас, я не уверен, что делать, чтобы сохранить соотношение сторон? Вот как я обрезаю изображение (scrollView имеет UIImageView, поэтому я могу перемещать и масштабировать изображение, и в конце я могу обрезать видимую часть scrollView, которая является sqare). Во всяком случае, изображение сверху изначально было 2048х2048, но оно все еще размытое.
var scale = 1/scrollView.zoomScale
var visibleRect : CGRect = CGRect()
visibleRect.origin.x = scrollView.contentOffset.x * scale
visibleRect.origin.y = scrollView.contentOffset.y * scale
visibleRect.size.width = scrollView.bounds.size.width * scale
visibleRect.size.height = scrollView.bounds.size.height * scale
image = crop(image!, rect: visibleRect)
func crop(srcImage : UIImage, rect : CGRect) -> UIImage? {
var imageRef = CGImageCreateWithImageInRect(srcImage.CGImage, rect)
var cropped = UIImage(CGImage: imageRef)
return cropped
}
1 ответ
Данный код верен, но проблема в том, что вы не поддерживаете соотношение сторон изображения
как в вашем коде вы создаете новый прямоугольник как
let rect = CGRectMake(0, 0, newSize.width, newSize.height)
если ваше заданное изображение имеет одинаковую высоту и ширину, оно даст плавное изменение размера изображения, но если высота и ширина отличаются, ваше изображение размыто. поэтому постарайтесь сохранить соотношение сторон
Ответить на редактирование вопроса:
сделать высоту или ширину кадрируемого изображения постоянной
Например, если вы сделаете ширину постоянной, используйте следующий код
visibleRect.size.height = orignalImg.size.height * visibleRect.size.width / orignalImg.size.width
image = crop(image!, rect: visibleRect)