iOS的圖片壓縮,目前我在用的有兩種:
一、在內存中壓縮
需要消耗內存,如果圖片較多,可能會造成crash
//壓縮圖片質量 +(UIImage *)reduceImage:(UIImage *)p_w_picpath percent:(float)percent { NSData *p_w_picpathData = UIImageJPEGRepresentation(p_w_picpath, percent); UIImage *newImage = [UIImage p_w_picpathWithData:p_w_picpathData]; return newImage; } //壓縮圖片尺寸 + (UIImage*)p_w_picpathWithImageSimple:(UIImage*)p_w_picpath scaledToSize:(CGSize)newSize { // Create a graphics p_w_picpath context UIGraphicsBeginImageContext(newSize); // new size [p_w_picpath drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; // Get the new p_w_picpath from the context UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); // End the context UIGraphicsEndImageContext(); // Return the new p_w_picpath. return newImage; }
二、利用ALAsset壓縮
#import <AssetsLibrary/AssetsLibrary.h> #import <ImageIO/ImageIO.h> static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) { ALAssetRepresentation *rep = (__bridge id)info; NSError *error = nil; size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error]; if (countRead == 0 && error) { // We have no way of passing this info back to the caller, so we log it, at least. NSLog(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error); } return countRead; } static void releaseAssetCallback(void *info) { // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:. // This release balances that retain. CFRelease(info); } - (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size { NSParameterAssert(asset != nil); NSParameterAssert(size > 0); ALAssetRepresentation *rep = [asset defaultRepresentation]; CGDataProviderDirectCallbacks callbacks = { .version = 0, .getBytePointer = NULL, .releaseBytePointer = NULL, .getBytesAtPosition = getAssetBytesCallback, .releaseInfo = releaseAssetCallback, }; CGDataProviderRef provider = CGDataProviderCreateDirect((void *)CFBridgingRetain(rep), [rep size], &callbacks); CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL); CGImageRef p_w_picpathRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef) @{ (NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @YES, (NSString *)kCGImageSourceThumbnailMaxPixelSize : @(size), (NSString *)kCGImageSourceCreateThumbnailWithTransform : @YES, }); CFRelease(source); CFRelease(provider); if (!p_w_picpathRef) { return nil; } UIImage *toReturn = [UIImage p_w_picpathWithCGImage:p_w_picpathRef]; CFRelease(p_w_picpathRef); return toReturn; }
#pragma mark - UIImagePickerControllerDelegate - (void)p_w_picpathPickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { NSLog(@"info:\n%@", info); UIImage *p_w_picpath = info[UIImagePickerControllerOriginalImage]; NSData *imgData = UIImagePNGRepresentation(p_w_picpath); NSLog(@"length1: %lu", (unsigned long)imgData.length); NSURL *p_w_picpathURL = info[UIImagePickerControllerReferenceURL]; ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; [assetsLibrary assetForURL:p_w_picpathURL resultBlock:^(ALAsset *asset) { UIImage *p_w_picpath = [self thumbnailForAsset:asset maxPixelSize:1]; NSData *imgData = UIImagePNGRepresentation(p_w_picpath); NSLog(@"length2: %lu", (unsigned long)imgData.length); } failureBlock:nil]; [picker dismissViewControllerAnimated:YES completion:^{ }]; }
使用第二種方法內存佔用率很低,很適合做多張圖片的壓縮處理。