iOS 下利用 CGContextRef 简单实现多图拼接功能

👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇

废话开篇:简单实现多张小图拼接为一张长整图的功能。

一、需要实现的功能

将这三张 酆都大帝 拼接成下面的一张整图

outside_default.png

最终要保存的图

outside_default.png outside_default.png
酆都大帝.jpg

二、合并功能操作代码

在控制器里进行多图的拼接操作,

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)以最大图片为准,居中排列。

//同时获取图片组最大宽度及拼接高度
+ (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 上下文中

在绘制前,可以先设置上下的填充颜色。

//设置大图上下文背景填充颜色(这里是黑色)
  CGContextSetFillColorWithColor(contextRef, [UIColor blackColor].CGColor);
  //设置大图上下文背景填充区域(全部区域)
  CGContextFillRect(contextRef, CGRectMake(0, 0, imageWidth, imageHeight));
复制代码

其次,进行循环绘制,直接放完整代码

+ (void)combineImages:(NSArray *)images callBack:(void(^)(UIImage * resultImage))callBack
{
    //获取拼接后图片的高度及最大宽度
    [self getAllImagesMaxWidthAndTotleHeight:images callBack:^(NSUInteger imageWidth, NSUInteger imageHeight) {
        //创建颜色空间
        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
        //开辟像素区域
        UInt32 *imagePiexl = (UInt32 *)calloc(imageWidth*imageHeight, 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、保存图片到沙盒

实现图片保存到沙盒的功能

//保存到沙盒
+ (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电脑 “前往文件夹”下输入此路径就能找到模拟器下的对应沙盒文件。

outside_default.png

四、总结与思考

上述实现原理比较简单。除此之外,如果是要某张小图的某一部分或者对图片整体像素处理,那么,就需要对图片进行像素操作了。个人理解,通过 image.CGImage 可以获得图片的很多信息数据,图片格式、图片宽高、三色素值等具体的信息,只要最后修改的文件符合图片格式,那么,其他的操作就都是二进制数据的修改与拼接。

代码拙劣,大神勿笑,互相讨论,共同进步[抱拳][抱拳][抱拳]。

转自:掘金-头痛脑胀的代码……

链接:https://juejin.cn/post/7048895249128620069

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

47265c69c4b6ad7aa0b4d382c7533004.png

点击👆卡片,关注后回复【面试题】即可获取

在看点这里75b614c72633e7cae8fb09beded74993.gif好文分享给更多人↓↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在iOS开发中获取图片中二维码的定位,可以使用CoreImage框架。具体步骤如下: 1. 使用CIImage加载图片: ``` CIImage *image = [CIImage imageWithCGImage:image.CGImage]; ``` 2. 创建CIDetector并设置识别类型: ``` CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}]; ``` 3. 识别二维码: ``` NSArray *features = [detector featuresInImage:image]; ``` 4. 遍历识别结果,获取二维码定位: ``` for (CIQRCodeFeature *feature in features) { NSArray *corners = feature.corners; // 获取定位四个角的坐标 // 在图像上绘制定位 UIGraphicsBeginImageContext(imageSize); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor); CGContextSetLineWidth(context, 2.0); CGContextMoveToPoint(context, corners[0].x, corners[0].y); CGContextAddLineToPoint(context, corners[1].x, corners[1].y); CGContextAddLineToPoint(context, corners[2].x, corners[2].y); CGContextAddLineToPoint(context, corners[3].x, corners[3].y); CGContextAddLineToPoint(context, corners[0].x, corners[0].y); CGContextStrokePath(context); UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); } ``` 这样就可以在原图上绘制出二维码的定位了。需要注意的是,CIDetector只能识别二维码,如果要识别其他类型的码,需要设置不同的detector类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值