iOS 下利用 CGContextRef 簡單實現多圖拼接功能
廢話開篇:簡單實現多張小圖拼接為一張長整圖的功能。
一、需要實現的功能
將這三張 酆都大帝 拼接成下面的一張整圖
最終要儲存的圖
二、合併功能操作程式碼
在控制器裡進行多圖的拼接操作,
```OC UIImage * image1 = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"fd1" ofType:@"jpeg"]];
UIImage * image2 = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"fd2" ofType:@"jpeg"]];
UIImage * image3 = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"fd3" ofType:@"jpeg"]];
self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.scrollView];
//合併小圖 [WSLImageCombineOperation combineImages:@[image1,image2,image3] callBack:^(UIImage * _Nonnull resultImage) {
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.scrollView.frame.size.height * resultImage.size.width / resultImage.size.height,self.scrollView.frame.size.height)];
imageView.image = resultImage;
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.scrollView addSubview:imageView];
self.scrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height); //儲存到沙盒 [WSLImageCombineOperation saveImageToCache:resultImage];
}]; ```
三、WSLImageCombineOperation 類,實現圖合併功能
其實這裡主要的是利用 CGContextRef 上下文進行的繪製。在開闢上下文後,在上下文裡面進行多圖的繪製,最後將上下文內容轉為 image 進行展示與儲存。
在開闢上下文的之前,需要做幾件事:
1、建立 CGContextRef 上下文。
建立上下文之前,需要計算多張圖上下依次拼接的最大高度及圖組中最寬的一張圖片寬度。
保證上下文滿足兩個條件:
(1)足夠的高度。
(2)以最大圖片為準,居中排列。
```OC //同時獲取圖片組最大寬度及拼接高度 + (void)getAllImagesMaxWidthAndTotleHeight:(NSArray *)images callBack:(void(^)(NSUInteger maxWith,NSUInteger totleHeight))callBack { CGFloat maxWidth = 0; CGFloat allImageHeight = 0; for (UIImage * image in images) { CGFloat currentImageWidth = [self imageWidth:image]; maxWidth = maxWidth < currentImageWidth ? currentImageWidth : maxWidth; allImageHeight += [self imageHeight:image]; } callBack(maxWidth,allImageHeight); }
//獲取圖片寬度 + (CGFloat)imageWidth:(UIImage *)image { return image.size.width; }
//獲取圖片高度 + (CGFloat)imageHeight:(UIImage *)image { return image.size.height; } ```
2、繪製內容到 CGContextRef 上下文中
在繪製前,可以先設定上下的填充顏色。
OC
//設定大圖上下文背景填充顏色(這裡是黑色)
CGContextSetFillColorWithColor(contextRef, [UIColor blackColor].CGColor);
//設定大圖上下文背景填充區域(全部區域)
CGContextFillRect(contextRef, CGRectMake(0, 0, imageWidth, imageHeight));
其次,進行迴圈繪製,直接放完整程式碼
```OC + (void)combineImages:(NSArray )images callBack:(void(^)(UIImage * resultImage))callBack { //獲取拼接後圖片的高度及最大寬度 [self getAllImagesMaxWidthAndTotleHeight:images callBack:^(NSUInteger imageWidth, NSUInteger imageHeight) { //建立顏色空間 CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); //開闢畫素區域 UInt32 imagePiexl = (UInt32 )calloc(imageWidthimageHeight, sizeof(UInt32)); //建立上下文 CGContextRef contextRef = CGBitmapContextCreate(imagePiexl, imageWidth, imageHeight, 8, 4*imageWidth, colorSpaceRef, kCGImageAlphaNoneSkipLast);
//設定大圖上下文背景填充顏色(這裡是黑色) CGContextSetFillColorWithColor(contextRef, [UIColor blackColor].CGColor); //設定大圖上下文背景填充區域(全部區域) CGContextFillRect(contextRef, CGRectMake(0, 0, imageWidth, imageHeight)); //拼接圖片 X 值 NSUInteger imageX = 0; //拼接圖片 Y 值 NSUInteger imageY = 0 //迴圈遍歷進行繪製 for (UIImage * image in images) {
//迴圈繪製 CGImageRef imageRef = image.CGImage; NSUInteger width = CGImageGetWidth(imageRef); NSUInteger height = CGImageGetHeight(imageRef);//謝謝[可愛親寶寶]的糾正 imageX = (imageWidth - width) / 2.0; CGContextDrawImage(contextRef, CGRectMake(imageX, imageY, width, height), imageRef); //重新計算 Y 值 imageY += height; }
//生成圖片,供外部 UIImageView 渲染 CGImageRef resultRef = CGBitmapContextCreateImage(contextRef); UIImage * resultImage = [UIImage imageWithCGImage:resultRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]; callBack(resultImage);
//釋放用過的記憶體 CGContextRelease(contextRef); CGColorSpaceRelease(colorSpaceRef); free(imagePiexl); CGImageRelease(resultRef); }];
} ```
3、儲存圖片到沙盒
實現圖片儲存到沙盒的功能
OC
//儲存到沙盒
+ (BOOL)saveImageToCache:(UIImage *)image
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"酆都大帝.jpg"];
NSLog(@"filePath = %@",filePath);
BOOL result = [UIImagePNGRepresentation(image) writeToFile: filePath atomically:YES];
return result;
}
這裡列印 filePath 快取路徑,複製出來,直接在 MAC電腦 “前往資料夾”下輸入此路徑就能找到模擬器下的對應沙盒檔案。
四、總結與思考
上述實現原理比較簡單。除此之外,如果是要某張小圖的某一部分或者對圖片整體畫素處理,那麼,就需要對圖片進行畫素操作了。個人理解,通過 image.CGImage 可以獲得圖片的很多資訊資料,圖片格式、圖片寬高、三色素值等具體的資訊,只要最後修改的檔案符合圖片格式,那麼,其他的操作就都是二進位制資料的修改與拼接。
程式碼拙劣,大神勿笑,互相討論,共同進步[抱拳][抱拳][抱拳]。
- Flutter 利用SmartRefresher實現下拉重新整理和上拉載入功能
- iOS 模擬充電動畫
- iOS 端 uniAPP 原生外掛打包流程
- iOS 基於 uniapp 原生元件開發,原生部分如何處理Vue頁面跳轉。
- iOS 實現刮刮樂
- iOS 下利用 CGContextRef 簡單實現多圖拼接功能
- iOS 簡單封裝一個新使用者功能模組引導工具類小玩兒意
- iOS 封裝一個仿 RxDriver 簡易 UITableView 資料來源驅動繫結功能思路與實現
- iOS 簡單封裝 UITableView 鏈式監聽點選事件下 Dispose 和 DisposeBag
- iOS 封裝一個簡易 UITableView 鏈式監聽點選事件的功能思路與實現
- iOS 簡單模擬伺服器如何解析客戶端傳來的表單資料及圖片格式資料並本地儲存
- iOS 簡單模擬 https 證書信任邏輯
- MAC 本地搭建推流環境、推流及實現 iOS demo 拉流瀏覽
- iOS 下關於指標指向及指標偏移的理解
- iOS 用UIView 封裝一個簡單的富文字展示 CoreTextView 類
- iOS 下的讀寫鎖的簡單實現
- iOS 關於block 、__weak、 __strong 物件引用計數的思考
- iOS UIViewController 跟 NSTimer 無法釋放真的是迴圈引用導致的嗎?
- 超簡單的Three.js 卡車跑跑demo
- 歌頌祖國