Programing

업로드 이미지 크기를 줄이기 위해 UIImage의 크기를 조정하는 방법

lottogame 2020. 11. 19. 07:48
반응형

업로드 이미지 크기를 줄이기 위해 UIImage의 크기를 조정하는 방법


나는 Google을 검색해 왔으며 높이 / 너비를 줄이거 나 CoreImage를 통해 UIImage 모양을 편집하는 방법 중 일부만 발견했습니다. 그러나 나는 이미지 크기를 줄이는 방법을 설명하는 하나의 라이브러리를 보거나 찾지 못 했으므로 업로드 할 때 전체 이미지 크기가 아닙니다.

지금까지 나는 이것을 가지고있다 :

        if image != nil {
        //let data = NSData(data: UIImagePNGRepresentation(image))
        let data = UIImagePNGRepresentation(image)
        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"image\"; filename=\"randomName\"\r\n")
        body.appendString("Content-Type: image/png\r\n\r\n")
        body.appendData(data)
        body.appendString("\r\n")
    }

12MB 사진을 보내고 있습니다. 이것을 1MB로 어떻게 줄일 수 있습니까? 감사!


Xcode 9 • Swift 4 이상

편집 / 업데이트 : iOS10 +의 경우 UIGraphicsImageRenderer 를 사용할 수 있습니다 . 이전 Swift 구문의 경우 편집 기록을 확인하십시오.

extension UIImage {
    func resized(withPercentage percentage: CGFloat) -> UIImage? {
        let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
        return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))  
        }
    }
    func resized(toWidth width: CGFloat) -> UIImage? {
        let canvas = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
        return UIGraphicsImageRenderer(size: canvas, format: imageRendererFormat).image {
            _ in draw(in: CGRect(origin: .zero, size: canvas))
        }
    }
}

용법:

let image = UIImage(data: try! Data(contentsOf: URL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!))!

let thumb1 = image.resized(withPercentage: 0.1)
let thumb2 = image.resized(toWidth: 72.0)

이것이 내가 이미지 크기를 조정하는 방법입니다.

 -(UIImage *)resizeImage:(UIImage *)image
{
   float actualHeight = image.size.height;
   float actualWidth = image.size.width;
   float maxHeight = 300.0;
   float maxWidth = 400.0;
   float imgRatio = actualWidth/actualHeight;
   float maxRatio = maxWidth/maxHeight;
   float compressionQuality = 0.5;//50 percent compression

   if (actualHeight > maxHeight || actualWidth > maxWidth)
   {
    if(imgRatio < maxRatio)
    {
        //adjust width according to maxHeight
        imgRatio = maxHeight / actualHeight;
        actualWidth = imgRatio * actualWidth;
        actualHeight = maxHeight;
    }
    else if(imgRatio > maxRatio)
    {
        //adjust height according to maxWidth
        imgRatio = maxWidth / actualWidth;
        actualHeight = imgRatio * actualHeight;
        actualWidth = maxWidth;
    }
    else
    {
        actualHeight = maxHeight;
        actualWidth = maxWidth;
    }
   }

   CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
   UIGraphicsBeginImageContext(rect.size);
   [image drawInRect:rect];
   UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
   NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality);
   UIGraphicsEndImageContext();

   return [UIImage imageWithData:imageData];

}

이 방법을 사용하면 6.5MB의 이미지가 104KB로 줄어 듭니다.

Swift 4 코드 :

func resize(_ image: UIImage) -> UIImage {
    var actualHeight = Float(image.size.height)
    var actualWidth = Float(image.size.width)
    let maxHeight: Float = 300.0
    let maxWidth: Float = 400.0
    var imgRatio: Float = actualWidth / actualHeight
    let maxRatio: Float = maxWidth / maxHeight
    let compressionQuality: Float = 0.5
    //50 percent compression
    if actualHeight > maxHeight || actualWidth > maxWidth {
        if imgRatio < maxRatio {
            //adjust width according to maxHeight
            imgRatio = maxHeight / actualHeight
            actualWidth = imgRatio * actualWidth
            actualHeight = maxHeight
        }
        else if imgRatio > maxRatio {
            //adjust height according to maxWidth
            imgRatio = maxWidth / actualWidth
            actualHeight = imgRatio * actualHeight
            actualWidth = maxWidth
        }
        else {
            actualHeight = maxHeight
            actualWidth = maxWidth
        }
    }
    let rect = CGRect(x: 0.0, y: 0.0, width: CGFloat(actualWidth), height: CGFloat(actualHeight))
    UIGraphicsBeginImageContext(rect.size)
    image.draw(in: rect)
    let img = UIGraphicsGetImageFromCurrentImageContext()
    let imageData = img?.jpegData(compressionQuality: CGFloat(compressionQuality)) 
    UIGraphicsEndImageContext()
    return UIImage(data: imageData!) ?? UIImage()
}

누군가 Swift 3 및 4를 사용 하여 이미지 크기1MB 미만으로 조정 하려는 경우 .

이 확장을 복사하여 붙여 넣기 만하면됩니다 .

extension UIImage {

func resized(withPercentage percentage: CGFloat) -> UIImage? {
    let canvasSize = CGSize(width: size.width * percentage, height: size.height * percentage)
    UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale)
    defer { UIGraphicsEndImageContext() }
    draw(in: CGRect(origin: .zero, size: canvasSize))
    return UIGraphicsGetImageFromCurrentImageContext()
}

func resizedTo1MB() -> UIImage? {
    guard let imageData = UIImagePNGRepresentation(self) else { return nil }

    var resizingImage = self
    var imageSizeKB = Double(imageData.count) / 1000.0 // ! Or devide for 1024 if you need KB but not kB

    while imageSizeKB > 1000 { // ! Or use 1024 if you need KB but not kB
        guard let resizedImage = resizingImage.resized(withPercentage: 0.9),
            let imageData = UIImagePNGRepresentation(resizedImage)
            else { return nil }

        resizingImage = resizedImage
        imageSizeKB = Double(imageData.count) / 1000.0 // ! Or devide for 1024 if you need KB but not kB
    }

    return resizingImage
}
}

그리고 사용 :

let resizedImage = originalImage.resizedTo1MB()

편집 : 그것의주의 UI를 차단 하므로 이동, 백그라운드 스레드 당신이 당신의 사건에 대한 올바른 방법이라고 생각합니다.


Leo Answer와 동일하지만 SWIFT 2.0에 대한 약간의 편집

 extension UIImage {
    func resizeWithPercentage(percentage: CGFloat) -> UIImage? {
        let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: size.width * percentage, height: size.height * percentage)))
        imageView.contentMode = .ScaleAspectFit
        imageView.image = self
        UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        imageView.layer.renderInContext(context)
        guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
        UIGraphicsEndImageContext()
        return result
    }

    func resizeWithWidth(width: CGFloat) -> UIImage? {
        let imageView = UIImageView(frame: CGRect(origin: .zero, size: CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))))
        imageView.contentMode = .ScaleAspectFit
        imageView.image = self
        UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, false, scale)
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        imageView.layer.renderInContext(context)
        guard let result = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
        UIGraphicsEndImageContext()
        return result
    }
}

다음은 user4261201의 답변이지만 현재 사용하고 있습니다.

func compressImage (_ image: UIImage) -> UIImage {

    let actualHeight:CGFloat = image.size.height
    let actualWidth:CGFloat = image.size.width
    let imgRatio:CGFloat = actualWidth/actualHeight
    let maxWidth:CGFloat = 1024.0
    let resizedHeight:CGFloat = maxWidth/imgRatio
    let compressionQuality:CGFloat = 0.5

    let rect:CGRect = CGRect(x: 0, y: 0, width: maxWidth, height: resizedHeight)
    UIGraphicsBeginImageContext(rect.size)
    image.draw(in: rect)
    let img: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    let imageData:Data = UIImageJPEGRepresentation(img, compressionQuality)!
    UIGraphicsEndImageContext()

    return UIImage(data: imageData)!

}

Swift4.2

  let imagedata = yourImage.jpegData(compressionQuality: 0.1)!

NSData형식으로 이미지를 업로드하는 경우 다음을 사용하십시오.

NSData *imageData = UIImageJPEGRepresentation(yourImage, floatValue);

yourImage귀하의 UIImage. floatvalue압축 값 (0.0 ~ 1.0)

위는 이미지를 JPEG.

에 대한 PNG사용 :UIImagePNGRepresentation

참고 : 위 코드는 Objective-C에 있습니다. Swift에서 NSData를 정의하는 방법을 확인하십시오.


이것이 내가 UIImage의 크기를 조정하기 위해 swift 3에서 한 일입니다. 이미지 크기를 100kb 미만으로 줄입니다. 비례 적으로 작동합니다!

extension UIImage {
    class func scaleImageWithDivisor(img: UIImage, divisor: CGFloat) -> UIImage {
        let size = CGSize(width: img.size.width/divisor, height: img.size.height/divisor)
        UIGraphicsBeginImageContext(size)
        img.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return scaledImage!
    }
}

용법:

let scaledImage = UIImage.scaleImageWithDivisor(img: capturedImage!, divisor: 3)

Tung Fam의 답변을 기반으로합니다. 특정 파일 크기로 크기를 조정합니다. 0.7MB처럼이 코드를 사용할 수 있습니다.

extension UIImage {

func resize(withPercentage percentage: CGFloat) -> UIImage? {
    var newRect = CGRect(origin: .zero, size: CGSize(width: size.width*percentage, height: size.height*percentage))
    UIGraphicsBeginImageContextWithOptions(newRect.size, true, 1)
    self.draw(in: newRect)
    defer {UIGraphicsEndImageContext()}
    return UIGraphicsGetImageFromCurrentImageContext()
}

func resizeTo(MB: Double) -> UIImage? {
    guard let fileSize = self.pngData()?.count else {return nil}
    let fileSizeInMB = CGFloat(fileSize)/(1024.0*1024.0)//form bytes to MB
    let percentage = 1/fileSizeInMB
    return resize(withPercentage: percentage)
}
}

이를 사용하여 원하는 크기를 제어 할 수 있습니다.

func jpegImage(image: UIImage, maxSize: Int, minSize: Int, times: Int) -> Data? {
    var maxQuality: CGFloat = 1.0
    var minQuality: CGFloat = 0.0
    var bestData: Data?
    for _ in 1...times {
        let thisQuality = (maxQuality + minQuality) / 2
        guard let data = image.jpegData(compressionQuality: thisQuality) else { return nil }
        let thisSize = data.count
        if thisSize > maxSize {
            maxQuality = thisQuality
        } else {
            minQuality = thisQuality
            bestData = data
            if thisSize > minSize {
                return bestData
            }
        }
    }
    return bestData
}

메서드 호출 예 :

jpegImage(image: image, maxSize: 500000, minSize: 400000, times: 10)  

maxSize와 minSize의 최대 크기와 최소 크기 사이의 파일을 얻으려고 시도하지만 시도 횟수 만 시도합니다. 그 시간 내에 실패하면 nil을 반환합니다.


이미지를 아래의 압축 데이터로 압축하는 가장 쉬운 방법은 swift 4.2의 코드입니다.

let imageData = yourImageTobeCompressed.jpegData(compressionQuality: 0.5)

이 imageData를 서버에 업로드 할 수 있습니다.


Objective-C에서 동일 :

상호 작용 :

@interface UIImage (Resize)

- (UIImage *)resizedWithPercentage:(CGFloat)percentage;
- (UIImage *)resizeTo:(CGFloat)weight isPng:(BOOL)isPng jpegCompressionQuality:(CGFloat)compressionQuality;

@end

구현 :

#import "UIImage+Resize.h"

@implementation UIImage (Resize)

- (UIImage *)resizedWithPercentage:(CGFloat)percentage {
    CGSize canvasSize = CGSizeMake(self.size.width * percentage, self.size.height * percentage);
    UIGraphicsBeginImageContextWithOptions(canvasSize, false, self.scale);
    [self drawInRect:CGRectMake(0, 0, canvasSize.width, canvasSize.height)];
    UIImage *sizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return sizedImage;
}

- (UIImage *)resizeTo:(CGFloat)weight isPng:(BOOL)isPng jpegCompressionQuality:(CGFloat)compressionQuality {
    NSData *imageData = isPng ? UIImagePNGRepresentation(self) : UIImageJPEGRepresentation(self, compressionQuality);
    if (imageData && [imageData length] > 0) {
        UIImage *resizingImage = self;
        double imageSizeKB = [imageData length] / weight;

        while (imageSizeKB > weight) {
            UIImage *resizedImage = [resizingImage resizedWithPercentage:0.9];
            imageData = isPng ? UIImagePNGRepresentation(resizedImage) : UIImageJPEGRepresentation(resizedImage, compressionQuality);
            resizingImage = resizedImage;
            imageSizeKB = (double)(imageData.length / weight);
        }

        return resizingImage;
    }
    return nil;
}

사용법 :

#import "UIImage+Resize.h"

UIImage *resizedImage = [self.picture resizeTo:2048 isPng:NO jpegCompressionQuality:1.0];

When I try to use the accepted answer to resize an image for use in my project it comes out very pixelated and blurry. I ended up with this piece of code to resize images without adding pixelation or blur:

func scale(withPercentage percentage: CGFloat)-> UIImage? {
        let cgSize = CGSize(width: size.width * percentage, height: size.height * percentage)

        let hasAlpha = true
        let scale: CGFloat = 0.0 // Use scale factor of main screen

        UIGraphicsBeginImageContextWithOptions(cgSize, !hasAlpha, scale)
        self.draw(in: CGRect(origin: CGPoint.zero, size: cgSize))

        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        return scaledImage
    }

extension UIImage {
func resized(toValue value: CGFloat) -> UIImage {
    if size.width > size.height {
        return self.resize(toWidth: value)!
    } else {
        return self.resize(toHeight: value)!
    }
}

Resize the UIImage using .resizeToMaximumBytes

참고URL : https://stackoverflow.com/questions/29137488/how-do-i-resize-the-uiimage-to-reduce-upload-image-size

반응형