在做項目時我們經常要對圖片進行一些處理,以達到性能優化或滿足需求。常見的情形有以下幾種
拉伸圖片
項目中使用的圖片素材如果能通過拉伸獲得就盡量這樣去做。這樣做有兩個顯而易見的好處,一是能夠減少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;