這篇文章主要介紹了iOS如何實現(xiàn)圖片壓縮、濾鏡、剪切及渲染,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:空間域名、網(wǎng)頁空間、營銷軟件、網(wǎng)站建設(shè)、治多網(wǎng)站維護、網(wǎng)站推廣。
一、圖片基礎(chǔ)知識的介紹
一張圖像是像素點的集合,每一個像素都是一個獨立,有自己的顏色。圖像一般情況下都存儲成數(shù)組,可以說是二維數(shù)組。當(dāng)成百上千萬個像素集合一起后,就構(gòu)成了圖像。表示圖形的方式很多種YUV,RGBA,最簡單的:32位RGBA模式。將一個顏色的值存儲在32位中(或4個字節(jié)) 每個字節(jié)存儲一個顏色通道(RGBA)。
二、圖片壓縮
2.1、簡單的回顧一下從相冊獲取一張圖片
<1>、說到系統(tǒng)的圖片,離不開相冊與相機,要能使真機在使用時成功調(diào)用相冊/拍照功能,那么我們需要在info.plist類里面設(shè)置兩個key:Privacy - Camera Usage Description與Privacy - Photo Library Usage Description,在測試的時候根據(jù)崩潰添加更好

相機與相冊的key
<2>、掛兩個代理:<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
<3>、定義兩個button,相冊的tag值 101,相機102,調(diào)用UIImagePickerController
#pragma mark 選擇相冊
-(void)selectImage:(UIButton *)sender{
NSInteger tag = sender.tag - 100;
NSUInteger sourceType = 0;
if (tag == 1) {
// 相冊
// 1.判斷能否打開照片庫(不支持直接返回)
if(![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}else if (tag == 2){
// 拍照
// 2.判斷支不支持相機(不支持直接返回)
if(![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) return;
sourceType = UIImagePickerControllerSourceTypeCamera;
}
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
//設(shè)置代理
imagePickerController.delegate = self;
// imagePickerController.allowsEditing = YES;
imagePickerController.sourceType = sourceType;
[self presentViewController:imagePickerController animated:YES completion:nil];
}<4>、UIImagePickerController代理方法的實現(xiàn)(暫且去掉剪輯圖片)
#pragma mark - UIImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
NSString *mediaType=[info objectForKey:UIImagePickerControllerMediaType];
// 獲取到的圖片
if ([mediaType isEqualToString:@"public.image"]) {
UIImage * image;
// 判斷,圖片是否允許修改
// if ([picker allowsEditing]){
//獲取用戶編輯之后的圖像
// image = [info objectForKey:UIImagePickerControllerEditedImage];
// } else {
// 照片的元數(shù)據(jù)參數(shù)
image = [info objectForKey:UIImagePickerControllerOriginalImage];
// }
// 壓縮圖片(處理) 看下面
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
// 當(dāng)用戶取消選擇的時候,調(diào)用該方法
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
NSLog(@"取消相冊使用 --- %s", __func__);
[self dismissViewControllerAnimated:YES completion:nil];
}<4>、 計算 NSData 的大小
#pragma mark 計算 NSData 的大小
- (NSString*)length:(NSInteger)length{
if (length > 1024 * 1024) {
int mb = (int)length/(1024*1024);
int kb = (length%(1024*1024))/1024;
return [NSString stringWithFormat:@"%dMb%dKB",mb, kb];
}else{
return [NSString stringWithFormat:@"%ldKB",length/1024];
}
}2.2、在上面我們已經(jīng)拿到圖片了,那么下面我們隊圖片的壓縮進行下處理
<1>:png 壓縮
// 壓縮圖片 NSData *dataPNG = UIImagePNGRepresentation(image); UIImage *compressPNGImage = [UIImage imageWithData:dataPNG]; NSLog(@"%@",[self length:dataPNG.length]);
提示:
這種壓縮方式會出現(xiàn)內(nèi)存飆升
文件屬性格式并不會壓縮,壓縮的是圖片內(nèi)容(像素)
<2>:jpg 壓縮
/** 第一個參數(shù):UIIMage 對象 第二個參數(shù):圖片質(zhì)量(壓縮系數(shù))0~1 之間 */ NSData *dataJPG = UIImageJPEGRepresentation(image, 0.1); UIImage *compressJPGImage = [UIImage imageWithData:dataJPG]; NSLog(@"%@",[self length:dataJPG.length]);
提示:
1.如果是通過JPEG來壓縮圖片, 圖片壓縮之后是不保真的
2.蘋果官方不推薦我們使用JPG圖片,因為現(xiàn)實JPG圖片的時候解壓縮非常消耗性能
3.這種壓縮方式雖然可以通過設(shè)置圖片質(zhì)量,但是也會出現(xiàn)內(nèi)存飆升
<3>:自定義 size 壓縮通過 上下文 來壓縮圖片
UIImage *compressImg = [self compressOriginalImage:image withImageSize:CGSizeMake(200, 200)];
NSLog(@"%@",NSStringFromCGSize(compressImg.size));
// 壓縮圖片
- (UIImage *)compressOriginalImage:(UIImage *)originalImage withImageSize:(CGSize)size{
// 開啟圖片上下文
UIGraphicsBeginImageContext(size);
// 將圖片渲染到圖片上下文
[originalImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
// 獲取圖片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// 關(guān)閉圖片上下文
UIGraphicsEndImageContext();
return newImage;
}提示:這種方式解決了內(nèi)存的飆升,算是一種好的壓縮方式
<4>:注意:一般情況下,只要涉及到從相冊中獲取圖片的功能, 都需要處理內(nèi)存,一般情況下一個應(yīng)用程序啟動會占用20M左右的內(nèi)存, 當(dāng)內(nèi)存飆升到500M左右的時候系統(tǒng)就會發(fā)送內(nèi)存警告, 此時就需要釋放內(nèi)存 , 否則就會閃退,只要內(nèi)存釋放到100M左右, 那么系統(tǒng)就不會閃退我們的應(yīng)用程序,也就是說一個應(yīng)用程序占用的內(nèi)存20~100時是比較安全的內(nèi)容范圍。
三、圖片處理
3.1、基于圖片像素修改
<1>、過濾圖片:涉及到圖片的像素處理,也是根據(jù)上下文進行操作的,進行一個繪制;從圖片文件把 圖片數(shù)據(jù)的像素拿出來(RGBA), 對像素進行操作, 進行一個轉(zhuǎn)換(Bitmap (GPU))
修改完之后,還原(圖片的屬性 RGBA,RGBA (寬度,高度,色值空間,拿到寬度和高度,每一個畫多少個像素,畫多少行))

過濾圖片
-(void)filterImage{
CGImageRef imageRef = self.imageView1.image.CGImage;
// 1 個字節(jié) = 8bit 每行有 17152 每行有17152*8 位
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
size_t bits = CGImageGetBitsPerComponent(imageRef); // 8
size_t bitsPerrow = CGImageGetBytesPerRow(imageRef); // width * bits
// 顏色空間
CGColorSpaceRef colorSpace = CGImageGetColorSpace(imageRef);
// AlphaInfo: RGBA AGBR RGB :AlphaInfo 信息
CGImageAlphaInfo alpInfo = CGImageGetAlphaInfo(imageRef);
// bitmap的數(shù)據(jù)
CGDataProviderRef providerRef = CGImageGetDataProvider(imageRef);
CFDataRef bitmapData = CGDataProviderCopyData(providerRef);
NSInteger pixLength = CFDataGetLength(bitmapData);
// 像素byte數(shù)組
Byte *pixbuf = CFDataGetMutableBytePtr((CFMutableDataRef)bitmapData);
// RGBA 為一個單元
for (int i = 0; i < pixLength; i+=4) {
[self eocImageFiletPixBuf:pixbuf offset:i];
}
// 準(zhǔn)備繪制圖片了
// bitmap 生成一個上下文 再通過上下文生成圖片
CGContextRef contextR = CGBitmapContextCreate(pixbuf, width, height, bits, bitsPerrow, colorSpace, alpInfo);
CGImageRef filterImageRef = CGBitmapContextCreateImage(contextR);
UIImage *filterImage = [UIImage imageWithCGImage:filterImageRef];
self.imageView1.image = filterImage;
}
// RGBA 為一個單元 彩色照變黑白照
- (void)eocImageFiletPixBuf:(Byte*)pixBuf offset:(int)offset{
int offsetR = offset;
int offsetG = offset + 1;
int offsetB = offset + 2;
// int offsetA = offset + 3;
int red = pixBuf[offsetR];
int gre = pixBuf[offsetG];
int blu = pixBuf[offsetB];
// int alp = pixBuf[offsetA];
int gray = (red + gre + blu)/3;
pixBuf[offsetR] = gray;
pixBuf[offsetG] = gray;
pixBuf[offsetB] = gray;
}<2>、還原圖片:這個其實沒什么講的,只要把過濾前的圖片的UIIMage進行保存,再次賦值就好
3.2、圖片剪切clip

圖片剪切clip
<1>、規(guī)則圖片剪切(圓形,矩形等)
#pragma mark 剪切圖片(規(guī)則的剪切圖)
-(void)clipImage{
CGSize size = CGSizeMake(100, 100);
// 開啟上下文
UIGraphicsBeginImageContext(size);
// 獲取當(dāng)前的上下文
CGContextRef context = UIGraphicsGetCurrentContext();
// 設(shè)置路徑剪切(設(shè)置一個圓)
CGRect rect = CGRectMake(0, 0, size.width, size.height);
CGContextAddEllipseInRect(context, rect);
CGContextClip(context);
// 把圖片繪制上去
[self.oriImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// 把剪切過的圖片展示出來
self.imageView2.image = clipImage;
}<2>、不規(guī)則圖片剪切(根據(jù)自定義path剪切)
#pragma mark 剪切圖片(不規(guī)則的剪切圖)
-(void)irRegularclipImage{
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
CGContextRef context = UIGraphicsGetCurrentContext();
// 非規(guī)則的path
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPoint lines[] = {
CGPointMake(50,0),
CGPointMake(100,0),
CGPointMake(150,80),
CGPointMake(0,80),
CGPointMake(50,0)
};
CGPathAddLines(pathRef, NULL, lines, 5);
CGContextAddPath(context, pathRef);
CGContextClip(context);
[self.oriImage drawInRect:CGRectMake(0, 0, 200, 200)];
UIImage *clipImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// 把剪切過的圖片展示出來
self.imageView3.image = clipImage;
}3.3、圖片渲染
#pragma mark 在圖片上渲染一層半透明的紅色
-(void)blend{
// 原圖的大小
CGSize size = CGSizeMake(self.imageView1.frame.size.width, self.imageView1.frame.size.height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.oriImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
// 設(shè)置半透明紅色的渲染
UIColor *redColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.5];
CGContextSetFillColorWithColor(context, redColor.CGColor);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
// 獲取渲染的CGImageRef
CGImageRef imageRef = CGBitmapContextCreateImage(context);
self.imageView1.image = [UIImage imageWithCGImage:imageRef];
UIGraphicsEndImageContext();
}3.4、截屏(截取一個對象上的所有視圖),我們以截取self.view的視圖為例

截屏**(截取一個對象上的所有視圖),我們以截取self.view的視圖為例
<1>、截屏方式一
- (UIImage *)jk_snapshotImage {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0);
[self.view drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}<2>、截屏方式一
- (UIImage *)imageFromFullView{
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
UIGraphicsEndImageContext();
return newImage;
}感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“iOS如何實現(xiàn)圖片壓縮、濾鏡、剪切及渲染”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
分享名稱:iOS如何實現(xiàn)圖片壓縮、濾鏡、剪切及渲染
網(wǎng)頁地址:http://www.chinadenli.net/article34/gichpe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、軟件開發(fā)、、網(wǎng)站維護、微信公眾號、網(wǎng)站設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)