Làm thế nào để dễ dàng thay đổi kích thước / tối ưu hóa kích thước hình ảnh với iOS?


114

Ứng dụng của tôi đang tải xuống một tập hợp các tệp hình ảnh từ mạng và lưu chúng vào đĩa cục bộ của iPhone. Một số hình ảnh có kích thước khá lớn (ví dụ: chiều rộng lớn hơn 500 pixel). Vì iPhone thậm chí không có màn hình đủ lớn để hiển thị hình ảnh ở kích thước ban đầu, tôi đang lên kế hoạch thay đổi kích thước hình ảnh thành một thứ gì đó nhỏ hơn một chút để tiết kiệm không gian / hiệu suất.

Ngoài ra, một số hình ảnh trong số đó là JPEG và chúng không được lưu dưới dạng cài đặt chất lượng 60% thông thường.

Làm cách nào để thay đổi kích thước ảnh bằng iPhone SDK và làm cách nào để thay đổi cài đặt chất lượng của ảnh JPEG?

Câu trả lời:


246

Một vài gợi ý được đưa ra như câu trả lời cho câu hỏi này . Tôi đã đề xuất kỹ thuật được mô tả trong bài đăng này , với mã liên quan:

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}

Đối với việc lưu trữ hình ảnh, định dạng hình ảnh nhanh nhất để sử dụng với iPhone là PNG, vì nó có tối ưu hóa cho định dạng đó. Tuy nhiên, nếu bạn muốn lưu trữ những hình ảnh này dưới dạng JPEG, bạn có thể lấy UIImage của mình và thực hiện như sau:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

Điều này tạo ra một cá thể NSData chứa các byte thô cho ảnh JPEG ở cài đặt chất lượng 60%. Nội dung của cá thể NSData đó sau đó có thể được ghi vào đĩa hoặc được lưu trong bộ nhớ.


1
thưa ông ... tôi đã viết logic tương tự, nhưng một đường thẳng màu trắng sẽ được xuất hiện (chân dung) trên bên phải plz cho tôi giải pháp
Nag_iphone

1
Xin chào, làm cách nào để chúng tôi giải quyết việc giữ nguyên tỷ lệ khung hình và clip khi thay đổi kích thước? Trong trường hợp của tôi, khi tôi thay đổi kích thước một hình ảnh có khẩu phần khác sau đó "newsize", tôi nhận được một hình ảnh đã thay đổi kích thước bị biến dạng. Cảm ơn!
Van Du Tran

1
Điều này đã từng hoạt động trong quá khứ, nhưng trong iOS5.0.1 trở lên, điều này dẫn đến rò rỉ bộ nhớ. Bất kỳ cách nào khác để thực hiện điều này?
Usman Nisar

Khuyên bạn sử dụng [drawInRect ảnh: blendMode rect: kCGBlendModeCopy alpha: 1,0] để cải thiện hiệu suất (để vẽ không nhất thiết phải làm tính pha trộn trong bốc thăm
cdemiris99

Bạn nên sử dụng UIGraphicsBeginImageContextWithOptions (size, NO, 0.0); trong đó 0,0 sẽ sử dụng tỷ lệ màn hình chính để hỗ trợ võng mạc trở lên. Apple tuyên bố "Nói chung, bạn nên tránh gọi hàm UIGraphicsBeginImageContext có tên tương tự (ngoại trừ hàm dự phòng để tương thích ngược)".
Brad Goss

65

Cách dễ nhất và đơn giản nhất để thay đổi kích thước hình ảnh của bạn sẽ là

float actualHeight = image.size.height;
float actualWidth = image.size.width;
float imgRatio = actualWidth/actualHeight;
float maxRatio = 320.0/480.0;

if(imgRatio!=maxRatio){
    if(imgRatio < maxRatio){
        imgRatio = 480.0 / actualHeight;
        actualWidth = imgRatio * actualWidth;
        actualHeight = 480.0;
    }
    else{
        imgRatio = 320.0 / actualWidth;
        actualHeight = imgRatio * actualHeight;
        actualWidth = 320.0;
    }
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Điều này thật đẹp. Tôi đã có thể cắt giảm hình ảnh được gửi đến máy chủ từ khoảng 1Mb xuống 100k trong khi vẫn duy trì độ phân giải hiển thị võng mạc (mặc dù tôi đã thay đổi các giá trị 320.0 và 480.0 thành 640.0 và 1136.0) và cũng thực hiện một số nén JPEG sau khi chia tỷ lệ: UIImageJPEGRepresentation (img, 0,7f);
Keller

2
Điều gì sẽ xảy ra nếu tỷ lệ hình ảnh và tỷ lệ tối đa hóa ra bằng nhau? Ví dụ: nếu kích thước iamge là 3200x4800?
akshay1188

Điều này đã từng hoạt động trong quá khứ, nhưng trong iOS5.0.1 trở lên, điều này dẫn đến rò rỉ bộ nhớ. Bất kỳ cách nào khác để thực hiện điều này?
Usman Nisar

25

Các phương pháp trên hoạt động tốt đối với hình ảnh nhỏ, nhưng khi bạn cố gắng thay đổi kích thước của hình ảnh rất lớn, bạn sẽ nhanh chóng hết bộ nhớ và sập ứng dụng. Một cách tốt hơn nhiều là sử dụng CGImageSourceCreateThumbnailAtIndexđể thay đổi kích thước hình ảnh mà không cần giải mã hoàn toàn trước.

Nếu bạn có đường dẫn đến hình ảnh bạn muốn thay đổi kích thước, bạn có thể sử dụng điều này:

- (void)resizeImageAtPath:(NSString *)imagePath {
    // Create the image source (from path)
    CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);

    // To create image source from UIImage, use this
    // NSData* pngData =  UIImagePNGRepresentation(image);
    // CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);

    // Create thumbnail options
    CFDictionaryRef options = (__bridge CFDictionaryRef) @{
            (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
            (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
            (id) kCGImageSourceThumbnailMaxPixelSize : @(640)
    };
    // Generate the thumbnail
    CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options); 
    CFRelease(src);
    // Write the thumbnail at path
    CGImageWriteToFile(thumbnail, imagePath);
}

Thêm chi tiết tại đây .


Cảm ơn bạn, giải pháp này hoạt động giống như một sự quyến rũ), Bạn có biết các định dạng tệp khác hỗ trợ CGImageSourcengoài hình ảnh và pdf không?
sage444

Cảm ơn. Tôi đang tìm kiếm một thiết bị tương tự inSampleSizeđược sử dụng bởi bộ giải mã của Android. Và đây là câu trả lời duy nhất cung cấp cách thu nhỏ hình ảnh theo cách hiệu quả về bộ nhớ.
Stan Mots

Tôi đã có kết quả tuyệt vời khi làm việc trực tiếp với các tệp trong bộ nhớ, cũng hoạt động với hình ảnh trong bộ nhớ nhưng không nhanh bằng (để tải hình ảnh lớn thành UIImage sau đó chia tỷ lệ).
Kendall Helmstetter Gelner

Không hoạt động trong phần mở rộng chia sẻ. Ứng dụng vẫn gặp sự cố với hình ảnh rất lớn.
George

18

Cách tốt nhất để chia tỷ lệ hình ảnh mà không làm mất tỷ lệ khung hình (tức là không kéo dài ảnh) là sử dụng phương pháp này:

//to scale images without changing aspect ratio
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {

    float width = newSize.width;
    float height = newSize.height;

    UIGraphicsBeginImageContext(newSize);
    CGRect rect = CGRectMake(0, 0, width, height);

    float widthRatio = image.size.width / width;
    float heightRatio = image.size.height / height;
    float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

    width = image.size.width / divisor;
    height = image.size.height / divisor;

    rect.size.width  = width;
    rect.size.height = height;

    //indent in case of width or height difference
    float offset = (width - height) / 2;
    if (offset > 0) {
        rect.origin.y = offset;
    }
    else {
        rect.origin.x = -offset;
    }

    [image drawInRect: rect];

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return smallImage;

}

Thêm phương thức này vào lớp Tiện ích của bạn để bạn có thể sử dụng nó trong suốt dự án của mình và truy cập nó như sau:

xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];

Phương pháp này xử lý tỷ lệ trong khi duy trì tỷ lệ khung hình. Nó cũng thêm thụt lề vào hình ảnh trong trường hợp hình ảnh thu nhỏ có nhiều chiều rộng hơn chiều cao (hoặc ngược lại).


8

Nếu bạn có quyền kiểm soát máy chủ, tôi thực sự khuyên bạn nên thay đổi kích thước phía máy chủ hình ảnh bằng ImageMagik . Tải xuống các hình ảnh lớn và thay đổi kích thước chúng trên điện thoại sẽ gây lãng phí nhiều tài nguyên quý giá - băng thông, pin và bộ nhớ. Tất cả đều khan hiếm trên điện thoại.


2
FTFQ: "Ứng dụng của tôi đang tải xuống một tập hợp các tệp hình ảnh từ mạng"
Rog

Đây có thể là một câu trả lời có liên quan. Câu hỏi cho biết các hình ảnh đang được tải xuống từ mạng. Nếu OP có thể làm việc với phía máy chủ hình ảnh, anh ta nên làm như vậy. Nếu anh ấy không thể, câu trả lời sẽ giúp ích nhiều hơn.
Joshua Dance

6

Tôi đã phát triển một giải pháp tối ưu để mở rộng hình ảnh trong Swift.

Bạn có thể sử dụng nó để thay đổi kích thước hình ảnh để lấp đầy, lấp đầy khía cạnh hoặc kích thước phù hợp với kích thước được chỉ định.

Bạn có thể căn chỉnh hình ảnh ở giữa hoặc bất kỳ trong bốn cạnh và bốn góc.

Và bạn cũng có thể cắt bớt không gian thừa được thêm vào nếu tỷ lệ khung hình của hình ảnh gốc và kích thước mục tiêu không bằng nhau.

enum UIImageAlignment {
    case Center, Left, Top, Right, Bottom, TopLeft, BottomRight, BottomLeft, TopRight
}

enum UIImageScaleMode {
    case Fill,
    AspectFill,
    AspectFit(UIImageAlignment)
}

extension UIImage {
    func scaleImage(width width: CGFloat? = nil, height: CGFloat? = nil, scaleMode: UIImageScaleMode = .AspectFit(.Center), trim: Bool = false) -> UIImage {
        let preWidthScale = width.map { $0 / size.width }
        let preHeightScale = height.map { $0 / size.height }
        var widthScale = preWidthScale ?? preHeightScale ?? 1
        var heightScale = preHeightScale ?? widthScale
        switch scaleMode {
        case .AspectFit(_):
            let scale = min(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        case .AspectFill:
            let scale = max(widthScale, heightScale)
            widthScale = scale
            heightScale = scale
        default:
            break
        }
        let newWidth = size.width * widthScale
        let newHeight = size.height * heightScale
        let canvasWidth = trim ? newWidth : (width ?? newWidth)
        let canvasHeight = trim ? newHeight : (height ?? newHeight)
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(canvasWidth, canvasHeight), false, 0)

        var originX: CGFloat = 0
        var originY: CGFloat = 0
        switch scaleMode {
        case .AspectFit(let alignment):
            switch alignment {
            case .Center:
                originX = (canvasWidth - newWidth) / 2
                originY = (canvasHeight - newHeight) / 2
            case .Top:
                originX = (canvasWidth - newWidth) / 2
            case .Left:
                originY = (canvasHeight - newHeight) / 2
            case .Bottom:
                originX = (canvasWidth - newWidth) / 2
                originY = canvasHeight - newHeight
            case .Right:
                originX = canvasWidth - newWidth
                originY = (canvasHeight - newHeight) / 2
            case .TopLeft:
                break
            case .TopRight:
                originX = canvasWidth - newWidth
            case .BottomLeft:
                originY = canvasHeight - newHeight
            case .BottomRight:
                originX = canvasWidth - newWidth
                originY = canvasHeight - newHeight
            }
        default:
            break
        }
        self.drawInRect(CGRectMake(originX, originY, newWidth, newHeight))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}

Dưới đây là các ví dụ về việc áp dụng giải pháp này.

Hình chữ nhật màu xám là hình ảnh trang web mục tiêu sẽ được thay đổi kích thước thành. Hình tròn màu xanh lam trong hình chữ nhật màu xanh lam nhạt là hình ảnh (Tôi đã sử dụng hình tròn vì nó dễ nhìn thấy khi nó được thu nhỏ mà không bảo toàn khía cạnh). Màu cam nhạt đánh dấu các khu vực sẽ được cắt bớt nếu bạn vượt quatrim: true .

Kích thước phù hợp trước và sau khi thu nhỏ:

Kích thước phù hợp 1 (trước) Kích thước phù hợp 1 (sau)

Một ví dụ khác về phù hợp khía cạnh :

Kích thước phù hợp 2 (trước) Kích thước phù hợp 2 (sau)

Kích thước vừa vặn với căn chỉnh hàng đầu:

Kích thước phù hợp 3 (trước) Kích thước phù hợp 3 (sau)

Điền vào khía cạnh :

Điền vào khung (trước) Điền vào khung (sau)

Điền :

Điền (trước) Điền (sau)

Tôi đã sử dụng phương pháp nâng cấp trong các ví dụ của mình vì nó dễ chứng minh hơn nhưng giải pháp cũng hoạt động để giảm tỉ lệ như được đề cập.

Để nén JPEG, bạn nên sử dụng cái này:

let compressionQuality: CGFloat = 0.75 // adjust to change JPEG quality
if let data = UIImageJPEGRepresentation(image, compressionQuality) {
  // ...
}

Bạn có thể kiểm tra ý chính của tôi với sân chơi Xcode.


3

Đối với Swift 3, đoạn mã dưới đây chia tỷ lệ hình ảnh giữ nguyên tỷ lệ khung hình. Bạn có thể đọc thêm về ImageContext trong tài liệu của Apple :

extension UIImage {
    class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
        let scale = newHeight / image.size.height
        let newWidth = image.size.width * 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!
    }
}

Để sử dụng nó, hãy gọi resizeImage()phương thức:

UIImage.resizeImage(image: yourImageName, newHeight: yourImageNewHeight)

2

bạn có thể sử dụng mã này để chia tỷ lệ hình ảnh theo kích thước yêu cầu.

+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize
{
    CGSize actSize = image.size;
    float scale = actSize.width/actSize.height;

    if (scale < 1) {
        newSize.height = newSize.width/scale;
    } 
    else {
        newSize.width = newSize.height*scale;
    }

    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

1

Một vấn đề có thể xảy ra trên màn hình võng mạc là tỷ lệ hình ảnh được đặt bởi ImageCapture hoặc lâu hơn. Các chức năng thay đổi kích thước ở trên sẽ không thay đổi điều đó. Trong những trường hợp này, việc thay đổi kích thước sẽ không hoạt động bình thường.

Trong đoạn mã dưới đây, tỷ lệ được đặt thành 1 (không được chia tỷ lệ) và hình ảnh trả về có kích thước mà bạn mong đợi. Điều này được thực hiện trong UIGraphicsBeginImageContextWithOptionscuộc gọi.

-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
    UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
    [theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

1

Thêm vào một loạt câu trả lời ở đây, nhưng tôi đã tìm ra giải pháp thay đổi kích thước theo kích thước tệp, thay vì kích thước.

Điều này sẽ làm giảm cả kích thước và chất lượng của hình ảnh cho đến khi nó đạt đến kích thước nhất định của bạn.

func compressTo(toSizeInMB size: Double) -> UIImage? {
    let bytes = size * 1024 * 1024
    let sizeInBytes = Int(bytes)
    var needCompress:Bool = true
    var imgData:Data?
    var compressingValue:CGFloat = 1.0

    while (needCompress) {

        if let resizedImage = scaleImage(byMultiplicationFactorOf: compressingValue), let data: Data = UIImageJPEGRepresentation(resizedImage, compressingValue) {

            if data.count < sizeInBytes || compressingValue < 0.1 {
                needCompress = false
                imgData = data
            } else {
                compressingValue -= 0.1
            }
        }
    }

    if let data = imgData {
        print("Finished with compression value of: \(compressingValue)")
        return UIImage(data: data)
    }
    return nil
}

private func scaleImage(byMultiplicationFactorOf factor: CGFloat) -> UIImage? {
    let size = CGSize(width: self.size.width*factor, height: self.size.height*factor)
    UIGraphicsBeginImageContext(size)
    draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    if let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()
        return newImage;
    }
    return nil
}

Tín dụng cho câu trả lời mở rộng theo kích thước


1

Phiên bản Swift

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

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

    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}

1

Theo phiên này, iOS Memory Deep Dive , chúng tôi đã sử dụng tốt hơn ImageIOđể giảm tỷ lệ hình ảnh.

Tệ hại của việc sử dụng UIImagehình ảnh giảm tỷ lệ.

  • Sẽ giải nén ảnh gốc vào bộ nhớ
  • Các phép biến đổi không gian tọa độ bên trong rất tốn kém

Sử dụng ImageIO

  • ImageIO có thể đọc kích thước hình ảnh và thông tin siêu dữ liệu mà không làm bẩn bộ nhớ.

  • ImageIO chỉ có thể thay đổi kích thước hình ảnh với chi phí thay đổi kích thước hình ảnh.

Giới thiệu về Hình ảnh trong bộ nhớ

  • Việc sử dụng bộ nhớ liên quan đến kích thước của hình ảnh, không phải kích thước tệp.
  • UIGraphicsBeginImageContextWithOptionsluôn sử dụng SRGBđịnh dạng kết xuất, sử dụng 4 byte trên mỗi pixel.
  • Một hình ảnh có load -> decode -> render3 pha.
  • UIImage tốn kém cho việc định cỡ và thay đổi kích thước

Đối với hình ảnh sau, nếu bạn sử dụng, UIGraphicsBeginImageContextWithOptions chúng tôi chỉ cần 590KB để tải một hình ảnh, trong khi chúng tôi cần 2048 pixels x 1536 pixels x 4 bytes per pixel= 10MB khi giải mã nhập mô tả hình ảnh ở đây

trong khi UIGraphicsImageRenderer, được giới thiệu trong iOS 10, sẽ tự động chọn định dạng đồ họa tốt nhất trong iOS12. Có nghĩa là, bạn có thể tiết kiệm 75% bộ nhớ bằng cách thay thế UIGraphicsBeginImageContextWithOptionsbằngUIGraphicsImageRenderer nếu bạn không cần SRGB.

Đây là bài viết của tôi về hình ảnh iOS trong bộ nhớ

func resize(url: NSURL, maxPixelSize: Int) -> CGImage? {
    let imgSource = CGImageSourceCreateWithURL(url, nil)
    guard let imageSource = imgSource else {
        return nil
    }

    var scaledImage: CGImage?
    let options: [NSString: Any] = [
            // The maximum width and height in pixels of a thumbnail.
            kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
            kCGImageSourceCreateThumbnailWithTransform: true
    ]
    scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)

    return scaledImage
}


let filePath = Bundle.main.path(forResource:"large_leaves_70mp", ofType: "jpg")

let url = NSURL(fileURLWithPath: filePath ?? "")

let image = resize(url: url, maxPixelSize: 600)

hoặc là

// Downsampling large images for display at smaller size
func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions =
        [kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceShouldCacheImmediately: true,
        // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
    let downsampledImage =
        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
    return UIImage(cgImage: downsampledImage)
}

0

Tôi đã sử dụng kỹ thuật Brads để tạo ra một scaleToFitWidthphương pháp UIImage+Extensionsnếu điều đó hữu ích cho bất kỳ ai ...

-(UIImage *)scaleToFitWidth:(CGFloat)width
{
    CGFloat ratio = width / self.size.width;
    CGFloat height = self.size.height * ratio;

    NSLog(@"W:%f H:%f",width,height);

    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    [self drawInRect:CGRectMake(0.0f,0.0f,width,height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}

sau đó bất cứ nơi nào bạn thích

#import "UIImage+Extensions.h"

UIImage *newImage = [image scaleToFitWidth:100.0f];

Cũng cần lưu ý rằng bạn có thể di chuyển điều này xuống sâu hơn vào một UIView+Extensionslớp nếu bạn muốn hiển thị hình ảnh từ UIView


0

Tôi chỉ muốn trả lời câu hỏi đó cho các lập trình viên Cocoa Swift. Hàm này trả về NSImage với kích thước mới. Bạn có thể sử dụng chức năng đó như thế này.

        let sizeChangedImage = changeImageSize(image, ratio: 2)






 // changes image size

    func changeImageSize (image: NSImage, ratio: CGFloat) -> NSImage   {

    // getting the current image size
    let w = image.size.width
    let h = image.size.height

    // calculating new size
    let w_new = w / ratio 
    let h_new = h / ratio 

    // creating size constant
    let newSize = CGSizeMake(w_new ,h_new)

    //creating rect
    let rect  = NSMakeRect(0, 0, w_new, h_new)

    // creating a image context with new size
    let newImage = NSImage.init(size:newSize)



    newImage.lockFocus()

        // drawing image with new size in context
        image.drawInRect(rect)

    newImage.unlockFocus()


    return newImage

}

0

Nếu hình ảnh của bạn nằm trong thư mục tài liệu, hãy thêm phần mở rộng URL này :

extension URL {
    func compressedImageURL(quality: CGFloat = 0.3) throws -> URL? {
        let imageData = try Data(contentsOf: self)
        debugPrint("Image file size before compression: \(imageData.count) bytes")

        let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".jpg")

        guard let actualImage = UIImage(data: imageData) else { return nil }
        guard let compressedImageData = UIImageJPEGRepresentation(actualImage, quality) else {
            return nil
        }
        debugPrint("Image file size after compression: \(compressedImageData.count) bytes")

        do {
            try compressedImageData.write(to: compressedURL)
            return compressedURL
        } catch {
            return nil
        }
    }
}

Sử dụng:

guard let localImageURL = URL(string: "< LocalImagePath.jpg >") else {
    return
}

//Here you will get URL of compressed image
guard let compressedImageURL = try localImageURL.compressedImageURL() else {
    return
}

debugPrint("compressedImageURL: \(compressedImageURL.absoluteString)")

Lưu ý: - Thay đổi <LocalImagePath.jpg> bằng đường dẫn hình ảnh jpg cục bộ của bạn.


-1

Nếu ai đó vẫn đang tìm kiếm lựa chọn tốt hơn

-(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {


    UIImage *sourceImage = image;
    UIImage *newImage = nil;

    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;

    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;

    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor)
            scaleFactor = widthFactor;
        else
            scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image


        if (widthFactor < heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
        } else if (widthFactor > heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }


    // this is actually the interesting part:

    UIGraphicsBeginImageContext(targetSize);

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if(newImage == nil) NSLog(@"could not scale image");


    return newImage ;

}

-1
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = image.CGImage;

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();

    return newImage;
}

Vui lòng cung cấp ít nhất một số giải thích về mã trong câu trả lời của bạn. Và cũng định dạng mã bằng trình chỉnh sửa câu trả lời để làm cho nó có thể đọc được.
xpereta

-2

Để thay đổi kích thước hình ảnh, tôi có kết quả (đồ họa) tốt hơn bằng cách sử dụng chức năng này thay cho DrawInRect:

- (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth
{
    float lScale = pWidth / pImage.size.width;
    CGImageRef cgImage = pImage.CGImage;
    UIImage   *lResult = [UIImage imageWithCGImage:cgImage scale:lScale
                            orientation:UIImageOrientationRight];
    return lResult;
}

Tỷ lệ co được tự động xử lý

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.