Обрезка основного изображения и масштабирование изображения по размеру - PullRequest
0 голосов
/ 04 августа 2020

Мне нужно обрезать миниатюрное изображение размера (w, h) из ciImage размера (W, H). Миниатюра обрезается и масштабируется до полного размера (w, h). Как правильно создать этот эскиз с помощью преобразования кадрирования и масштабирования основного изображения? По сути, мне нужна реализация scaledAspectFill с использованием основного изображения.

Вот мой код:

    var ciImage = CIImage(cvPixelBuffer: pixelBuffer)
   
    let width = CVPixelBufferGetWidth(pixelBuffer)
    let height = CVPixelBufferGetHeight(pixelBuffer)
    let imageSize = CGSize(width: width, height: height)
    

    var scaledImageRect = CGRect.zero
    
    let widthFactor = size.width / imageSize.width
    let heightFactor = size.height / imageSize.height

    let aspectRatio = max(widthFactor, heightFactor)

    scaledImageRect.size.width = imageSize.width * aspectRatio;
    scaledImageRect.size.height = imageSize.height * aspectRatio;
    scaledImageRect.origin.x = (size.width - scaledImageRect.size.width) / 2.0;
    scaledImageRect.origin.y = (size.height - scaledImageRect.size.height) / 2.0;
    
    ciImage = ciImage.cropped(to: scaledImageRect)

   let rect = CGRect(x: 0, y: 0, width: size.width,
                      height: size.height)

   //Do I need to scale again to fit 'size'??? If so, what should be scaling factor and what's the correct way to apply scaling transform that scales the image from center 
    
    let colorSpace = CGColorSpaceCreateDeviceRGB()

    if let jpegData = context.jpegRepresentation(of: ciImage, colorSpace: colorSpace, options: nil) {
        
      //Write jpegData

    } 

Этот код является излишним? Или есть более чистый и лучший способ добиться этого?

1 Ответ

1 голос
/ 06 августа 2020

Да, вам нужно уменьшить изображение перед вызовом jpegRepresentation, иначе вы просто вырежете небольшой прямоугольник из оригинала.

Этот код работает для меня:

let targetSize = CGSize(width: 50, height: 50)
let imageSize = ciImage.extent.size

let widthFactor = targetSize.width / imageSize.width
let heightFactor = targetSize.height / imageSize.height
let scaleFactor = max(widthFactor, heightFactor)

// scale down, retaining the original's aspect ratio
let scaledImage = ciImage.transformed(by: CGAffineTransform(scaleX: scaleFactor, y: scaleFactor))

let xInset = (scaledImage.extent.width - targetSize.width) / 2.0
let yInset = (scaledImage.extent.height - targetSize.height) / 2.0

// crop the center to match the target size
let croppedImage = scaledImage.cropped(to: scaledImage.extent.insetBy(dx: xInset, dy: yInset))
...