1~图片压缩
(1)UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];//
NSData *imageData = UIImageJPEGRepresentation(image, 0.5);
UIImage *curimage = [UIImage imageWithData:imageData];
在Iphone上有两种读取图片数据的简单方法:
UIImageJPEGRepresentation和UIImagePNGRepresentation.
UIImageJPEGRepresentation函数需要两个参数:图片的引用和压缩系数.而UIImagePNGRepresentation只需要图片引用作为参数.通过在实际使用过程中,比较发现: UIImagePNGRepresentation(UIImage* image) 要比UIImageJPEGRepresentation(UIImage* image, 1.0) 返回的图片数据量大很多.譬如,同样是读取摄像头拍摄的同样景色的照片, UIImagePNGRepresentation()返回的数据量大小为199K ,而 UIImageJPEGRepresentation(UIImage* image, 1.0)返回的数据量大小只为140KB,比前者少了50多KB.如果对图片的清晰度要求不高,还可以通过设置 UIImageJPEGRepresentation函数的第二个参数,大幅度降低图片数据量.譬如,刚才拍摄的图片, 通过调用UIImageJPEGRepresentation(UIImage* image, 1.0)读取数据时,返回的数据大小为140KB,但更改压缩系数后,通过调用UIImageJPEGRepresentation(UIImage* image, 0.5)读取数据时,返回的数据大小只有11KB多,大大压缩了图片的数据量 ,而且从视角角度看,图片的质量并没有明显的降低.因此,在读取图片数据内容时,建议优先使用UIImageJPEGRepresentation,并可根据自己的实际使用场景,设置压缩系数,进一步降低图片数据量大小.
方法二
image3 = [UploadClassViewCTRL thumbnailWithImage1:image1 size:CGSizeMake(image1.size.width/2, image1.size.height/2)];
+ (UIImage *)thumbnailWithImage1:(UIImage *)image size:(CGSize)asize
{
UIImage *newimage;
if (nil == image) {
newimage = nil;
}
else{
UIGraphicsBeginImageContext(asize);
[image drawInRect:CGRectMake(0, 0, asize.width, asize.height)];
newimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return newimage;
}
2~图片旋转
UIImage * myimage = [UIImage imageWithCGImage:[image CGImage] scale:1 orientation:UIImageOrientationRight];
[self.HeadImageView setImage:myimage];
(2)
- (UIImage *)fixOrientation:(UIImage*)myImage {
// No-op if the orientation is already correct
if (myImage.imageOrientation == UIImageOrientationUp) return myImage;
// 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 (myImage.imageOrientation) {
case UIImageOrientationDown:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, myImage.size.width, myImage.size.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
transform = CGAffineTransformTranslate(transform, myImage.size.width, 0);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, 0, myImage.size.height);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
}
switch (myImage.imageOrientation) {
case UIImageOrientationUpMirrored:
case UIImageOrientationDownMirrored:
transform = CGAffineTransformTranslate(transform, myImage.size.width, 0);
transform = CGAffineTransformScale(transform, -1, 1);
break;
case UIImageOrientationLeftMirrored:
case UIImageOrientationRightMirrored:
transform = CGAffineTransformTranslate(transform, myImage.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, myImage.size.width, myImage.size.height,
CGImageGetBitsPerComponent(myImage.CGImage), 0,
CGImageGetColorSpace(myImage.CGImage),
CGImageGetBitmapInfo(myImage.CGImage));
CGContextConcatCTM(ctx, transform);
switch (myImage.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
// Grr...
CGContextDrawImage(ctx, CGRectMake(0,0,myImage.size.height,myImage.size.width), myImage.CGImage);
break;
default:
CGContextDrawImage(ctx, CGRectMake(0,0,myImage.size.width,myImage.size.height), myImage.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;
}
3~设置默认图
NSURL *urlhead = [NSURL URLWithString:[dic valueForKey:@"user_photo"]];
[self.ImageHead setImageWithURL:urlhead placeholderImage:[UIImage imageNamed:@"doctor.jpg"]];//imageHead 为UIimageView类型
4~IOS与图片内存
在IOS上,图片会被自动缩放到2的N次方大小。比如一张1024*1025的图片,占用的内存与一张1024*2048的图片是一致的。图片占用内存大小的计算的公式是;长*宽*4。这样一张512*512 占用的内存就是 512*512*4 = 1M。其他尺寸以此类推。(ps:IOS上支持的最大尺寸为2048*2048)。
5~图片的缓存
在开发移动应用的时候比如Android,IOS,因为手机流量、网速、内存等这些因素,当我们的移动应用是针对互联网,并要频繁访问网络的话,对网络优化这块就显得尤为重要了。
比如某个应用要经常显示网络图片,就不能每次显示图片都去网络上下载,那太耗费时间也太耗费流量,这时就要对网络图片进行缓存了,以下是我对IOS网络图片缓存的一些见解,有不足之处,欢迎大家指出来,一起探讨。
处理网络图片缓存步骤:
1、根据图片URL查找内存是否有这张图片,有则返回图片,没有则进入第二步
2、查找物理存储是否有这张图片,有则返回图片,没有则进入第三步
3、从网络上下载该图片,下载完后保存到内存和物理存储上,并返回该图片
注:因为URL包含特殊字符和长度不确定,要对URL进行MD5处理或其他处理
下面是针对以上步骤的代码讲解:
1、内存缓存图片处理
使用NSMutableDictionary存储图片UIImage,数组的Key为该图片的URL地址
//缓存图片到内存上[plain] view plaincopy
- [memCache setObject:image forKey:key];
2、物理缓存图片处理
把图片保持到物理存储设备上,则直接使用NSFileManager,把URL作为文件名保存
3、网络图片下载处理
图片使用异步下载,下载完后把图片保持到NSMutableDictionary和物理存储上
以下是摘自SDWebImageleik网络图片缓存处理的一个类,有详细注释
.h文件
[plain] view plaincopy
- @interface SDImageCache : NSObject
- {
- NSMutableDictionary *memCache;//内存缓存图片引用
- NSString *diskCachePath;//物理缓存路径
- NSOperationQueue *cacheInQueue, *cacheOutQueue;
- }
- + (SDImageCache *)sharedImageCache;
- //保存图片
- - (void)storeImage:(UIImage *)image forKey:(NSString *)key;
- //保存图片,并选择是否保存到物理存储上
- - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk;
- //保存图片,可以选择把NSData数据保存到物理存储上
- - (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk;
- //通过key返回UIImage
- - (UIImage *)imageFromKey:(NSString *)key;
- //如果获取内存图片失败,是否可以在物理存储上查找
- - (UIImage *)imageFromKey:(NSString *)key fromDisk:(BOOL)fromDisk;
- - (void)queryDiskCacheForKey:(NSString *)key delegate:(id <SDImageCacheDelegate>)delegate userInfo:(NSDictionary *)info;
- //清除key索引的图片
- - (void)removeImageForKey:(NSString *)key;
- //清除内存图片
- - (void)clearMemory;
- //清除物理缓存
- - (void)clearDisk;
- //清除过期物理缓存
- - (void)cleanDisk;
- @end
.m文件[plain] view plaincopy
- @implementation SDImageCache
- #pragma mark NSObject
- - (id)init
- {
- if ((self = [super init]))
- {
- // Init the memory cache
- memCache = [[NSMutableDictionary alloc] init];
- // Init the disk cache
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
- diskCachePath = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageCache"] retain];
- if (![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath])
- {
- [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath
- withIntermediateDirectories:YES
- attributes:nil
- error:NULL];
- }
- // Init the operation queue
- cacheInQueue = [[NSOperationQueue alloc] init];
- cacheInQueue.maxConcurrentOperationCount = 1;
- cacheOutQueue = [[NSOperationQueue alloc] init];
- cacheOutQueue.maxConcurrentOperationCount = 1;
- #if TARGET_OS_IPHONE
- // Subscribe to app events
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(clearMemory)
- name:UIApplicationDidReceiveMemoryWarningNotification
- object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(cleanDisk)
- name:UIApplicationWillTerminateNotification
- object:nil];
- #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0
- UIDevice *device = [UIDevice currentDevice];
- if ([device respondsToSelector:@selector(isMultitaskingSupported)] && device.multitaskingSupported)
- {
- // When in background, clean memory in order to have less chance to be killed
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(clearMemory)
- name:UIApplicationDidEnterBackgroundNotification
- object:nil];
- }
- #endif
- #endif
- }
- return self;
- }
- - (void)dealloc
- {
- [memCache release], memCache = nil;
- [diskCachePath release], diskCachePath = nil;
- [cacheInQueue release], cacheInQueue = nil;
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [super dealloc];
- }
- #pragma mark SDImageCache (class methods)
- + (SDImageCache *)sharedImageCache
- {
- if (instance == nil)
- {
- instance = [[SDImageCache alloc] init];
- }
- return instance;
- }
- #pragma mark SDImageCache (private)
- /*
- *创建指定图片key的路径
- */
- - (NSString *)cachePathForKey:(NSString *)key
- {
- const char *str = [key UTF8String];
- unsigned char r[CC_MD5_DIGEST_LENGTH];
- CC_MD5(str, (CC_LONG)strlen(str), r);
- NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]];
- return [diskCachePath stringByAppendingPathComponent:filename];
- }
- /*
- *保存key和Data到物理存储
- *keyAndData[0] ->key
- *keyAndData[1] ->Data
- */
- - (void)storeKeyWithDataToDisk:(NSArray *)keyAndData
- {
- // Can't use defaultManager another thread
- NSFileManager *fileManager = [[NSFileManager alloc] init];
- NSString *key = [keyAndData objectAtIndex:0];
- NSData *data = [keyAndData count] > 1 ? [keyAndData objectAtIndex:1] : nil;
- //如果有数据,则保存到物理存储上
- if (data)
- {
- [fileManager createFileAtPath:[self cachePathForKey:key] contents:data attributes:nil];
- }
- else
- {
- //如果没有data,则把UIImage转换为JPEG,并保存到物理存储上
- // If no data representation given, convert the UIImage in JPEG and store it
- // This trick is more CPU/memory intensive and doesn't preserve alpha channel
- UIImage *image = [[self imageFromKey:key fromDisk:YES] retain]; // be thread safe with no lock
- if (image)
- {
- #if TARGET_OS_IPHONE
- [fileManager createFileAtPath:[self cachePathForKey:key] contents:UIImageJPEGRepresentation(image, (CGFloat)1.0) attributes:nil];
- #else
- NSArray* representations = [image representations];
- NSData* jpegData = [NSBitmapImageRep representationOfImageRepsInArray: representations usingType: NSJPEGFileType properties:nil];
- [fileManager createFileAtPath:[self cachePathForKey:key] contents:jpegData attributes:nil];
- #endif
- [image release];
- }
- }
- [fileManager release];
- }
- /*
- *查找图片委托
- */
- - (void)notifyDelegate:(NSDictionary *)arguments
- {
- NSString *key = [arguments objectForKey:@"key"];
- id <SDImageCacheDelegate> delegate = [arguments objectForKey:@"delegate"];
- NSDictionary *info = [arguments objectForKey:@"userInfo"];
- UIImage *image = [arguments objectForKey:@"image"];
- if (image)
- {
- [memCache setObject:image forKey:key];
- if ([delegate respondsToSelector:@selector(imageCache:didFindImage:forKey:userInfo:)])
- {
- [delegate imageCache:self didFindImage:image forKey:key userInfo:info];
- }
- }
- else
- {
- if ([delegate respondsToSelector:@selector(imageCache:didNotFindImageForKey:userInfo:)])
- {
- [delegate imageCache:self didNotFindImageForKey:key userInfo:info];
- }
- }
- }
- /*
- *查找物理缓存上的图片
- */
- - (void)queryDiskCacheOperation:(NSDictionary *)arguments
- {
- NSString *key = [arguments objectForKey:@"key"];
- NSMutableDictionary *mutableArguments = [[arguments mutableCopy] autorelease];
- UIImage *image = [[[UIImage alloc] initWithContentsOfFile:[self cachePathForKey:key]] autorelease];
- if (image)
- {
- #ifdef ENABLE_SDWEBIMAGE_DECODER
- UIImage *decodedImage = [UIImage decodedImageWithImage:image];
- if (decodedImage)
- {
- image = decodedImage;
- }
- #endif
- [mutableArguments setObject:image forKey:@"image"];
- }
- [self performSelectorOnMainThread:@selector(notifyDelegate:) withObject:mutableArguments waitUntilDone:NO];
- }
- #pragma mark ImageCache
- /*
- *缓存图片
- *
- **/
- - (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk
- {
- if (!image || !key)
- {
- return;
- }
- //缓存图片到内存上
- [memCache setObject:image forKey:key];
- //如果需要缓存到物理存储上,并data不为空,则把data缓存到物理存储上
- if (toDisk)
- {
- if (!data) return;
- NSArray *keyWithData;
- if (data)
- {
- keyWithData = [NSArray arrayWithObjects:key, data, nil];
- }
- else
- {
- keyWithData = [NSArray arrayWithObjects:key, nil];
- }
- //后台线程缓存图片到物理存储上
- [cacheInQueue addOperation:[[[NSInvocationOperation alloc] initWithTarget:self
- selector:@selector(storeKeyWithDataToDisk:)
- object:keyWithData] autorelease]];
- }
- }
- /*
- *保存图片到内存上,不保存到物理存储上
- */
- - (void)storeImage:(UIImage *)image forKey:(NSString *)key
- {
- [self storeImage:image imageData:nil forKey:key toDisk:YES];
- }
- /*
- *保存图片到内存上,不保存到物理存储上
- */
- - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk
- {
- [self storeImage:image imageData:nil forKey:key toDisk:toDisk];
- }
- /*
- *通过key返回指定图片
- */
- - (UIImage *)imageFromKey:(NSString *)key
- {
- return [self imageFromKey:key fromDisk:YES];
- }
- /*
- *返回一张图像
- *key:图像的key
- *fromDisk:如果内存中没有图片,是否在物理存储上查找
- *return 返回查找到的图片,如果没有则返回nil
- */
- - (UIImage *)imageFromKey:(NSString *)key fromDisk:(BOOL)fromDisk
- {
- if (key == nil)
- {
- return nil;
- }
- UIImage *image = [memCache objectForKey:key];
- if (!image && fromDisk) //如果内存没有图片,并且可以在物理存储上查找,则返回物理存储上的图片
- {
- image = [[[UIImage alloc] initWithContentsOfFile:[self cachePathForKey:key]] autorelease];
- if (image)
- {
- [memCache setObject:image forKey:key];
- }
- }
- return image;
- }
- - (void)queryDiskCacheForKey:(NSString *)key delegate:(id <SDImageCacheDelegate>)delegate userInfo:(NSDictionary *)info
- {
- if (!delegate)
- {
- return;
- }
- if (!key)
- {
- if ([delegate respondsToSelector:@selector(imageCache:didNotFindImageForKey:userInfo:)])
- {
- [delegate imageCache:self didNotFindImageForKey:key userInfo:info];
- }
- return;
- }
- // First check the in-memory cache...
- UIImage *image = [memCache objectForKey:key];
- if (image)
- {
- // ...notify delegate immediately, no need to go async
- if ([delegate respondsToSelector:@selector(imageCache:didFindImage:forKey:userInfo:)])
- {
- [delegate imageCache:self didFindImage:image forKey:key userInfo:info];
- }
- return;
- }
- NSMutableDictionary *arguments = [NSMutableDictionary dictionaryWithCapacity:3];
- [arguments setObject:key forKey:@"key"];
- [arguments setObject:delegate forKey:@"delegate"];
- if (info)
- {
- [arguments setObject:info forKey:@"userInfo"];
- }
- [cacheOutQueue addOperation:[[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(queryDiskCacheOperation:) object:arguments] autorelease]];
- }
- /*
- *从内存和物理存储上移除指定图片
- */
- - (void)removeImageForKey:(NSString *)key
- {
- if (key == nil)
- {
- return;
- }
- [memCache removeObjectForKey:key];
- [[NSFileManager defaultManager] removeItemAtPath:[self cachePathForKey:key] error:nil];
- }
- /*
- *清除内存缓存区的图片
- */
- - (void)clearMemory
- {
- [cacheInQueue cancelAllOperations]; // won't be able to complete
- [memCache removeAllObjects];
- }
- /*
- *清除物理存储上的图片
- */
- - (void)clearDisk
- {
- [cacheInQueue cancelAllOperations];
- [[NSFileManager defaultManager] removeItemAtPath:diskCachePath error:nil];
- [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath
- withIntermediateDirectories:YES
- attributes:nil
- error:NULL];
- }
- /*
- *清除过期缓存的图片
- */
- - (void)cleanDisk
- {
- NSDate *expirationDate = [NSDate dateWithTimeIntervalSinceNow:-cacheMaxCacheAge];
- NSDirectoryEnumerator *fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:diskCachePath];
- for (NSString *fileName in fileEnumerator)
- {
- NSString *filePath = [diskCachePath stringByAppendingPathComponent:fileName];
- NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
- if ([[[attrs fileModificationDate] laterDate:expirationDate] isEqualToDate:expirationDate])
- {
- [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
- }
- }
- }
- @end