且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用蒙版获取图像像素

更新时间:2023-01-28 18:50:07

你可以把你的图片放在一个 UIImageView 中,然后给那个图片视图添加一个掩码,比如

You can put your image in a UIImageView and add a mask to that image view with something like

myImageView.layer.mask = myMaskLayer;

要绘制您的自定义形状,myMaskLayer 应该是您自己的实现 drawInContext 方法的 CALayer 子类的实例.该方法应该使用完整的 alpha 绘制要在图像中显示的区域以及使用零 alpha 隐藏的区域(如果您愿意,也可以在 alpha 之间使用).这是一个 CALayer 子类的示例实现,当它用作图像视图上的掩码时,将只显示图像左上角的椭圆形区域:

To draw your custom shapes, myMaskLayer should be an instance of your own subclass of CALayer that implements the drawInContext method. The method should draw the areas to be shown in the image with full alpha and the areas to be hidden with zero alpha (and can also use in between alphas if you like). Here's an example implementation of a CALayer subclass that, when used as a mask on the image view, will cause only an oval area in the top left corner of the image to be shown:

@interface MyMaskLayer : CALayer
@end

@implementation MyMaskLayer
- (void)drawInContext:(CGContextRef)ctx {
    static CGColorSpaceRef rgbColorSpace;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    });

    const CGRect selfBounds = self.bounds;
    CGContextSetFillColorSpace(ctx, rgbColorSpace);
    CGContextSetFillColor(ctx, (CGFloat[4]){0.0, 0.0, 0.0, 0.0});
    CGContextFillRect(ctx, selfBounds);
    CGContextSetFillColor(ctx, (CGFloat[4]){0.0, 0.0, 0.0, 1.0});
    CGContextFillEllipseInRect(ctx, selfBounds);
}
@end

要将这样的遮罩层应用于图像视图,您可以使用这样的代码

To apply such a mask layer to an image view, you might use code like this

MyMaskLayer *maskLayer = [[MyMaskLayer alloc] init];
maskLayer.bounds = self.view.bounds;
[maskLayer setNeedsDisplay];
self.imageView.layer.mask = maskLayer;

现在,如果您想从这样的渲染中获取像素数据,***渲染到由您控制像素缓冲区的位图支持的 CGContext 中.您可以在渲染后检查缓冲区中的像素数据.这是一个示例,我创建了位图上下文并将图层和蒙版渲染到该位图上下文中.由于我为像素数据提供了自己的缓冲区,因此我可以在缓冲区中四处寻找渲染后的 RGBA 值.

Now, if you want to get pixel data from a rendering like this it's best to render into a CGContext backed by a bitmap where you control the pixel buffer. You can inspect the pixel data in your buffer after rendering. Here's an example where I create a bitmap context and render a layer and mask into that bitmap context. Since I supply my own buffer for the pixel data, I can then go poking around in the buffer to get RGBA values after rendering.

const CGRect imageViewBounds = self.imageView.bounds;
const size_t imageWidth = CGRectGetWidth(imageViewBounds);
const size_t imageHeight = CGRectGetHeight(imageViewBounds);
const size_t bytesPerPixel = 4;
// Allocate your own buffer for the bitmap data.  You can pass NULL to
// CGBitmapContextCreate and then Quartz will allocate the memory for you, but
// you won't have a pointer to the resulting pixel data you want to inspect!
unsigned char *bitmapData = (unsigned char *)malloc(imageWidth * imageHeight * bytesPerPixel);
CGContextRef context = CGBitmapContextCreate(bitmapData, imageWidth, imageHeight, 8, bytesPerPixel * imageWidth, rgbColorSpace, kCGImageAlphaPremultipliedLast);
// Render the image into the bitmap context.
[self.imageView.layer renderInContext:context];
// Set the blend mode to destination in, pixels become "destination * source alpha"
CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
// Render the mask into the bitmap context.
[self.imageView.layer.mask renderInContext:context];
// Whatever you like here, I just chose the middle of the image.
const size_t x = imageWidth / 2;
const size_t y = imageHeight / 2;
const size_t pixelIndex = y * imageWidth + x;
const unsigned char red = bitmapData[pixelIndex];
const unsigned char green = bitmapData[pixelIndex + 1];
const unsigned char blue = bitmapData[pixelIndex + 2];
const unsigned char alpha = bitmapData[pixelIndex + 3];
NSLog(@"rgba: {%u, %u, %u, %u}", red, green, blue, alpha);