Ändern Sie die Größe von UIImage auf 200x200pt / px

82

Ich habe Probleme, die Größe eines Bildes zu ändern. Grundsätzlich bin ich auf Folgendes gestoßen: Wie kann ich ein UIImage verkleinern und es gleichzeitig knusprig / scharf machen, anstatt es zu verwischen?

Dies scheint eine legitime Lösung zu sein, aber irgendwie funktioniert es nicht richtig.

Meine App funktioniert mit Fotos von der Kamerarolle. Die Größe dieser Fotos sollte auf etwa 200 x 200 geändert werden, wobei die Breite und nicht die Höhe wichtig sind.

Leider habe ich keinen Beispielcode, da ich ihn in meiner Wut über nicht funktionierende Lösungen verworfen habe, sorry.

swift_dan
quelle
Was genau funktioniert nicht richtig? Welches Ergebnis erwarten Sie und welches Ergebnis haben Sie erzielt?
Ifau
Ich erwarte ein Bild mit einer Breite von 200 und in diesem Verhältnis eine Höhe von x. Ich bekomme immer noch das Originalbild wie 1920x .... was auch immer
swift_dan

Antworten:

149

Hier ist mein Code. Das Bild hat eine Breite von 850 px und keine 200 px:

 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)

}
swift_dan
quelle
1
Um die Fehler in Swift 3 zu beseitigen, könnten Informationen in stackoverflow.com/a/37948158/1404324 helfen
Faruk
3
Arbeiten in Swift 4: 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

Basierend auf der Antwort von swift_dan ein Update für Swift 3

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
}
Christoph R.
quelle
2
Wenn Sie Qualität in Retina-Displays speichern und transparent speichern möchten, verwenden Sie: UIGraphicsBeginImageContextWithOptions (CGSize (Breite: newWidth, Höhe: newHeight), false, 0)
Evgeny Karev
Dies reduzierte mein Bild von 18 MB auf <als 1 MB! Ich habe verwendet: resizeImage (Bild: (info [UIImagePickerControllerOriginalImage] als? UIImage)!, NewWidth: 200) auf einem iPad 9.7 ". Bild aus imagePickerController. Mit swift 3.0
Brian
43

Wenn Sie mit PNG-Bildern arbeiten, die Transparentfolien enthalten, konvertiert die akzeptierte Antwortfunktion die transparenten Bereiche tatsächlich in Schwarz.

Wenn Sie die Folien skalieren und an Ort und Stelle halten möchten, versuchen Sie diese Funktion:

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
    }
}
Travis M.
quelle
1
Erstaunlich .. reduzierte Speicherfläche von unter 200 MB auf 18: D
Tom
3
Sie sollten auch die Bildschirmskala berücksichtigen, indem Sie die UIImage-Init durch Folgendes ersetzen:let scale = UIScreen.main.scale let newImage = UIImage(cgImage: context.makeImage()!, scale: scale, orientation: .up)
picciano
1
% 30 der Benutzer stürzt bei dieser Funktion ab. In der Zeile context.draw (self.cgImage!, In: newRect) > UIImage?
Kann Aksoy
1
Vielen Dank, @CanAksoy, ich habe die erzwungenen Optionen entfernt, dies sollte helfen.
Travis M.
21

Für Swift 3.0

Fügen Sie einfach dieses Snippet als Erweiterung hinzu UIImage. Denken Sie jedoch daran, dass das Bild nicht in quadratischer Form erstellt wird. Wenn es jedoch in dieser Form vorliegt, ist das Ergebnis quadratisch.

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!
    } }
Faruk
quelle
Versuchte diesen Code. Es erzeugt zwar ein kleines Bild, hinterlässt jedoch einen großen Speicherabdruck - weist dem Heap zusätzliche 100-200 MB zu ((
rommex
10

Swift 4.0 -

Wenn Sie mit Bildern arbeiten, die Transparentfolien enthalten, konvertiert die akzeptierte Antwortfunktion die transparenten Bereiche tatsächlich in Schwarz.

Wenn Sie die Folien skalieren und an Ort und Stelle halten möchten, versuchen Sie diese Funktion:

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
}
abhimanyu jindal
quelle
8

Dieser Code verwendet den in iOS 10 eingeführten UIGraphicsImageRenderer : In meinen Tests war er 10-40% schneller als frühere Beispiele mit UIGraphicsBeginImageContext (Swift 4 / Xcode 9):

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
        }
    }
rommex
quelle
Es gibt bereits eine Antwort, die dies abdeckt: stackoverflow.com/a/45936836/1489885
HAT
1
@ HAT mein Code ist kürzer, ist mit Erweiterung fertig und hat meine Leistungsdaten.
Rommex
Obwohl ich diese Antwort wirklich geliebt habe (für die Verwendung moderner Tools, schnelle und präzise Codierung), muss ich auf unerwartetes Verhalten hinweisen, das ich damit erlebt habe. Wenn das ursprüngliche UIImage von der Kamera abgeschnitten wurde und eine gewisse Größe hat (z. B. 1180 x 850) und ich den Code gebeten habe, es auf newWidth: 800 zu "verkleinern", hat es tatsächlich die Bildgröße verdreifacht - weil mein Gerät 3x Netzhaut hatte !! ! Man MUSS ein UIGraphicsImageRendererFormat mit der gewünschten Skala bereitstellen !!! In acht nehmen. Wir haben ein großes Bild statt eines kleinen.
Motti Shneor
7

Diese Funktion gibt ein Bild mit der von Ihnen angegebenen Breite zurück :

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)
}
Rashid
quelle
3

Weitere Verbesserung der Antwort von @rommex unter Verwendung einer maximalen Größe in Swift 4.2:

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))
        }
    }
}
Balázs Vincze
quelle
3

Dieser Code funktioniert hervorragend bei quadratischen Bildern und verliert nicht an Qualität

extension UIImage {

func resize(targetSize: CGSize) -> UIImage {
    return UIGraphicsImageRenderer(size:targetSize).image { _ in
        self.draw(in: CGRect(origin: .zero, size: targetSize))
    }
}

}

Antwort von: Ändern Sie die Bildgröße, ohne an Qualität zu verlieren

Ninahadi
quelle
2

Wenn Sie kingfisher lib zum Laden von Bildern in Ihr Projekt verwenden und die Größe ändern möchten, gehen Sie wie folgt vor:

  • Xcode 8
  • Swift 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)

    ODER

    Lokale Bildgröße ändern: - Sie können sich auf die Antwort von @Christoph R beziehen

  • Abdul Karim
    quelle
    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) ")
    Mohammad Razipour
    quelle
    0

    Reduzieren Sie die Bildgröße um 1024, Sie können immer entsprechend der Serverkapazität konvertieren

    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
            }
    
        }
    Urvish Modi
    quelle
    0

    Dies ist eine Fortsetzung der Antwort von @Christoph R, die für Swift 3.0 veröffentlicht wurde. Dieser Code funktioniert für Swift 5.0.1.

    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!
    }

    bei Anrufern vor Ort

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