UIImage'ı 200x200pt / piksel olarak yeniden boyutlandırma


84

Bir resmi yeniden boyutlandırmakta zorlanıyorum. Temel olarak şunu buldum: Bir UIImage ölçeği nasıl küçültülür ve bulanık yerine aynı anda gevrek / keskin yapılır?

Bu yasal bir çözüm gibi görünüyor, ancak bir şekilde doğru çalışmıyor.

Uygulamam, Film Rulosundaki Fotoğraflar ile çalışır. Bu fotoğraflar yaklaşık 200x200 olarak yeniden boyutlandırılmalıdır, oysa genişlik önemlidir, yükseklik değil.

Maalesef, çalışmayan çözüm konusunda öfkeyle attığım için bir örnek kodum yok, üzgünüm.


Tam olarak doğru çalışmayan nedir? Ne gibi bir sonuç bekliyorsunuz ve ne sonuç aldınız?
ifau

200 genişliğinde ve bu oranda x yüksekliğinde bir görüntü bekliyorum. Hala
1920x

Yanıtlar:


150

İşte kodum. Görselin genişliği 850 pikseldir ve 200 piksel değildir:

 func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {

    let scale = newWidth / image.size.width
    let newHeight = image.size.height * scale
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
    image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}


@IBAction func chooseImage(sender: AnyObject) {


    var myPickerController = UIImagePickerController()
    myPickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
    myPickerController.delegate = self;
    self.presentViewController(myPickerController, animated: true, completion: nil)


}

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject])

{
    var imagenow = info[UIImagePickerControllerOriginalImage] as? UIImage

    imageImage.image = resizeImage(imagenow!, newWidth: 200)



    pimg2 = imageImage.image!

    cidnew2 = textFieldCID!.text!
    pname2 = textFieldName!.text
    pmanu2 = textFieldMan!.text
    pnick2 = textFieldNick!.text
    podate2 = textFieldPODate!.text
    pno2 = textFieldArtNo!.text



    self.dismissViewControllerAnimated(true, completion: nil)

}

1
Swift 3'teki hatalardan kurtulmak için stackoverflow.com/a/37948158/1404324
Faruk

3
swift 4'te çalışıyor: func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage { let scale = newWidth / image.size.width let newHeight = image.size.height * scale UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight)) image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage! }
mikey9

65

Swift_dan'ın cevabına göre, Swift 3 için bir güncelleme

func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {

    let scale = newWidth / image.size.width
    let newHeight = image.size.height * scale
    UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
    image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

2
Retina ekranlarda kaliteden tasarruf etmek ve şeffaf olarak kaydetmek istiyorsanız, şunu kullanın: UIGraphicsBeginImageContextWithOptions (CGSize (width: newWidth, height: newHeight), false, 0)
Evgeny Karev

Bu, resmimi 18MB'den <1 MB'a düşürdü! Ben kullandım: resizeImage (image: (bilgi [UIImagePickerControllerOriginalImage] as? UIImage) !, newWidth: 200) bir iPad 9.7 ". İmagePickerController'dan alınmış görüntü. Swift 3.0 kullanılıyor
Brian

43

Saydam içeren PNG görüntüleriyle uğraşıyorsanız, kabul edilen yanıt işlevi aslında saydam alanları siyaha dönüştürür.

Asetatları ölçeklendirmek ve yerinde tutmak istiyorsanız, şu işlevi deneyin:

SWIFT 4

extension UIImage {
    func scaleImage(toSize newSize: CGSize) -> UIImage? {
        var newImage: UIImage?
        let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
        if let context = UIGraphicsGetCurrentContext(), let cgImage = self.cgImage {
            context.interpolationQuality = .high
            let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height)
            context.concatenate(flipVertical)
            context.draw(cgImage, in: newRect)
            if let img = context.makeImage() {
                newImage = UIImage(cgImage: img)
            }
            UIGraphicsEndImageContext()
        }
        return newImage
    }
}

1
İnanılmaz .. bellek ayak izi 200 mb'nin altından 18'e düşürüldü: D
Tom

3
UIImage let scale = UIScreen.main.scale let newImage = UIImage(cgImage: context.makeImage()!, scale: scale, orientation: .up)
init'i

1
Kullanıcıların% 30'u bu işlevde çöküyor .. satır context.draw (self.cgImage !, in: newRect) ... Kilitlendi: com.apple.root.utility-qos 0x1001500a8 özel UIImage.scaleImage (toSize: CGSize) - > UIImage?
Can Aksoy

1
Teşekkürler @CanAksoy, zorunlu opsiyonları kaldırdım, bu yardımcı olmalı.
Travis M.

22

Swift 3.0 için

bu snippet'i uzantı olarak eklemeniz yeterlidir UIImage. Bununla birlikte, bunun görüntüyü kare yapmayacağını unutmayın, ancak bu şekilde olsaydı, sonuç kare olur.

extension UIImage {
    func resizeImage(newWidth: CGFloat) -> UIImage {

        let scale = newWidth / self.size.width
        let newHeight = self.size.height * scale
        UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
        self.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    } }

Bu kodu denedim. Bu küçük ;; er görüntü üretmek, ama bu çok büyük bir bellek baskısı yaprakları - öbek üzerinde bazı ekstra 100-200MB ayırır ((
rommex

10

Swift 4.0 -

Asetat içeren resimlerle uğraşıyorsanız, kabul edilen yanıt işlevi aslında şeffaf alanları siyaha dönüştürür.

Asetatları ölçeklendirmek ve yerinde tutmak istiyorsanız, şu işlevi deneyin:

func resizeImageWith(image: UIImage, newSize: CGSize) -> UIImage {

    let horizontalRatio = newSize.width / image.size.width
    let verticalRatio = newSize.height / image.size.height

    let ratio = max(horizontalRatio, verticalRatio)
    let newSize = CGSize(width: image.size.width * ratio, height: image.size.height * ratio)
    var newImage: UIImage

    if #available(iOS 10.0, *) {
        let renderFormat = UIGraphicsImageRendererFormat.default()
        renderFormat.opaque = false
        let renderer = UIGraphicsImageRenderer(size: CGSize(width: newSize.width, height: newSize.height), format: renderFormat)
        newImage = renderer.image {
            (context) in
            image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        }
    } else {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: newSize.width, height: newSize.height), isOpaque, 0)
        image.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
        newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
    }

    return newImage
}

8

Bu kod, iOS 10'da tanıtılan UIGraphicsImageRenderer'ı kullanıyor : testlerimde, UIGraphicsBeginImageContext (Swift 4 / Xcode 9) ile önceki örneklerden% 10-40 daha hızlıydı:

extension UIImage {
        func renderResizedImage (newWidth: CGFloat) -> UIImage {
            let scale = newWidth / self.size.width
            let newHeight = self.size.height * scale
            let newSize = CGSize(width: newWidth, height: newHeight)

            let renderer = UIGraphicsImageRenderer(size: newSize)

            let image = renderer.image { (context) in
                self.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: newSize))
            }
            return image
        }
    }

Bunu kapsayan bir cevap zaten var: stackoverflow.com/a/45936836/1489885
HAS

1
@ Kodum daha kısa, uzantı ile yapıldı ve performans verilerimi içeriyor.
rommex

Bu cevabı gerçekten sevmeme rağmen (modern araçları kullanmak için, hızlı ve özlü kodlama), onunla yaşadığım beklenmedik davranışları belirtmeliyim. Orijinal UIImage kameradan kırpılmışsa ve bir boyuta sahipse (örneğin 1180x850) ve koddan yeni Genişlik: 800'e "küçültmesini" istiyordum, aslında görüntü boyutunu ÜÇLÜYOR - çünkü cihazım 3x retina !! ! İstenen ölçekte bir UIGraphicsImageRendererFormat sağlamalıdır !!! Dikkat. Smallr yerine büyük imajımız var.
Motti Shneor

7

Bu işlev, belirttiğiniz genişlikte bir görüntü döndürür :

func scaleImage(image: UIImage, maximumWidth: CGFloat) -> UIImage {
    let rect: CGRect = CGRectMake(0, 0, image.size.width, image.size.height)
    let cgImage: CGImageRef = CGImageCreateWithImageInRect(image.CGImage!, rect)!
    return UIImage(CGImage: cgImage, scale: image.size.width / maximumWidth, orientation: image.imageOrientation)
}

Swift 3.0

func scaledImage(_ image: UIImage, maximumWidth: CGFloat) -> UIImage {
    let rect: CGRect = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)
    let cgImage: CGImage = image.cgImage!.cropping(to: rect)!
    return UIImage(cgImage: cgImage, scale: image.size.width / maximumWidth, orientation: image.imageOrientation)
}

4

Swift 4.2'de maksimum boyut kullanarak @rommex'in yanıtını daha da iyileştirmek :

private extension UIImage {
    func scaled(to maxSize: CGFloat) -> UIImage? {
        let aspectRatio: CGFloat = min(maxSize / size.width, maxSize / size.height)
        let newSize = CGSize(width: size.width * aspectRatio, height: size.height * aspectRatio)
        let renderer = UIGraphicsImageRenderer(size: newSize)
        return renderer.image { context in
            draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: newSize))
        }
    }
}


2

Projenizde görüntüleri yüklemek için kingfisher lib kullanıyorsanız ve onu yeniden boyutlandırmak istiyorsanız, şu şekilde:

  • Xcode 8
  • Hızlı 3x

    let imageUrl = URL(string: "your image url")
     //Size refer to the size which you want to resize your original image
     let size = CGSize(width: 60, height: 60)
     let processImage = ResizingImageProcessor(targetSize: size, contentMode: .aspectFit)
     cell.courseTitleImage.kf.setImage(with: imageUrl! , placeholder: UIImage(named: "placeholder"), options: [.transition(ImageTransition.fade(1)), .processor(processImage)], progressBlock: nil, completionHandler: nil)
    

    VEYA

    Yerel Resmi Yeniden Boyutlandır: - @Christoph R yanıtına başvurabilirsiniz.


  • 1
    func getScaledDimension(width: CGFloat, height: CGFloat,new_width: CGFloat, new_height: CGFloat)->CGPoint {
    
            let widthAspect =  (width / new_width)
            let heightAspect = (height / new_height)
            if widthAspect == 0 || heightAspect == 0 {
                return CGPoint(x: width, y: height)
            }
            var width1 : CGFloat = 0
            var height1 : CGFloat =  0
            if widthAspect > heightAspect {
                width1 = (width) / heightAspect
                height1 = (height) / heightAspect
            } else {
                width1 = (width) / widthAspect
                height1 = (height) / widthAspect
            }
    
            return CGPoint(x: width1, y: height1 )
        }
    
    
    
        func ResizeImage(image: UIImage, targetSize: CGSize) -> UIImage {
    
            let rect = CGRectMake(0, 0, targetSize.width, targetSize.height)
    
            UIGraphicsBeginImageContextWithOptions(targetSize, false, 1.0)
            image.drawInRect(rect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return newImage
        }
    
    
     let imagesize =  getScaledDimension(image.size.width, height: image.size.height , new_width: Width, new_height: Hieght)
    
            print("Image Size Scaled Dimension -> H:\(imagesize.x) W:\(imagesize.y)")
    
            let newImage = ResizeImage(image, targetSize: CGSizeMake(imagesize.x,imagesize.y))
            print("Resize Image Size -> H\(newImage.size.height) W\(newImage.size.width) ")
    

    1

    Bu @Christoph R'nin Swift 3.0 için gönderdiği cevabının devamıdır. Bu kod Swift 5.0.1 için çalışır.

    static func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
    
        let scale = newWidth / image.size.width
        let newHeight = image.size.height * scale
        UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
        image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
    
        return newImage!
    }
    

    arayanların sitesinde

    TaskUtilties.resizeImage(image: rawImage!, newWidth: CGFloat(50))
    

    0

    Görüntü boyutunu 1024 küçültün, her zaman sunucu kapasitesine göre dönüştürebilirsiniz

    func resizeImage(image: UIImage) -> UIImage {
    
            if image.size.height >= 1024 && image.size.width >= 1024 {
    
                UIGraphicsBeginImageContext(CGSize(width:1024, height:1024))
                image.draw(in: CGRect(x:0, y:0, width:1024, height:1024))
    
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
    
                return newImage!
    
            }
            else if image.size.height >= 1024 && image.size.width < 1024
            {
    
                UIGraphicsBeginImageContext(CGSize(width:image.size.width, height:1024))
                image.draw(in: CGRect(x:0, y:0, width:image.size.width, height:1024))
    
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
    
                return newImage!
    
            }
            else if image.size.width >= 1024 && image.size.height < 1024
            {
    
                UIGraphicsBeginImageContext(CGSize(width:1024, height:image.size.height))
                image.draw(in: CGRect(x:0, y:0, width:1024, height:image.size.height))
    
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
    
                return newImage!
    
            }
            else
            {
                return image
            }
    
        }
    
    Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
    Licensed under cc by-sa 3.0 with attribution required.