iOS图片处理2---CGImageRef实例

幽灵图的实例注释

该方法:传入一个图片,返回一个添加了幽灵图片的新图。
- (UIImage )processUsingPixels:(UIImage)inputImage {

    UInt32 * inputPixels; // 一个指针
 /* 
     1、图片先转成位图,等待添加新图片
 */
    CGImageRef inputCGImage = [inputImage CGImage];
    NSUInteger inputWidth = CGImageGetWidth(inputCGImage);
    NSUInteger inputHeight = CGImageGetHeight(inputCGImage);
    // @1 颜色空间
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    NSUInteger bytesPerPixel = 4;
    NSUInteger bitsPerComponent = 8;
    NSUInteger inputBytesPerRow = bytesPerPixel*inputWidth;
    inputPixels = (UInt32 *)calloc(inputWidth * inputHeight, sizeof(UInt32));
    // @2 位图内容
    CGContextRef context = CGBitmapContextCreate(inputPixels, inputWidth, inputHeight,
                                        bitsPerComponent, inputBytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGContextDrawImage(context, CGRectMake(0, 0, inputWidth, inputHeight), inputCGImage);

     /* 
     2、将幽灵图,(提前计算好需要缩放成的大小)转换成位图
   */
    
    UIImage * ghostImage = [UIImage imageNamed:@"ghost"];
    CGImageRef ghostCGImage = [ghostImage CGImage];
    CGFloat ghostImageAspectRatio = ghostImage.size.width / ghostImage.size.height;
    NSInteger targetGhostWidth = inputWidth * 0.25;

    CGSize ghostSize = CGSizeMake(targetGhostWidth, targetGhostWidth / ghostImageAspectRatio);
    CGPoint ghostOrigin = CGPointMake(inputWidth * 0.5, inputHeight * 0.2);
    NSUInteger ghostBytesPerRow = bytesPerPixel * ghostSize.width;
    UInt32 * ghostPixels = (UInt32 *)calloc(ghostSize.width * ghostSize.height, sizeof(UInt32));
    CGContextRef ghostContext = CGBitmapContextCreate(ghostPixels, ghostSize.width, ghostSize.height,
                                                  bitsPerComponent, ghostBytesPerRow, colorSpace,
                                                  kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

    CGContextDrawImage(ghostContext, CGRectMake(0, 0, ghostSize.width, ghostSize.height),ghostCGImage);

   /* 
     3、ghost图片在背景图上的起始点像素位置(依照背景图)
   */
    NSUInteger offsetPixelCountForInput = ghostOrigin.y * inputWidth + ghostOrigin.x;
    UInt32 count = 0;
    NSLog(@"%f,%f",ghostSize.width,ghostSize.height);
   /* 
     4、添加(重点!!!!!)
   */
    // 循环遍历整个背景图
    for (NSUInteger j = 0; j < ghostSize.height; j++) {
        for (NSUInteger i = 0; i < ghostSize.width+1; i++) {
        
//          // 新建指针,在ghostSize的位置上,指针指向相对于背景图的ghostSize的位置
            UInt32 * inputPixel = inputPixels + j * inputWidth + i + offsetPixelCountForInput;
            // 获取到背景图上该点的像素值
            UInt32 inputColor = *inputPixel;
        
        
            count++;
//         NSLog(@"%d * %d + %d + %d -1  = %u",i,j,i,j,(unsigned int)count);
            // 新建指针,获取到幽灵图上的对应位置,并指向!
            UInt32 * ghostPixel = ghostPixels + j * (int)ghostSize.width + i;
            // 获取到幽灵图上该点的像素值
            UInt32 ghostColor = 0;
//                NSLog(@"%x",*ghostPixel);
            if (*ghostPixel > 0) {
            
                ghostColor = *ghostPixel;
//              NSLog(@"%x",(unsigned int)ghostColor);
            }
        
        
            // 两个像素值进行合并。
                /*
         每一个颜色都有一个透明通道来标识透明度。并且,你每创建一张图像,每一个像素都会有一个颜色值。
         所以,如果遇到有透明度和半透明的颜色值该如何处理呢?
         答案是,对透明度进行混合。在最顶层的颜色会使用一个公式与它后面的颜色进行混合。公式如下:
         
         NewColor = TopColor * TopColor.Alpha + BottomColor * (1 - TopColor.Alpha)
         当顶层透明度为1时,新的颜色值等于顶层颜色值。
         当顶层透明度为0时,新的颜色值于底层颜色值。
         最后,当顶层的透明度值是0到1之前的时候,新的颜色值会混合借于顶层和底层颜色值之间。
         
         还可以用 premultiplied alpha的方法。

             */
            // 将幽灵图像的每一个像素的透明通道都乘以了0.5,使它成为半透明状态。然后将它混合到图像中
            CGFloat ghostAlpha = 0.5f * (A(ghostColor) / 255.0);
            UInt32 newR = R(inputColor) * (1 - ghostAlpha) + R(ghostColor) * ghostAlpha;
            UInt32 newG = G(inputColor) * (1 - ghostAlpha) + G(ghostColor) * ghostAlpha;
            UInt32 newB = B(inputColor) * (1 - ghostAlpha) + B(ghostColor) * ghostAlpha;
        
            // 将每个颜色的值范围进行限定到0到255之间,以防越界。
            newR = MAX(0,MIN(255, newR));
            newG = MAX(0,MIN(255, newG));
            newB = MAX(0,MIN(255, newB));
        
            // 像素拼接,设置ghostSize位置上的新像素
             *inputPixel = RGBAMake(newR, newG, newB, A(inputColor));
//            inputPixel = NULL;
//            ghostPixel = NULL;
        }
    }


    CGImageRef newCGImage = CGBitmapContextCreateImage(context);
    UIImage * processedImage = [UIImage imageWithCGImage:newCGImage];

    // 5. Cleanup!
    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);
    CGContextRelease(ghostContext);
    CGImageRelease(newCGImage);
    free(inputPixels);
    free(ghostPixels);
    return processedImage;

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,800评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 175,901评论 25 709
  • 看完《温州一家人》这本小说,感触颇深,对温州人更加由衷的佩服,也许他们骨子里就流淌着经商的血液。就如同书封...
    冷冷123456阅读 9,601评论 0 3
  • 又是一年秋收季,又是一年开学季。于是想到了校园、想到了未曾谋面的可爱孩子们,心中有期待、有压力、有畅想、有...
    唯美儿阅读 3,690评论 0 2
  • 开源2d游戏引擎,由cocos2d-objc演化而来的纯swift版本,Fiber2D开源地址:https://g...
    工匠良辰阅读 3,222评论 0 0