UIImage의 크기를 조정하는 가장 간단한 방법은 무엇입니까?


397

iPhone 앱에서 카메라로 사진을 찍은 다음 290 * 390 픽셀로 크기를 조정하고 싶습니다. 이 방법을 사용하여 이미지 크기를 조정했습니다.

UIImage *newImage = [image _imageScaledToSize:CGSizeMake(290, 390)
                         interpolationQuality:1];    

완벽하게 작동하지만 문서화되지 않은 기능이므로 iPhone OS4에서 더 이상 사용할 수 없습니다.

그렇다면 ... UIImage의 크기를 조정하는 가장 간단한 방법은 무엇입니까?


2019 년에하는 방법, nshipster.com/image-resizing
dengST30

답변:


772

가장 간단한 방법은 프레임을 UIImageView설정 contentMode하고 크기 조정 옵션 중 하나로 설정하는 것입니다.

또는 실제로 이미지 크기를 조정해야하는 경우이 유틸리티 방법을 사용할 수 있습니다.

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    //UIGraphicsBeginImageContext(newSize);
    // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
    // Pass 1.0 to force exact pixel size.
    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}

사용법 예 :

#import "MYUtil.h"

UIImage *myIcon = [MYUtil imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)];

11
나는 여기에 결과를 유지하지 않을 것입니다. newImage이미 자동 릴리스되며이를 유지하기 위해 이것을 호출 한 메소드에 따라야합니다. 이 접근법은 init메소드 이름의 일부가 아니기 때문에 메모리 버그 를 요구하고 있습니다. 이와 같은 이름의 메소드가 자동 해제 된 객체를 반환 할 것으로 예상합니다.
Alex Wayne

유효하고 편집했습니다. 이 코드를 사용하는 코드가 추가 유지없이 다른 곳에서 malloc 오류를 생성한다는 점에주의를 기울일 것입니다. 어쨌든 내 잘못입니다 :-).
Paul Lynch

26
iOS 4.0 부터 UIGraphics * 기능은 모두 스레드로부터 안전합니다.
BJ 호머

3
@Paul Lynch :이 변경으로 인해 원래 게시물의 사명이 깨짐을 명심하십시오. 이미지를 정확한 픽셀 크기 로 조정하는 방법 ( 포인트 크기가 아닌 ).
Nikolai Ruhe

8
로 호출 1.0 대신 0.0을 전달하여 제한 @NikolaiRuhe 지적에, 당신이 정확한 픽셀 크기로 강제로 인해 어려움을 겪고 사람들을 위해UIGraphicsBeginImageContextWithOptions
대니

84

다음은 Paul Lynch의 Swift 버전 답변입니다.

func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

그리고 확장으로 :

public extension UIImage {
    func copy(newSize: CGSize, retina: Bool = true) -> UIImage? {
        // In next line, pass 0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
        // Pass 1 to force exact pixel size.
        UIGraphicsBeginImageContextWithOptions(
            /* size: */ newSize,
            /* opaque: */ false,
            /* scale: */ retina ? 0 : 1
        )
        defer { UIGraphicsEndImageContext() }

        self.draw(in: CGRect(origin: .zero, size: newSize))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

2
단지 아이폰 OS에서, 2 배, 3 배하여 newSize와 의지의 여러 장치를 기반으로, 주목
Sruit A.Suk에게

6
UIGraphicsBeginImageContextWithOptions (newSize, false, image.scale); 모든 기기
phnmnn

이것은 기본 CGImage의 크기를 조정하지 않습니다 (적어도 iOS 12.1에서는). 질문에 따라 괜찮지 만 이미지를 작성하는 경우 cgImage를 사용해야하고 원본 이미지를 얻습니다.
prewett

72

적절한 스위프트 3.0 에 대한 아이폰 OS 10 + 솔루션 : 사용 ImageRenderer및 폐쇄 구문 :

func imageWith(newSize: CGSize) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: newSize)
    let image = renderer.image { _ in
        self.draw(in: CGRect.init(origin: CGPoint.zero, size: newSize))
    }

    return image.withRenderingMode(self.renderingMode)
}

Objective-C 버전은 다음과 같습니다.

@implementation UIImage (ResizeCategory)
- (UIImage *)imageWithSize:(CGSize)newSize
{
    UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newSize];
    UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext*_Nonnull myContext) {
        [self drawInRect:(CGRect) {.origin = CGPointZero, .size = newSize}];
    }];
    return [image imageWithRenderingMode:self.renderingMode];
}
@end

1
매우 우아한 해결책, 이것은 받아 들여지는 대답이어야합니다!
appsunited

2
이것은 우아한 것보다 낫습니다. 맞습니다. Apple의 API 문서는이 코드와 마찬가지로 UIGraphicsRenderer를 사용하도록 새 코드를 권장합니다. 감사합니다
Paul Bruneau

1
@appsunited이 질문은 거의 8 살입니다. 그리고이 방법 은 명시된 바와 같이 iOS10 이상 에서만 작동합니다 .

새 이미지 객체를 클립 보드에 복사하면 흰색 블록이 만들어집니다. 실제로 이미지 뷰의 크기를 조정하지 않습니까?
Oliver Dixon

1
이 함수는 높이 0과 너비 0의 이미지를 반환합니다. 높이는 9000 높이와 9000 너비입니다.
krishan kumar

31

Trevor Howard에는 크기 조정을 매우 잘 처리 하는 UIImage 범주 가 있습니다. 다른 것이 없다면 코드를 예제로 사용할 수 있습니다.

참고 : iOS 5.1부터이 답변은 유효하지 않을 수 있습니다. 아래의 의견을 참조하십시오.


2
일부 이미지의 크기도 조정해야했고, 먼저 UIImage에 Trevor의 추가 기능을 시도했지만 PNG (알파 채널에 관한 것)에 이상한 버그가 생겼습니다. 이 질문에 대한 대답은 훌륭하게 해결되었습니다.
Sorig

1
이것은 더 이상 유효하지 않습니다 (최소한 iOS5.1
Jann

@Jann, 게시물 아래의 커밋을 살펴보십시오.
vikingosegundo

@Jann 댓글에 제안 된 수정 사항을 따르면 "Matt는 2011 년 11 월 22 일 오후 5시 39 분"으로 이동합니다 (horseshoe7의 유사한 솔루션과 달리).
벤 플린

1
@sanmai는 이러한 크기 조정 방법 중 하나를 사용하여 이미지의 선명도를 잃어 버렸습니다. 선명도를 달성 할 수있는 방법이
있습니까

31

Swift 4 및 iOS 10+를위한보다 컴팩트 한 버전 :

extension UIImage {
    func resized(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

용법:

let resizedImage = image.resized(to: CGSize(width: 50, height: 50))

26

또한이 작업을 수행 한 것을 보았습니다 ( UIButtons버튼이 작동하지 않기 때문에 일반 및 선택 상태 에 사용합니다)resize 맞지 ). 크레디트는 원저자에게 갔다.

먼저 빈 .h 및 .m 파일 UIImageResizing.hUIImageResizing.m

// Put this in UIImageResizing.h
@interface UIImage (Resize)
- (UIImage*)scaleToSize:(CGSize)size;
@end

// Put this in UIImageResizing.m
@implementation UIImage (Resize)

- (UIImage*)scaleToSize:(CGSize)size {
UIGraphicsBeginImageContext(size);

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0.0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);

UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return scaledImage;
}

@end

이 .h 파일을 함수를 사용할 .m 파일에 포함시키고 다음과 같이 호출하십시오.

UIImage* image = [UIImage imageNamed:@"largeImage.png"];
UIImage* smallImage = [image scaleToSize:CGSizeMake(100.0f,100.0f)];

이미지 방향으로 복사하지 않습니다.
Kevin

20

Paul의 코드 개선으로 인해 레티 나 디스플레이가 장착 된 iPhone에서 선명한 고해상도 이미지를 얻을 수 있습니다. 그렇지 않으면 축소 할 때 흐릿합니다.

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    if ([[UIScreen mainScreen] scale] == 2.0) {
        UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);
    } else {
        UIGraphicsBeginImageContext(newSize);
    }
} else {
    UIGraphicsBeginImageContext(newSize);
}
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
UIGraphicsEndImageContext();
return newImage;
}

13
참고로, 스케일 인에 0.0 값을 제공 UIGraphicsBeginImageContextWithOptions하면 자동으로 주 화면의 스케일 (iOS 3.2 기준)이 사용 되므로 변경 사항이 필요하지 않습니다.
Andrew R.

16

간단한 방법은 다음과 같습니다.

    UIImage * image = [UIImage imageNamed:@"image"];
    CGSize sacleSize = CGSizeMake(10, 10);
    UIGraphicsBeginImageContextWithOptions(sacleSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, sacleSize.width, sacleSize.height)];
    UIImage * resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

resizedImage 는 새로운 이미지입니다.


16

스트레치 채우기, 가로 세로 채우기 및 가로 세로 맞춤을위한 신속한 솔루션

extension UIImage {
    enum ContentMode {
        case contentFill
        case contentAspectFill
        case contentAspectFit
    }

    func resize(withSize size: CGSize, contentMode: ContentMode = .contentAspectFill) -> UIImage? {
        let aspectWidth = size.width / self.size.width
        let aspectHeight = size.height / self.size.height

        switch contentMode {
        case .contentFill:
            return resize(withSize: size)
        case .contentAspectFit:
            let aspectRatio = min(aspectWidth, aspectHeight)
            return resize(withSize: CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio))
        case .contentAspectFill:
            let aspectRatio = max(aspectWidth, aspectHeight)
            return resize(withSize: CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio))
        }
    }

    private func resize(withSize size: CGSize) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, self.scale)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

사용하려면 다음을 수행하십시오.

let image = UIImage(named: "image.png")!
let newImage = image.resize(withSize: CGSize(width: 200, height: 150), contentMode: .contentAspectFill)

독창적 인 솔루션 abdullahselek에게 감사드립니다.


15

위의 iWasRobbed가 작성한 카테고리의 수정 사항은 다음과 같습니다. 원본 이미지의 화면비가 왜곡되지 않고 유지됩니다.

- (UIImage*)scaleToSizeKeepAspect:(CGSize)size {
    UIGraphicsBeginImageContext(size);

    CGFloat ws = size.width/self.size.width;
    CGFloat hs = size.height/self.size.height;

    if (ws > hs) {
        ws = hs/ws;
        hs = 1.0;
    } else {
        hs = ws/hs;
        ws = 1.0;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0.0, size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextDrawImage(context, CGRectMake(size.width/2-(size.width*ws)/2,
        size.height/2-(size.height*hs)/2, size.width*ws,
        size.height*hs), self.CGImage);

    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return scaledImage;
}

11

이미지를 더 작게 만들고 정확한 크기를 신경 쓰지 않으면 :

+ (UIImage *)imageWithImage:(UIImage *)image scaledToScale:(CGFloat)scale
{
    UIGraphicsBeginImageContextWithOptions(self.size, YES, scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

배율을 설정 0.25f하면 8MP 카메라의 816 x 612 이미지가 제공됩니다.

다음은 UIImage + Scale 범주 가 필요한 사람들을위한 것입니다.


10

왜 그렇게 복잡한가? 시스템 API를 사용하면 동일한 결과를 얻을 수 있다고 생각합니다.

UIImage *largeImage;
CGFloat ratio = 0.4; // you want to get a new image that is 40% the size of large image.
UIImage *newImage = [UIImage imageWithCGImage:largeImage.CGImage
                                        scale:1/ratio
                                  orientation:largeImage.imageOrientation];
// notice the second argument, it is 1/ratio, not ratio.

문서에 따르면 두 번째 매개 변수는 새로운 스케일링 된 이미지와 비교하여 원본 이미지의 비율을 지정하므로 대상 비율의 역수를 두 번째 인수로 전달해야합니다.


scale (%)은 픽셀 (w / h)과 같지 않기 때문입니다.

스케일은 1 / 비가 아닌 largeImage.scale / ratio 여야합니다.
Marián Černý

9

Swift 3Swift 4 와 호환되는 UIImage 확장 으로 가로 세로 비율로 지정된 크기로 이미지 크기를 조정합니다.

extension UIImage {

    func scaledImage(withSize size: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
        return UIGraphicsGetImageFromCurrentImageContext()!
    }

    func scaleImageToFitSize(size: CGSize) -> UIImage {
        let aspect = self.size.width / self.size.height
        if size.width / aspect <= size.height {
            return scaledImage(withSize: CGSize(width: size.width, height: size.width / aspect))
        } else {
            return scaledImage(withSize: CGSize(width: size.height * aspect, height: size.height))
        }
    }

}

사용법 예

let image = UIImage(named: "apple")
let scaledImage = image.scaleImageToFitSize(size: CGSize(width: 45.0, height: 45.0))

나는 함수의 이름을 추천 할 것입니다 scaledImage(with size:)또는 scaledWithSize(_:). 또한 UIGraphicsGetImageFromCurrentImageContext정말 반환 할 수 nil있으므로, !잘 작동. rect 생성을로 단순화 할 수도 있습니다 CGRect(origin: .zero, size: size).
Sulthan

8

동일한 트릭을 수행하는 Apple의 예제에서 UIImage 카테고리를 찾았습니다. 다음 링크는 다음과 같습니다 https://developer.apple.com/library/ios/samplecode/sc2273/Listings/AirDropSample_UIImage_Resize_m.html .

통화를 변경해야합니다.

UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);

에서 imageWithImage:scaledToSize:inRect:와 :

UIGraphicsBeginImageContextWithOptions(newSize, NO, 2.0);

이미지의 알파 채널을 고려하기 위해.


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

코드와 함께 설명 텍스트를 추가하는 것이 좋습니다.
GMchris

6

내 동료 Xamarians를 들어, 다음입니다 Xamarin.iOS @ 폴 린치 응답의 C # 버전.

private UIImage ResizeImage(UIImage image, CGSize newSize) 
{
    UIGraphics.BeginImageContextWithOptions(newSize, false, 0.0f);
    image.Draw(new CGRect(0, 0, newSize.Width, newSize.Height));
    UIImage newImage = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return newImage;
}

5

비례 크기 조정 또는 일부 자르기와 관련된 UIImage의 축소판을 만들려면 간결한 ImageMagick과 같은 구문을 사용할 수있는 UIImage + Resize 범주를 확인하십시오 .

UIImage* squareImage       = [image resizedImageByMagick: @"320x320#"];

5

[크리스 CF] 크기를 조정하려면 원하는 크기 :

UIImage *after = [UIImage imageWithCGImage:before.CGImage
                                     scale:CGImageGetHeight(before.CGImage)/DESIREDHEIGHT
                               orientation:UIImageOrientationUp];

또는 동등하게 대체 CGImageGetWidth(...)/DESIREDWIDTH


이미지 데이터 자체는 크기가 조정되지 않지만 스케일 팩터가 적용되므로 이미지의 메모리 크기가 동일합니다.
inkredibl

5

Rogerio Chaves 는 신속한 확장으로 응답합니다

func scaledTo(size: CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(size, false, 0.0);
    self.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return newImage
}

그리고 보너스

func scaledTo(height: CGFloat) -> UIImage{
    let width = height*self.size.width/self.size.height
    return scaledTo(size: CGSize(width: width, height: height))
}

5

안전 장치 옵션이있는 Swift 3.0 (오류 발생시 원본 이미지를 반환) :

func resize(image: UIImage, toSize size: CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(size,false,1.0)
    image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    if let resizedImage = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()
        return resizedImage
    }
    UIGraphicsEndImageContext()
    return image
}

5

(Swift 4 호환) iOS 10+ 및 iOS <10 솔루션 ( UIGraphicsImageRenderer가능한 경우 사용 UIGraphicsGetImageFromCurrentImageContext)

/// Resizes an image
///
/// - Parameter newSize: New size
/// - Returns: Resized image
func scaled(to newSize: CGSize) -> UIImage {
    let rect = CGRect(origin: .zero, size: newSize)

    if #available(iOS 10, *) {
        let renderer = UIGraphicsImageRenderer(size: newSize)
        return renderer.image { _ in
            self.draw(in: rect)
        }
    } else {
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        self.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

5

이미지를 늘리지 않고 효과적인 접근 방식 Swift 4

// Method to resize image
func resize(image: UIImage, toScaleSize:CGSize) -> UIImage {
                UIGraphicsBeginImageContextWithOptions(toScaleSize, true, image.scale)
                        image.draw(in: CGRect(x: 0, y: 0, width: toScaleSize.width, height: toScaleSize.height))
                        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
                        UIGraphicsEndImageContext()
                        return scaledImage!
                }

// 호출 방법

    let resizedImage = self.resize(image: UIImage(named: "YourImageName")!, toScaleSize: CGSize(width: 290, height: 390))

3

@Paul Lynch의 답변은 훌륭하지만 이미지 비율이 변경됩니다. 이미지 비율을 변경하지 않고 새 이미지에 새 이미지를 계속 적용하려면이 방법을 시도하십시오.

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {

// calculate a new size which ratio is same to original image
CGFloat ratioW = image.size.width / newSize.width;
CGFloat ratioH = image.size.height / newSize.height;

CGFloat ratio = image.size.width / image.size.height;

CGSize showSize = CGSizeZero;
if (ratioW > 1 && ratioH > 1) { 

    if (ratioW > ratioH) { 
        showSize.width = newSize.width;
        showSize.height = showSize.width / ratio;
    } else {
        showSize.height = newSize.height;
        showSize.width = showSize.height * ratio;
    }

} else if (ratioW > 1) {

    showSize.width = showSize.width;
    showSize.height = showSize.width / ratio;

} else if (ratioH > 1) {

    showSize.height = showSize.height;
    showSize.width = showSize.height * ratio;

}

//UIGraphicsBeginImageContext(newSize);
// In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
// Pass 1.0 to force exact pixel size.
UIGraphicsBeginImageContextWithOptions(showSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, showSize.width, showSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;}

3

이 확장을 사용하십시오

extension UIImage {
    public func resize(size:CGSize, completionHandler:(resizedImage:UIImage, data:NSData?)->()) {
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { () -> Void in
            let newSize:CGSize = size
            let rect = CGRectMake(0, 0, newSize.width, newSize.height)
            UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
            self.drawInRect(rect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            let imageData = UIImageJPEGRepresentation(newImage, 0.5)
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                completionHandler(resizedImage: newImage, data:imageData)
            })
        })
    }
}

2

스위프트 2.0 :

let image = UIImage(named: "imageName")
let newSize = CGSize(width: 10, height: 10)

UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
let imageResized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

2

여기에 다소 장황한 스위프트 코드가 있습니다.

func scaleImage(image:UIImage,  toSize:CGSize) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(toSize, false, 0.0);

    let aspectRatioAwareSize = self.aspectRatioAwareSize(image.size, boxSize: toSize, useLetterBox: false)


    let leftMargin = (toSize.width - aspectRatioAwareSize.width) * 0.5
    let topMargin = (toSize.height - aspectRatioAwareSize.height) * 0.5


    image.drawInRect(CGRectMake(leftMargin, topMargin, aspectRatioAwareSize.width , aspectRatioAwareSize.height))
    let retVal = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return retVal
}

func aspectRatioAwareSize(imageSize: CGSize, boxSize: CGSize, useLetterBox: Bool) -> CGSize {
    // aspect ratio aware size
    // http://stackoverflow.com/a/6565988/8047
    let imageWidth = imageSize.width
    let imageHeight = imageSize.height
    let containerWidth = boxSize.width
    let containerHeight = boxSize.height

    let imageAspectRatio = imageWidth/imageHeight
    let containerAspectRatio = containerWidth/containerHeight

    let retVal : CGSize
    // use the else at your own risk: it seems to work, but I don't know 
    // the math
    if (useLetterBox) {
        retVal = containerAspectRatio > imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth)
    } else {
        retVal = containerAspectRatio < imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth)
    }

    return retVal
}

1
이것은 나의 시간을 절약했다. 감사!
Quy Nguyen

유용하지만 segue 및 활동 재 방문 후 이상하게 행동하려면 여기를 참조하십시오 : plz : stackoverflow.com/questions/30978685/…
He Yifei 何 一 非

참고하십시오 : 당신은 (전제 조건을 추가 할 수 있습니다 guard받는 사람) aspectRatioAwareSizeimageSize 또는 boxSize 중 하나에 대한 입력 매개 변수가있는 경우 제로 예외하여이 격차가 발생하지 않도록 기능CGSize.zero
pkluz

@ pkluz 이것은 좋은 제안이지만 함수마다 모든 변수가 필요합니다. 각 변수는 다른 줄의 제수이기 때문에 명확하게하기 위해 그대로 두겠습니다. github의 프로덕션이나 라이브러리의 경우 이것을 강화하고 싶을 수도 있습니다 ... 가드 이상으로, 함수가별로 말하지 않는 짧은 변수 이름을 사용하는 것이 걱정됩니다. 아마 그 문제를 먼저 해결 한 다음 다른 것들에 대한 가드를 추가 한 다음 단위 테스트를 추가합니다.
Dan Rosenstark

2

스위프트 4 답변 :

func scaleDown(image: UIImage, withSize: CGSize) -> UIImage {
    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(withSize, false, scale)
    image.draw(in: CGRect(x: 0, y: 0, width: withSize.width, height: withSize.height))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

실제 규모를 설정할 필요가 없습니다 :The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
nathan

1

Swift 3 프로젝트 에서 즉시 사용할 수있는 답변을 찾기가 어렵다는 것을 발견했습니다 . 다른 답변의 주요 문제는 이미지의 알파 채널을 존중하지 않는다는 것입니다. 다음은 프로젝트에서 사용중인 기술입니다.

extension UIImage {

    func scaledToFit(toSize newSize: CGSize) -> UIImage {
        if (size.width < newSize.width && size.height < newSize.height) {
            return copy() as! UIImage
        }

        let widthScale = newSize.width / size.width
        let heightScale = newSize.height / size.height

        let scaleFactor = widthScale < heightScale ? widthScale : heightScale
        let scaledSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor)

        return self.scaled(toSize: scaledSize, in: CGRect(x: 0.0, y: 0.0, width: scaledSize.width, height: scaledSize.height))
    }

    func scaled(toSize newSize: CGSize, in rect: CGRect) -> UIImage {
        if UIScreen.main.scale == 2.0 {
            UIGraphicsBeginImageContextWithOptions(newSize, !hasAlphaChannel, 2.0)
        }
        else {
            UIGraphicsBeginImageContext(newSize)
        }

        draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage ?? UIImage()
    }

    var hasAlphaChannel: Bool {
        guard let alpha = cgImage?.alphaInfo else {
            return false
        }
        return alpha == CGImageAlphaInfo.first ||
            alpha == CGImageAlphaInfo.last ||
            alpha == CGImageAlphaInfo.premultipliedFirst ||
            alpha == CGImageAlphaInfo.premultipliedLast
    }
}

사용 예 :

override func viewDidLoad() {
    super.viewDidLoad()

    let size = CGSize(width: 14.0, height: 14.0)
    if let image = UIImage(named: "barbell")?.scaledToFit(toSize: size) {
        let imageView = UIImageView(image: image)
        imageView.center = CGPoint(x: 100, y: 100)
        view.addSubview(imageView)
    }
}

이 코드는 알파 채널 유무에 관계없이 이미지에 대한 지원이 추가 된 Apple 확장의 재 작성입니다 .

추가로 읽을 때 다른 이미지 크기 조정 기술에 대해이 기사 를 확인 하는 것이 좋습니다 . 현재 접근 방식은 적절한 성능을 제공하고 높은 수준의 API를 운영하며 이해하기 쉽습니다. 이미지 크기 조정이 성능에 병목 현상이 발생하지 않는 한이를 고수하는 것이 좋습니다.


1

가로 세로 비율로만 너비 / 높이의 크기를 조정해야하는 경우이 확장을 사용하십시오.

extension UIImage {
    func resize(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
    func resize(width: CGFloat) -> UIImage {
        return resize(to: CGSize(width: width, height: width / (size.width / size.height)))
    }
    func resize(height: CGFloat) -> UIImage {
        return resize(to: CGSize(width: height * (size.width / size.height), height: height))
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.