在做項目時我們經常要對圖片進行一些處理,以達到性能優化或滿足需求。常見的情形有以下幾種
拉伸圖片
項目中使用的圖片素材如果能通過拉伸獲得就盡量這樣去做。這樣做有兩個顯而易見的好處,一是能夠減少App安裝包的大小,另外一個則是減少App運行時占據的內存空間大小。畢竟App的UI基本上來說是建立在大量的精致的圖片上,如果這些圖片都一概使用屏幕等大小的圖片,那麼對App的性能及安裝量都是有一定的負面影響的。
對於拉伸圖片,適配ios 5及之後可以使用
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets這個方法只接收一個UIEdgeInsets類型的參數,可以通過設置UIEdgeInsets的top、left、bottom、right來分別指定上端蓋高度、左端蓋寬度、下端蓋高度、右端蓋寬度。這個端蓋的距離值是用單位pt(點,point)衡量的,在普通顯示屏中,1pt = 1pix;在retina顯示屏中,1pt = 2pix。還有一個需要注意的地方,如果端蓋距離值不是整數的話,拉伸後的圖片會有白條細線。
創建縮略圖
如果有一張大圖,我們只想要顯示它的指定大小的縮略圖內容,可以這樣做:在UIImage的類別中實現如下方法,調用方法創建縮略圖
- (UIImage *)imageByScalingAndCroppingForSize:(CGSize)targetSize { UIImage *sourceImage = self; 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; // scale to fit height else scaleFactor = heightFactor; // scale to fit width 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; } } UIGraphicsBeginImageContext(targetSize); // this will crop CGRect thumbnailRect = CGRectZero; thumbnailRect.origin = thumbnailPoint; thumbnailRect.size.width = scaledWidth; thumbnailRect.size.height = scaledHeight; [sourceImage drawInRect:thumbnailRect]; newImage = UIGraphicsGetImageFromCurrentImageContext(); if(newImage == nil) NSLog(@"could not scale image"); //pop the context to get back to the default UIGraphicsEndImageContext(); return newImage; }
ios程序中使用系統相機拍照和從相冊選取圖片,直接上傳後在非mac系統下看到的圖片會發生旋轉的現象,那是因為我們沒有通過圖片的旋轉屬性修改圖片轉向。可以用下面的方法解決這個問題:
@interface UIImage (fixOrientation) - (UIImage *)fixOrientation; @end @implementation UIImage (fixOrientation) - (UIImage *)fixOrientation { // No-op if the orientation is already correct if (self.imageOrientation == UIImageOrientationUp) return self; // We need to calculate the proper transformation to make the image upright. // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored. CGAffineTransform transform = CGAffineTransformIdentity; switch (self.imageOrientation) { case UIImageOrientationDown: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, 0); transform = CGAffineTransformRotate(transform, M_PI_2); break; case UIImageOrientationRight: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, 0, self.size.height); transform = CGAffineTransformRotate(transform, -M_PI_2); break; } switch (self.imageOrientation) { case UIImageOrientationUpMirrored: case UIImageOrientationDownMirrored: transform = CGAffineTransformTranslate(transform, self.size.width, 0); transform = CGAffineTransformScale(transform, -1, 1); break; case UIImageOrientationLeftMirrored: case UIImageOrientationRightMirrored: transform = CGAffineTransformTranslate(transform, self.size.height, 0); transform = CGAffineTransformScale(transform, -1, 1); break; } // Now we draw the underlying CGImage into a new context, applying the transform // calculated above. CGContextRef ctx = CGBitmapContextCreate(NULL, self.size.width, self.size.height, CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage)); CGContextConcatCTM(ctx, transform); switch (self.imageOrientation) { case UIImageOrientationLeft: case UIImageOrientationLeftMirrored: case UIImageOrientationRight: case UIImageOrientationRightMirrored: // Grr... CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage); break; default: CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage); break; } // And now we just create a new UIImage from the drawing context CGImageRef cgimg = CGBitmapContextCreateImage(ctx); UIImage *img = [UIImage imageWithCGImage:cgimg]; CGContextRelease(ctx); CGImageRelease(cgimg); return img; } @end
圖片編碼及上傳
有時候我們會需要將圖片數據以字符串的形式上傳到服務器。在將UIImage對象轉化為NSData再轉化為NSString的時候,NSString對象中會出現有亂碼的情況,這個時候再將NSData轉化為NSString之前要編碼NSData對象
#import "UIImage+Ext.h" #import "GTMBase64.h" @interface UIImage (Ext) - (NSString *)convertToString; @end @implementation UIImage (Ext) - (NSString *)convertToString { if (!self) { return nil; } NSData *imgData = UIImageJPEGRepresentation(self,0.5); NSData *encode = [GTMBase64 encodeData:imgData]; // base64編碼NSData(解決亂碼問題) NSString *imgStr = [[NSString alloc] initWithData:encode encoding:NSUTF8StringEncoding]; return imgStr; } @end
要將圖片存儲到本地磁盤中,需要先把圖片對象轉化為NSData對象,然後調用writeToFile:接口寫入
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;