對圖片壓縮這一塊之前也沒具體研究過翔脱,因?yàn)轫?xiàng)目中要處理用戶發(fā)布的圖片磁滚,所以Google了一下這個問題...
第一部分是圖片尺寸的壓縮
在網(wǎng)上搜索一番育韩,發(fā)現(xiàn)一篇不錯的文章討論了微信的圖片尺寸轉(zhuǎn)換規(guī)則,微信縮小尺寸基本上是圍繞1280的pixel來展開的蛇更,還有些文章也提到了pixel最好是8的倍數(shù)之類的內(nèi)容瞻赶,很巧的是1280正好也符合這個要求。
總結(jié)之后的規(guī)則是這樣的:
a派任,圖片寬或者高均小于或等于1280時圖片尺寸保持不變砸逊,不改變圖片大小
b,寬或者高大于1280,但是圖片寬度高度比小于或等于2掌逛,則將圖片寬或者高取值大的等比壓縮至1280
c师逸,寬或者高均大于1280,但是圖片寬高比大于2豆混,則寬或者高取值小的等比壓縮至1280
**d, **寬或者高篓像,只有一個值大于1280,并且寬高比超過2皿伺,不改變圖片大小
那么接下來就簡單了员辩,按照規(guī)則以下是代碼部分
private func resizeImage(originalImg:UIImage) -> UIImage{
//prepare constants
let width = originalImg.size.width
let height = originalImg.size.height
let scale = width/height
var sizeChange = CGSize()
if width <= 1280 && height <= 1280{ //a,圖片寬或者高均小于或等于1280時圖片尺寸保持不變心傀,不改變圖片大小
return originalImg
}else if width > 1280 || height > 1280 {//b,寬或者高大于1280屈暗,但是圖片寬度高度比小于或等于2拆讯,則將圖片寬或者高取大的等比壓縮至1280
if scale <= 2 && scale >= 1 {
let changedWidth:CGFloat = 1280
let changedheight:CGFloat = changedWidth / scale
sizeChange = CGSize(width: changedWidth, height: changedheight)
}else if scale >= 0.5 && scale <= 1 {
let changedheight:CGFloat = 1280
let changedWidth:CGFloat = changedheight * scale
sizeChange = CGSize(width: changedWidth, height: changedheight)
}else if width > 1280 && height > 1280 {//寬以及高均大于1280脂男,但是圖片寬高比大于2時,則寬或者高取小的等比壓縮至1280
if scale > 2 {//高的值比較小
let changedheight:CGFloat = 1280
let changedWidth:CGFloat = changedheight * scale
sizeChange = CGSize(width: changedWidth, height: changedheight)
}else if scale < 0.5{//寬的值比較小
let changedWidth:CGFloat = 1280
let changedheight:CGFloat = changedWidth / scale
sizeChange = CGSize(width: changedWidth, height: changedheight)
}
}else {//d, 寬或者高种呐,只有一個大于1280宰翅,并且寬高比超過2,不改變圖片大小
return originalImg
}
}
UIGraphicsBeginImageContext(sizeChange)
//draw resized image on Context
originalImg.drawInRect(CGRectMake(0, 0, sizeChange.width, sizeChange.height))
//create UIImage
let resizedImg = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImg
}
感覺上寫得有些啰嗦爽室,以后再修改吧汁讼,打印了一下轉(zhuǎn)換后的大小,效果也是挺好的阔墩,打印結(jié)果如下:
第二步就是文件大小的再壓縮
因?yàn)橄Mw的壓縮大小控制在100-200k左右嘿架,這個沒有網(wǎng)上細(xì)查,所以自己亂寫了一個簡單的處理算法啸箫,如下:
//圖片壓縮 1000kb以下的圖片控制在100kb-200kb之間
func compressImageSize(image:UIImage) -> NSData{
if originalImgSize>1500 {
zipImageData = UIImageJPEGRepresentation(image,0.1)!
}else if originalImgSize>600 {
zipImageData = UIImageJPEGRepresentation(image,0.2)!
}else if originalImgSize>400 {
zipImageData = UIImageJPEGRepresentation(image,0.3)!
}else if originalImgSize>300 {
zipImageData = UIImageJPEGRepresentation(image,0.4)!
}else if originalImgSize>200 {
zipImageData = UIImageJPEGRepresentation(image,0.5)!
}
return zipImageData
}
尾聲
經(jīng)過圖片尺寸與質(zhì)量的雙重壓縮后耸彪,上傳到服務(wù)器的圖片的體積已經(jīng)比較小了,特別用手機(jī)拍攝的高清圖片忘苛,下一步的話可以根據(jù)項(xiàng)目的要求做一些縮略圖蝉娜,也可以交給服務(wù)器端的人處理唱较。
最后附上github鏈接.
后記
因?yàn)轫?xiàng)目需要,我又添加了一個水印在圖片上召川,google一下代碼也很簡單南缓,其中使用
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
時發(fā)現(xiàn)一個問題,當(dāng)同樣大小的情況下畫一次圖像后荧呐,圖片會變大很多, 特別是大圖汉形,比如一個5m的圖片會增大到40m左右,所以如果想保持圖片體積不變的話倍阐,應(yīng)該使用
UIGraphicsBeginImageContextWithOptions(size, NO, 1);
或者
UIGraphicsBeginImageContext(size)
具體的原理可以參見apple的文檔, 雖然很努力地看了获雕,但是沒看懂,如果沒看懂那就是因?yàn)椴粔蚺κ盏罚詺w正傳届案,文中提到了,影響圖像尺寸的值:Scale Factor比例系數(shù)罢艾,也就是長與寬的比楣颠,設(shè)1才是原始的比例圖像,設(shè)成0就變成屏幕的比例圖像咐蚯,根據(jù)屏幕的ScaleFactor的定義
For standard-resolution displays, the scale factor is 1.0
and one point equals one pixel. For Retina displays, the scale factor is 2.0
and one point is represented by four pixels.
所以圖片變大了童漩。
PS:壓縮過的圖像,NSData的大小不等于UIImage的大小春锋,而png格式的圖片比同質(zhì)量同分辨率的jpg和jpeg格式圖片大數(shù)倍矫膨。