压缩图片到指定大小(单位KB)(不失真)

 #pragma mark - 压缩图片到指定大小(单位KB)

- (NSData *)resetSizeOfImageData:(UIImage *)sourceImage

                         maxSize:(NSInteger)maxSize {

 //先判断当前质量是否满足要求,不满足再进行压缩

 __block NSData *finallImageData = UIImageJPEGRepresentation(sourceImage,1.0);

 NSUInteger sizeOrigin   = finallImageData.length;

 NSUInteger sizeOriginKB = sizeOrigin / 1000;


 if (sizeOriginKB <= maxSize) {

 return finallImageData;

    }


 //获取原图片宽高比

 CGFloat sourceImageAspectRatio = sourceImage.size.width/sourceImage.size.height;

 //先调整分辨率

 CGSize defaultSize = CGSizeMake(1024, 1024/sourceImageAspectRatio);

 UIImage *newImage = [self newSizeImage:defaultSize image:sourceImage];


finallImageData = UIImageJPEGRepresentation(newImage,1.0);


 //保存压缩系数

 NSMutableArray *compressionQualityArr = [NSMutableArray array];

 CGFloat avg   = 1.0/250;

 CGFloat value = avg;

 for (int i = 250; i >= 1; i--) {

        value = i*avg;

[compressionQualityArr addObject:@(value)];

    }


 /*

     调整大小

     说明:压缩系数数组compressionQualityArr是从大到小存储。

     */

 //思路:使用二分法搜索

 __block NSData *canCompressMinData = [NSData data];//当无法压缩到指定大小时,用于存储当前能够压缩到的最小值数据。

    [self halfFuntion:compressionQualityArr image:newImage sourceData:finallImageData maxSize:maxSize resultBlock:^(NSData *finallData, NSData *tempData) {

        finallImageData = finallData;

        canCompressMinData = tempData;

    }];

 //如果还是未能压缩到指定大小,则进行降分辨率

 while (finallImageData.length == 0) {

 //每次降100分辨率

 CGFloat reduceWidth = 100.0;

 CGFloat reduceHeight = 100.0/sourceImageAspectRatio;

 if (defaultSize.width-reduceWidth <= 0 || defaultSize.height-reduceHeight <= 0) {

 break;

        }

defaultSize = CGSizeMake(defaultSize.width-reduceWidth, defaultSize.height-reduceHeight);

 UIImage *image = [self newSizeImage:defaultSize

 image:[UIImage imageWithData:UIImageJPEGRepresentation(newImage,[[compressionQualityArr lastObject] floatValue])]];

        [self halfFuntion:compressionQualityArr image:image sourceData:UIImageJPEGRepresentation(image,1.0) maxSize:maxSize resultBlock:^(NSData *finallData, NSData *tempData) {

            finallImageData = finallData;

            canCompressMinData = tempData;

        }];

    }

 //如果分辨率已经无法再降低,则直接使用能够压缩的那个最小值即可

 if (finallImageData.length==0) {

        finallImageData = canCompressMinData;

    }

 return finallImageData;

}

#pragma mark 调整图片分辨率/尺寸(等比例缩放)

///调整图片分辨率/尺寸(等比例缩放)

- (UIImage *)newSizeImage:(CGSize)size

                    image:(UIImage *)sourceImage {

 CGSize newSize = CGSizeMake(sourceImage.size.width, sourceImage.size.height);


 CGFloat tempHeight = newSize.height / size.height;

 CGFloat tempWidth = newSize.width / size.width;


 if (tempWidth > 1.0 && tempWidth > tempHeight) {

newSize = CGSizeMake(sourceImage.size.width / tempWidth, sourceImage.size.height / tempWidth);

else if (tempHeight > 1.0 && tempWidth < tempHeight) {

newSize = CGSizeMake(sourceImage.size.width / tempHeight, sourceImage.size.height / tempHeight);

    }


 //    UIGraphicsBeginImageContext(newSize);

 UIGraphicsBeginImageContextWithOptions(newSize, NO, 1);

[sourceImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

 UIGraphicsEndImageContext();

 return newImage;

}

#pragma mark 二分法

///二分法,block回调中finallData长度不为零表示最终压缩到了指定的大小,如果为零则表示压缩不到指定大小。tempData表示当前能够压缩到的最小值。

- (void)halfFuntion:(NSArray *)arr

              image:(UIImage *)image

         sourceData:(NSData *)finallImageData

            maxSize:(NSInteger)maxSize

        resultBlock:(void(^)(NSData *finallData, NSData *tempData))block {

 NSData *tempData = [NSData data];

 NSUInteger start = 0;

 NSUInteger end = arr.count - 1;

 NSUInteger index = 0;


 NSUInteger difference = NSIntegerMax;

 while(start <= end) {

        index = start + (end - start)/2;


finallImageData = UIImageJPEGRepresentation(image,[arr[index] floatValue]);


 NSUInteger sizeOrigin = finallImageData.length;

 NSUInteger sizeOriginKB = sizeOrigin / 1000;

 NSLog(@"当前降到的质量:%ld", (unsigned long)sizeOriginKB);

 //        NSLog(@"\nstart:%zd\nend:%zd\nindex:%zd\n压缩系数:%lf", start, end, (unsigned long)index, [arr[index] floatValue]);


 if (sizeOriginKB > maxSize) {

start = index + 1;

else if (sizeOriginKB < maxSize) {

 if (maxSize-sizeOriginKB < difference) {

                difference = maxSize-sizeOriginKB;

                tempData = finallImageData;

            }

 if (index<=0) {

 break;

            }

end = index - 1;

else {

 break;

        }

    }

 NSData *d = [NSData data];

 if (tempData.length==0) {

        d = finallImageData;

    }

 if (block) {

        block(tempData, d);

    }

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容