iOS 下利用 CGContextRef 簡單實現多圖拼接功能

語言: CN / TW / HK

廢話開篇:簡單實現多張小圖拼接為一張長整圖的功能。

相關文章: iOS 下實現本地影片自選幀檢視多圖拼接工具類

一、需要實現的功能

將這三張 酆都大帝 拼接成下面的一張整圖

image.png

最終要儲存的圖

image.png

酆都大帝.jpg

二、合併功能操作程式碼

在控制器裡進行多圖的拼接操作,

```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.png

四、總結與思考

上述實現原理比較簡單。除此之外,如果是要某張小圖的某一部分或者對圖片整體畫素處理,那麼,就需要對圖片進行畫素操作了。個人理解,通過 image.CGImage 可以獲得圖片的很多資訊資料,圖片格式、圖片寬高、三色素值等具體的資訊,只要最後修改的檔案符合圖片格式,那麼,其他的操作就都是二進位制資料的修改與拼接。

程式碼拙劣,大神勿笑,互相討論,共同進步[抱拳][抱拳][抱拳]。