Thay đổi kích thước UIImage thành 200x200pt / px


82

Tôi đã gặp khó khăn trong việc thay đổi kích thước hình ảnh. Về cơ bản, tôi đã gặp khó khăn: Làm thế nào để thu nhỏ hình ảnh UIIm và làm cho nó trở nên giòn / sắc nét cùng một lúc thay vì mờ?

Đây có vẻ là một giải pháp hợp pháp nhưng bằng cách nào đó nó không hoạt động chính xác.

Ứng dụng của tôi hoạt động với Ảnh từ Thư viện ảnh. Ảnh này nên được thay đổi kích thước thành khoảng 200x200 trong khi chiều rộng là quan trọng, không phải chiều cao.

Rất tiếc, tôi không có mã mẫu vì tôi đã loại bỏ nó trong cơn thịnh nộ về giải pháp không hoạt động, xin lỗi.


Những gì chính xác không hoạt động chính xác? Bạn mong đợi kết quả nào và bạn đã nhận được kết quả gì?
ifau

tôi mong đợi một hình ảnh có chiều rộng là 200 và theo tỷ lệ này thì chiều cao là x. Tôi vẫn nhận được hình ảnh ban đầu như 1920x .... bất cứ điều gì
swift_dan

Câu trả lời:


149

Đây là mã của tôi. Hình ảnh có chiều rộng 850 px chứ không phải 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)

}

1
để thoát khỏi khỏi sai sót trong nhanh chóng 3, thông tin được cung cấp trong stackoverflow.com/a/37948158/1404324 có thể giúp
Faruk

3
làm việc trong nhanh chóng 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

Dựa trên câu trả lời của swift_dan, một bản cập nhật cho 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
}

2
Nếu bạn muốn tiết kiệm chất lượng trong màn hình dạng lưới và tiết kiệm trong suốt, sử dụng: UIGraphicsBeginImageContextWithOptions (CGSize (width: newWidth, chiều cao: newHeight), false, 0)
Evgeny Karev

Điều này đã làm giảm hình ảnh của tôi từ 18MB xuống còn <1 MB! Tôi đã sử dụng: resizeImage (image: (info [UIImagePickerControllerOriginalImage] as? UIImage) !, newWidth: 200) trên iPad 9.7 ". Hình ảnh được chụp từ imagePickerController. Sử dụng swift 3.0
Brian

43

Nếu bạn đang xử lý các hình ảnh PNG có chứa giấy trong suốt, thì hàm trả lời được chấp nhận sẽ thực sự chuyển các vùng trong suốt thành màu đen.

Nếu bạn muốn chia tỷ lệ và giữ nguyên độ trong suốt, hãy thử chức năng này:

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
Tuyệt vời .. giảm bộ nhớ từ dưới 200 MB đến 18: D
Tom

3
Bạn cũng nên đi vào xem xét quy mô màn hình bằng cách thay thế init UIImage với:let scale = UIScreen.main.scale let newImage = UIImage(cgImage: context.makeImage()!, scale: scale, orientation: .up)
Picciano

1
% 30 người dùng gặp sự cố trên chức năng này .. tại dòng context.draw (self.cgImage !, trong: newRect) ... Đã gặp sự cố: com.apple.root.utility-qos 0x1001500a8 UIImage.scaleImage chuyên biệt (toSize: CGSize) - > Hình ảnh?
Có thể Aksoy

1
Cảm ơn bạn, @CanAksoy, tôi đã xóa các tùy chọn bắt buộc, điều này sẽ hữu ích.
Travis M.

21

Đối với Swift 3.0

chỉ cần thêm đoạn mã này làm phần mở rộng vào UIImage. Tuy nhiên, hãy nhớ rằng điều đó sẽ không làm cho hình ảnh ở dạng hình vuông nhưng nếu nó ở dạng đó, kết quả sẽ là hình vuông.

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

Đã thử mã này. Nó tạo ra một hình ảnh nhỏ ;; er, nhưng nó để lại một bản in bộ nhớ khổng lồ - phân bổ thêm một số 100-200MB trên heap ((
rommex

10

Swift 4.0 -

Nếu bạn đang xử lý các hình ảnh chứa trong suốt, thì hàm trả lời được chấp nhận sẽ thực sự chuyển các vùng trong suốt thành màu đen.

Nếu bạn muốn chia tỷ lệ và giữ nguyên độ trong suốt, hãy thử chức năng này:

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

Mã này sử dụng UIGraphicsImageRenderer được giới thiệu trong iOS 10: trong thử nghiệm của tôi, nó nhanh hơn 10-40% so với các mẫu trước đó với 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
        }
    }

Đã có câu trả lời cho vấn đề này: stackoverflow.com/a/45936836/1489885
ĐÃ CÓ

1
@HAS mã của tôi ngắn hơn, được thực hiện với phần mở rộng và có dữ liệu về hiệu suất của tôi.
rommex

Mặc dù tôi thực sự thích câu trả lời này (vì sử dụng các công cụ hiện đại, mã hóa nhanh và ngắn gọn), tôi phải chỉ ra hành vi không mong muốn mà tôi đã trải qua với nó. Nếu hình ảnh UII ban đầu được cắt khỏi máy ảnh và có một số kích thước, (giả sử 1180x850) và tôi đã yêu cầu mã "thu nhỏ" thành newWidth: 800, nó thực sự đã TRUYỀN kích thước hình ảnh - vì thiết bị của tôi là 3x retina !! ! Người ta PHẢI cung cấp một UIGraphicsImageRendererFormat với tỷ lệ mong muốn !!! Hãy coi chừng. Chúng tôi có hình ảnh lớn thay vì nhỏ hơn.
Motti Shneor

7

Hàm này sẽ trả về một hình ảnh có chiều rộng bạn đã chỉ định:

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

Cải thiện hơn nữa câu trả lời của @rommex bằng cách sử dụng kích thước tối đa, trong 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))
        }
    }
}


2

Nếu bạn đang sử dụng lib bói cá để tải hình ảnh trong dự án của bạn và muốn thay đổi kích thước nó thì đây là cách:

  • 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)
    

    HOẶC LÀ

    Thay đổi kích thước hình ảnh cục bộ: - bạn có thể tham khảo câu trả lời của @Christoph R


  • 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

    Đây là phần tiếp theo câu trả lời của @Christoph R được đăng cho Swift 3.0. Mã này hoạt động cho 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!
    }
    

    tại trang web của người gọi

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

    0

    Giảm kích thước hình ảnh xuống 1024, bạn luôn có thể chuyển đổi theo dung lượng máy chủ

    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
            }
    
        }
    
    Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
    Licensed under cc by-sa 3.0 with attribution required.