iOS - CoreImage - Add an effect to partial of image

梦想的初衷 提交于 2019-12-05 11:32:01
Felix

Watch session 510 from the WWDC 2012 videos. They present a technique how to apply a mask to a CIImage. You need to learn how to chain the filters together. In particular take a look at:

  • CICrop, CILinearGradient, CIRadialGradient (could be used to create the mask)
  • CISourceOverCompositing (put mask images together)
  • CIBlendWithMask (create final image)

The filters are documented here:

https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html

Your best bet would be to copy the CIImage (so you now have two), crop the copied CIImage to the rect you want to effect, perform the effect on that cropped version, then use an overlay effect to create a new CIImage based on the two older CIImages.

It seems like a lot of effort, but when you understand all of this is being set up as a bunch of GPU shaders it makes a lot more sense.

     typedef enum {
   ALPHA = 0,
   BLUE = 1,
   GREEN = 2,
  RED = 3

} PIXELS;

- (UIImage *)convertToGrayscale:(UIImage *) originalImage inRect: (CGRect) rect{
       CGSize size = [originalImage size];
   int width = size.width;
  int height = size.height;

// the pixels will be painted to this array
uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t));

// clear the pixels so any transparency is preserved
memset(pixels, 0, width * height * sizeof(uint32_t));

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

// create a context with RGBA pixels
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, 
                                             kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);

// paint the bitmap to our context which will fill in the pixels array
CGContextDrawImage(context, CGRectMake(0, 0, width, height), [originalImage CGImage]);

for(int y = 0; y < height; y++) {
    for(int x = 0; x < width; x++) {
        uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x];

        if(x > rect.origin.x && y > rect.origin.y && x < rect.origin.x + rect.size.width && y < rect.origin.y + rect.size.height) {

            // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale

            uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE];

            // set the pixels to gray in your rect

            rgbaPixel[RED] = gray;
            rgbaPixel[GREEN] = gray;
            rgbaPixel[BLUE] = gray;
          }
    }
}

// create a new CGImageRef from our context with the modified pixels
CGImageRef image = CGBitmapContextCreateImage(context);

// we're done with the context, color space, and pixels
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixels);

// make a new UIImage to return
UIImage *resultUIImage = [UIImage imageWithCGImage:image];

// we're done with image now too
CGImageRelease(image);

return resultUIImage;

}

You can test it in a UIImageView:

  imageview.image = [self convertToGrayscale:imageview.image inRect:CGRectMake(50, 50, 100, 100)];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!