麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 系統(tǒng) > iOS > 正文

iOS實現(xiàn)高效裁剪圖片圓角算法教程

2019-10-21 18:40:59
字體:
供稿:網(wǎng)友

前言

項目有個需求:裁剪圖片,針對頭像,下面是要求:

 iOS,裁剪圖片,圓角算法

大家可以看到這張圖片的圓角已經(jīng)去除,下面說說我在項目利用了兩種方式實現(xiàn)此裁剪以及查看技術(shù)文檔發(fā)現(xiàn)更高效裁剪方式,下面一一講解:看下來大約需要15-20分鐘。

在公共類中Util類中創(chuàng)建類方法

1.CGContext裁剪

//CGContext裁剪+ (UIImage *)CGContextClip:(UIImage *)img cornerRadius:(CGFloat)c;

實現(xiàn)該方法:

// CGContext 裁剪+ (UIImage *)CGContextClip:(UIImage *)img cornerRadius:(CGFloat)c{ int w = img.size.width * img.scale; int h = img.size.height * img.scale; UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), false, 1.0); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextMoveToPoint(context, 0, c); CGContextAddArcToPoint(context, 0, 0, c, 0, c); CGContextAddLineToPoint(context, w-c, 0); CGContextAddArcToPoint(context, w, 0, w, c, c); CGContextAddLineToPoint(context, w, h-c); CGContextAddArcToPoint(context, w, h, w-c, h, c); CGContextAddLineToPoint(context, c, h); CGContextAddArcToPoint(context, 0, h, 0, h-c, c); CGContextAddLineToPoint(context, 0, c); CGContextClosePath(context);  // 先裁剪 context,再畫圖,就會在裁剪后的 path 中畫 CGContextClip(context); [img drawInRect:CGRectMake(0, 0, w, h)]; // 畫圖 CGContextDrawPath(context, kCGPathFill); UIImage *ret = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();  return ret;}

在該需要的地方調(diào)用如下:

[Util CGContextClip:image cornerRadius:radius];

2.UIBezierPath 裁剪

在Util.h類中聲明

//UIBezierPath 裁剪+ (UIImage *)UIBezierPathClip:(UIImage *)img cornerRadius:(CGFloat)c;

在Util.m實現(xiàn)方法

//UIBezierPath 裁剪+ (UIImage *)UIBezierPathClip:(UIImage *)img cornerRadius:(CGFloat)c{ int w = img.size.width * img.scale; int h = img.size.height * img.scale; CGRect rect = CGRectMake(0, 0, w, h); UIGraphicsBeginImageContextWithOptions(CGSizeMake(w, h), false, 1.0); [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:c] addClip]; [img drawInRect:rect];  UIImage *ret = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return ret;}

3.空域處理的辦法,寫個裁剪圓角的算法

對于圖像上的一個點(x, y),判斷其在不在圓角矩形內(nèi),在的話 alpha 是原值,不在的話 alpha 設(shè)為 0 即可

iOS,裁剪圖片,圓角算法

遍歷所有像素,判斷每個像素在不在4個圓的圓內(nèi)就行了,4個角,每個角有一個四分之一的圓。

一個優(yōu)化就是,我不需要遍歷全部的像素就能裁出圓角,只需要考慮類似左下角三角形的區(qū)域就行了,左下,左上,右上,右下,一共4個三角形區(qū)域(另外3個圖中沒畫出),for循環(huán)的時候,就循環(huán)這個4個三角形區(qū)域就行了。

所以對于一幅 w * h 的圖像,設(shè)圓角大小為 n,n <= min(w, h) / 2,其復(fù)雜度為 O(n) = 2(n^2),最壞的情況計算量也不會超過 wh / 2。

對于一個像素點(x, y),判斷其在不在圓內(nèi)的公式:
如果  (x-cx)^2 + (y-cy)^2 <= r^2  就表示點 (x, y) 在圓內(nèi),反之不在。通過測試:此算法效率可以提高幾倍之上(時間)

在Util.h中聲明:

+ (UIImage *)dealImage:(UIImage *)img cornerRadius:(CGFloat)c

在Util.m中實現(xiàn):

+ (UIImage *)dealImage:(UIImage *)img cornerRadius:(CGFloat)c { // 1.CGDataProviderRef 把 CGImage 轉(zhuǎn) 二進制流 CGDataProviderRef provider = CGImageGetDataProvider(img.CGImage); void *imgData = (void *)CFDataGetBytePtr(CGDataProviderCopyData(provider)); int width = img.size.width * img.scale; int height = img.size.height * img.scale;  // 2.處理 imgData// dealImage(imgData, width, height); cornerImage(imgData, width, height, c);  // 3.CGDataProviderRef 把 二進制流 轉(zhuǎn) CGImage CGDataProviderRef pv = CGDataProviderCreateWithData(NULL, imgData, width * height * 4, releaseData); CGImageRef content = CGImageCreate(width , height, 8, 32, 4 * width, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, pv, NULL, true, kCGRenderingIntentDefault); UIImage *result = [UIImage imageWithCGImage:content]; CGDataProviderRelease(pv); // 釋放空間 CGImageRelease(content);  return result;}void releaseData(void *info, const void *data, size_t size) { free((void *)data);}// 在 img 上處理圖片, 測試用void dealImage(UInt32 *img, int w, int h) { int num = w * h; UInt32 *cur = img; for (int i=0; i<num; i++, cur++) { UInt8 *p = (UInt8 *)cur; // RGBA 排列 // f(x) = 255 - g(x) 求負片 p[0] = 255 - p[0]; p[1] = 255 - p[1]; p[2] = 255 - p[2]; p[3] = 255; }}// 裁剪圓角void cornerImage(UInt32 *const img, int w, int h, CGFloat cornerRadius) { CGFloat c = cornerRadius; CGFloat min = w > h ? h : w;  if (c < 0) { c = 0; } if (c > min * 0.5) { c = min * 0.5; }  // 左上 y:[0, c), x:[x, c-y) for (int y=0; y<c; y++) { for (int x=0; x<c-y; x++) {  UInt32 *p = img + y * w + x; // p 32位指針,RGBA排列,各8位  if (isCircle(c, c, c, x, y) == false) {  *p = 0;  } } } // 右上 y:[0, c), x:[w-c+y, w) int tmp = w-c; for (int y=0; y<c; y++) { for (int x=tmp+y; x<w; x++) {  UInt32 *p = img + y * w + x;  if (isCircle(w-c, c, c, x, y) == false) {  *p = 0;  } } } // 左下 y:[h-c, h), x:[0, y-h+c) tmp = h-c; for (int y=h-c; y<h; y++) { for (int x=0; x<y-tmp; x++) {  UInt32 *p = img + y * w + x;  if (isCircle(c, h-c, c, x, y) == false) {  *p = 0;  } } } // 右下 y~[h-c, h), x~[w-c+h-y, w) tmp = w-c+h; for (int y=h-c; y<h; y++) { for (int x=tmp-y; x<w; x++) {  UInt32 *p = img + y * w + x;  if (isCircle(w-c, h-c, c, x, y) == false) {  *p = 0;  } } }}// 判斷點 (px, py) 在不在圓心 (cx, cy) 半徑 r 的圓內(nèi)static inline bool isCircle(float cx, float cy, float r, float px, float py) { if ((px-cx) * (px-cx) + (py-cy) * (py-cy) > r * r) { return false; } return true;}// 其他圖像效果可以自己寫函數(shù),然后在 dealImage: 中調(diào)用 otherImage 即可void otherImage(UInt32 *const img, int w, int h) { // 自定義處理}

上面是三種方式,可以解決圖片裁剪的需求,

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識閱讀請移步到IOS開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 性欧美xxxx免费岛国不卡电影 | 天天夜干| 国产午夜精品一区二区三区在线观看 | 日韩视频中文 | 黄片毛片一级 | 久久逼逼| 久久99国产精品久久99 | 一区二区三区欧美在线观看 | 日日摸夜夜骑 | 久久精品日产第一区二区三区 | 欧美一级在线免费 | 亚洲精品一区二区三区在线看 | 成人在线观看免费视频 | 99精品国产一区二区三区 | 黑人三级毛片 | 久久久久久久爱 | 亚洲日韩精品欧美一区二区 | 国产毛片在线高清视频 | 色欧美视频 | 久久精品亚洲欧美日韩精品中文字幕 | 最新久久免费视频 | 国产精品啪一品二区三区粉嫩 | 色中色在线播放 | 毛片大全在线观看 | 欧美成在人线a免费 | 看免费毛片 | 国产精品一区在线观看 | 国产一区日韩精品 | 久久久久久久久久久久久九 | 韩国一大片a毛片 | 欧美性生交zzzzzxxxxx | 国产午夜精品理论片a级探花 | 日日碰日日操 | 免费午夜视频在线观看 | 亚洲人成综合第一网 | sm高h视频| 国产免费一区二区三区最新不卡 | 激情小说激情图片激情电影 | 中文字幕亚洲一区二区三区 | 91,视频免费看 | 影视免费观看 |