iOS - Image compression algorithm
...大约 2 分钟
由于最近公司在做图片相册选择上传的功能,对于图片的压缩算法这里我借鉴了 ochina 的 ios 端 App。其中有涉及到图片压缩的算法,这里贴出来留待后用;
GACompressionPicHandle.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>
@class GACompressionPicHandle;
@protocol GACompressionPicHandleDelegate <NSObject>
- (void)CompressionPicHandle:(GACompressionPicHandle* )handle
CompressionFailureInfo:(NSString* )info;
@end
#define CompressionMax_W 1224
#define CompressionMax_Size 300 * 1024
/** OSChina 后台限制上传图片的大小*/
#define stand_size 1024 * 800
#define min_compressionRatio 0.3
@interface GACompressionPicHandle : NSObject
+ (instancetype)shareCompressionPicHandle;
@property(nonatomic,weak)id<GACompressionPicHandleDelegate> delegate;
/** 分辨率越小反而越占用时间 建议分辨率高的图片使用*/
- (NSData* )scaleToSize:(CGSize)size
image:(UIImage* )picture;
/** 受到宽高比例问题 越接近正方形所用的时间越小 */
- (NSData *)imageByScalingAndCroppingForSize:( CGSize)targetSize image:(UIImage *)image;
@end
GACompressionPicHandle.m
#import "GACompressionPicHandle.h"
@implementation GACompressionPicHandle
static GACompressioinPicHandle*_shareCompressionPicHandle;
+ (instancetype)shareCompressionPicHandle{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shareCompressionPicHandle = [[GACompressionPicHandle alloc]init];
});
return _shareCompressionPicHandle;
}
- (NSData* )scaleToSize:(CGSize)sizeimage:(UIImage* )picture {
CGFloat width = CGImageGetWidth(picture.CGImage);
CGFloat height = CGImageGetHeight(picture.CGImage);
float verticalRadio = size.height * 1.0 / height;
float horizontalRadio = size.width * 1.0 / width;
float radio = 1;
if(verticalRadio > 1 && horizontalRadio > 1) {
radio = verticalRadio > horizontalRadio ? horizontalRadio : verticalRadio;
}else{
radio = verticalRadio < horizontalRadio ? verticalRadio : horizontalRadio;
}
width = width * radio;
height = height * radio;
int xPos = (size.width - width) / 2;
int yPos = (size.height - height) / 2;
UIGraphicsBeginImageContext(size);
[picture drawInRect:CGRectMake(xPos, yPos, width, height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData* scaledImageData = UIImageJPEGRepresentation(scaledImage, 1);
CGFloat compressionRatio = 0.9f;
NSData* tagerImageData = scaledImageData;
NSLog(@"tagerImageData.length : %lu",(unsigned long)tagerImageData.length);
while (tagerImageData.length > stand_size && compressionRatio > 0) {
if (compressionRatio < min_compressionRatio) {
if ([_delegate respondsToSelector:@selector(CompressionPicHandle:CompressionFailureInfo:)]) {
[_delegate CompressionPicHandle:self CompressionFailureInfo:@"图片过大"];
}
}
@autoreleasepool {
NSData* newCompressionData = UIImageJPEGRepresentation(scaledImage, compressionRatio);
tagerImageData = newCompressionData;
}
compressionRatio = compressionRatio - 0.12;
NSLog(@"tagerImageData.length : %lu , compressionRatio : %lf",tagerImageData.length,compressionRatio);
}
NSLog(@"compressionRatio : %lf",compressionRatio);
return tagerImageData;
}
- (NSData *)imageByScalingAndCroppingForSize:(CGSize)targetSize image:(UIImage *)image {
UIImage *sourceImage = image;
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;
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)
UIGraphicsEndImageContext();
NSData* scaledImageData = UIImageJPEGRepresentation(newImage, 1);
CGFloat compressionRatio = 0.9f;
NSData* tagerImageData = scaledImageData;
NSLog(@"tagerImageData.length : %lu",(unsigned long)tagerImageData.length);
while (tagerImageData.length > stand_size && compressionRatio > 0) {
if (compressionRatio < min_compressionRatio) {
if ([_delegate respondsToSelector:@selector(CompressionPicHandle:CompressionFailureInfo:)]) {
[_delegate CompressionPicHandle:self CompressionFailureInfo:@"图片过大"];
}
}
@autoreleasepool {
NSData* newCompressionData = UIImageJPEGRepresentation(newImage, compressionRatio);
tagerImageData = newCompressionData;
}
compressionRatio = compressionRatio - 0.12;
NSLog(@"tagerImageData.length : %lu , compressionRatio : %lf",tagerImageData.length,compressionRatio);
}
NSLog(@"compressionRatio : %lf",compressionRatio);
return tagerImageData;
}
赞助