2011-05-26 54 views
67

我需要縮小圖像的大小,但方式很敏銳。在Photoshop中,例如,圖像尺寸縮小選項「Bicubic Smoother」(模糊)和「Bicubic Sharper」。如何縮小UIImage並使其變得脆脆/銳利,而不是模糊?

此圖像縮小算法是開源還是在某處存在文檔,或者SDK是否提供了執行此操作的方法?

+0

的可能重複的[如何按比例提供高品質的一個UIImage](http://stackoverflow.com/questions/6052188/how-to-scale-a-uiimage-with-high - 質量) – DarkDust 2011-05-26 15:59:47

+0

另請參閱[任何代碼/庫縮小UIImage?](http://stackoverflow.com/questions/1573758/any-code-library-to-scale-down-an-uiimage)。 – DarkDust 2011-05-26 16:01:29

+0

看到這個問題。 http://stackoverflow.com/questions/2658738/the-simplest-way-to-resize-an-uiimage最被投票的答案是我找到的這個問題的最簡單的解決方案。 – 2013-01-10 15:52:56

回答

122

僅僅使用imageWithCGImage是不夠的。它會擴大規模,但結果將會模糊和不理想,無論是向上還是向下。

如果你想得到別名的權利,擺脫「鋸齒」你需要這樣的事情:http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

我的工作測試代碼看起來是這樣的,這是Trevor的一個小的調整解決方案與我透明的PNG工作:

- (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(); 

    // Set the quality level to use when rescaling 
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh); 
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height); 

    CGContextConcatCTM(context, flipVertical); 
    // Draw into the context; this scales the image 
    CGContextDrawImage(context, newRect, imageRef); 

    // Get the resized image from the context and a UIImage 
    CGImageRef newImageRef = CGBitmapContextCreateImage(context); 
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; 

    CGImageRelease(newImageRef); 
    UIGraphicsEndImageContext();  

    return newImage; 
} 
+0

謝謝!正在尋找這個。這適用於PNG,但繞過特雷弗的'transformForOrientation'。這個功能真的有必要嗎?它僅適用於帶有方向元數據的JPG嗎? – pixelfreak 2011-10-22 22:22:15

+0

@pixelfreak是你說我提供的代碼缺少使用在其元數據中設置方向的jpegs的必要工作嗎?如果它不會太複雜,請隨意編輯我的代碼。我只是剔除了Trevor代碼中不需要 – 2011-10-22 23:40:26

+1

的東西,他正在檢查'imageOrientation'(我假設的EXIF數據),並根據其值進行額外的轉換。不知道是否有必要。我會玩弄它。 – pixelfreak 2011-10-23 00:44:07

11

如果在縮放時保留圖像的原始縱橫比,則無論縮小多少,總是會得到清晰的圖像。

您可以用下面的方法進行縮放:

+ (UIImage *)imageWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation 
+2

爲我工作... – 2012-06-22 21:40:48

+1

該UIImage方法有什麼問題? – rodowi 2012-10-11 20:30:29

+0

似乎對視圖應用了轉換,但不調整基礎數據的大小 – Cbas 2016-07-21 06:47:01

2

@YAR您的解決方案是否工作正常。

只有一件事不符合我的要求:整個圖像被調整大小。我寫了一個類似photos app on iphone的方法。 這會計算「長邊」並切斷「疊加」,從而獲得有關圖像質量的更好結果。

- (UIImage *)resizeImageProportionallyIntoNewSize:(CGSize)newSize; 
{ 
    CGFloat scaleWidth = 1.0f; 
    CGFloat scaleHeight = 1.0f; 

    if (CGSizeEqualToSize(self.size, newSize) == NO) { 

     //calculate "the longer side" 
     if(self.size.width > self.size.height) { 
      scaleWidth = self.size.width/self.size.height; 
     } else { 
      scaleHeight = self.size.height/self.size.width; 
     } 
    }  

    //prepare source and target image 
    UIImage *sourceImage = self; 
    UIImage *newImage = nil; 

    // Now we create a context in newSize and draw the image out of the bounds of the context to get 
    // A proportionally scaled image by cutting of the image overlay 
    UIGraphicsBeginImageContext(newSize); 

    //Center image point so that on each egde is a little cutoff 
    CGRect thumbnailRect = CGRectZero; 
    thumbnailRect.size.width = newSize.width * scaleWidth; 
    thumbnailRect.size.height = newSize.height * scaleHeight; 
    thumbnailRect.origin.x = (int) (newSize.width - thumbnailRect.size.width) * 0.5; 
    thumbnailRect.origin.y = (int) (newSize.height - thumbnailRect.size.height) * 0.5; 

    [sourceImage drawInRect:thumbnailRect]; 

    newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

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

    return newImage ; 
} 
18

對於這裏使用雨燕的是斯威夫特接受的答案:

func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) { 
    let newRect = CGRectIntegral(CGRectMake(0,0, newSize.width, newSize.height)) 
    let imageRef = image.CGImage 

    UIGraphicsBeginImageContextWithOptions(newSize, false, 0) 
    let context = UIGraphicsGetCurrentContext() 

    // Set the quality level to use when rescaling 
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh) 
    let flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height) 

    CGContextConcatCTM(context, flipVertical) 
    // Draw into the context; this scales the image 
    CGContextDrawImage(context, newRect, imageRef) 

    let newImageRef = CGBitmapContextCreateImage(context) as CGImage 
    let newImage = UIImage(CGImage: newImageRef) 

    // Get the resized image from the context and a UIImage 
    UIGraphicsEndImageContext() 

    return newImage 
} 
+0

酷!那麼你也可以把它作爲一個擴展。 – 2015-06-06 21:26:55

+1

爲什麼你需要翻轉圖像來調整它的大小(例如,爲什麼你需要'CGContextConcatCTM(context,flipVertical)'? – Crashalot 2016-01-26 22:18:56

+5

kCGInterpolationHigh - > CGInterpolation.High在Swift 2中,或者你得到一個編譯錯誤 – Crashalot 2016-01-27 01:41:28

14

如果有人找斯威夫特的版本,這裏是雨燕版本@亞爾的接受的答案:

func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage { 
    let scale = newHeight/image.size.height 
    let newWidth = image.size.width * scale 
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)) 
    image.drawInRect(CGRectMake(0, 0, newWidth, newHeight)) 
    let newImage = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 

    return newImage 
} 
+1

感謝答案我們也可以用的是作爲一個擴展 公共推廣的UIImage { FUNC ... } – mert 2016-01-28 11:32:18

+0

雷大姐在下面的鏈接的答案完全適用於我的http://計算器。 com/questions/6052188/uiimage的高質量縮放 – 2016-03-16 09:50:04

10

For Swift 3

func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) { 

    let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral 
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0) 
    let context = UIGraphicsGetCurrentContext() 

    // Set the quality level to use when rescaling 
    context!.interpolationQuality = CGInterpolationQuality.default 
    let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height) 

    context!.concatenate(flipVertical) 
    // Draw into the context; this scales the image 
    context?.draw(image.cgImage!, in: CGRect(x: 0.0,y: 0.0, width: newRect.width, height: newRect.height)) 

    let newImageRef = context!.makeImage()! as CGImage 
    let newImage = UIImage(cgImage: newImageRef) 

    // Get the resized image from the context and a UIImage 
    UIGraphicsEndImageContext() 

    return newImage 
} 
+0

這是將圖像視爲縱橫填充,是否有一種方法可以使其縱向適合?謝謝 – Coder221 2017-10-10 22:51:02

0

此擴展應該在保持原始寬高比的同時縮放圖像。圖像的其餘部分被裁剪。 (SWIFT 3)

extension UIImage {  
    func thumbnail(ofSize proposedSize: CGSize) -> UIImage? { 

     let scale = min(size.width/proposedSize.width, size.height/proposedSize.height) 

     let newSize = CGSize(width: size.width/scale, height: size.height/scale) 
     let newOrigin = CGPoint(x: (proposedSize.width - newSize.width)/2, y: (proposedSize.height - newSize.height)/2) 

     let thumbRect = CGRect(origin: newOrigin, size: newSize).integral 

     UIGraphicsBeginImageContextWithOptions(proposedSize, false, 0) 

     draw(in: thumbRect) 

     let result = UIGraphicsGetImageFromCurrentImageContext() 

     UIGraphicsEndImageContext() 

     return result 
    } 
}