为了账号安全,请及时绑定邮箱和手机立即绑定

如何从UIImage(Cocoa Touch)或CGImage(核心图形)获取像素数据?

/ 猿问

如何从UIImage(Cocoa Touch)或CGImage(核心图形)获取像素数据?

慕粉4167745 2019-06-01 16:40:36

如何从UIImage(Cocoa Touch)或CGImage(核心图形)获取像素数据?

我有一个UIImage(可可触觉)。从这一点上,我很高兴得到一个CGImage或其他您想要的任何东西都是可用的。我想写这个函数:

- (int)getRGBAFromImage:(UIImage *)image atX:(int)xx andY:(int)yy {
  // [...]
  // What do I want to read about to help
  // me fill in this bit, here?
  // [...]

  int result = (red << 24) | (green << 16) | (blue << 8) | alpha;
  return result;}

谢谢!


查看完整描述

4 回答

?
米琪卡哇伊

FYI,我把Keremk的答案和我原来的大纲结合起来,清理了排版,把它概括为返回了一系列的颜色,然后把整件事情都做了编译。结果如下:

+ (NSArray*)getRGBAsFromImage:(UIImage*)image atX:(int)x andY:(int)y count:(int)count{
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];

    // First get the image into your data buffer
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                    bitsPerComponent, bytesPerRow, colorSpace,
                    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);

    // Now your rawData contains the image data in the RGBA8888 pixel format.
    NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
    for (int i = 0 ; i < count ; ++i)
    {
        CGFloat alpha = ((CGFloat) rawData[byteIndex + 3] ) / 255.0f;
        CGFloat red   = ((CGFloat) rawData[byteIndex]     ) / alpha;
        CGFloat green = ((CGFloat) rawData[byteIndex + 1] ) / alpha;
        CGFloat blue  = ((CGFloat) rawData[byteIndex + 2] ) / alpha;
        byteIndex += bytesPerPixel;

        UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
        [result addObject:acolor];
    }

  free(rawData);

  return result;}


查看完整回答
反对 回复 2019-06-01
?
慕容4345310

一种方法是将图像绘制到由给定颜色空间的给定缓冲区支持的位图上下文(在本例中是RGB):(请注意,这将图像数据复制到该缓冲区,因此您确实希望缓存它,而不是每次需要获取像素值时执行此操作)。


作为样本,见下文:


// First get the image into your data buffer

CGImageRef image = [myUIImage CGImage];

NSUInteger width = CGImageGetWidth(image);

NSUInteger height = CGImageGetHeight(image);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

unsigned char *rawData = malloc(height * width * 4);

NSUInteger bytesPerPixel = 4;

NSUInteger bytesPerRow = bytesPerPixel * width;

NSUInteger bitsPerComponent = 8;

CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGColorSpaceRelease(colorSpace);


CGContextDrawImage(context, CGRectMake(0, 0, width, height));

CGContextRelease(context);


// Now your rawData contains the image data in the RGBA8888 pixel format.

int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;

red = rawData[byteIndex];

green = rawData[byteIndex + 1];

blue = rawData[byteIndex + 2];

alpha = rawData[byteIndex + 3];


查看完整回答
反对 回复 2019-06-01
?
ABOUTYOU

苹果的技术问答QA 1509显示以下简单方法:

CFDataRef CopyImagePixels(CGImageRef inImage){
    return CGDataProviderCopyData(CGImageGetDataProvider(inImage));}

使用CFDataGetBytePtr获取实际字节(以及各种字节)CGImageGet*方法了解如何解释它们)。


查看完整回答
反对 回复 2019-06-01
?
交互式爱情

不敢相信没有一个正确的答案这里。不需要分配指针,并且仍然需要标准化这些不相乘的值。下面是SWIFT 4的正确版本。为UIImage只管用.cgImage.

extension CGImage {
    func colors(at: [CGPoint]) -> [UIColor]? {
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bytesPerPixel = 4
        let bytesPerRow = bytesPerPixel * width
        let bitsPerComponent = 8
        let bitmapInfo: UInt32 = CGImageAlphaInfo.premultipliedLast.rawValue | CGBitmapInfo.byteOrder32Big.rawValue

        guard let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: bitsPerComponent, bytesPerRow: 
        bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo),
            let ptr = context.data?.assumingMemoryBound(to: UInt8.self) else {
            return nil        }

        context.draw(self, in: CGRect(x: 0, y: 0, width: width, height: height))

        return at.map { p in
            let i = bytesPerRow * Int(p.y) + bytesPerPixel * Int(p.x)

            let a = CGFloat(ptr[i + 3]) / 255.0
            let r = (CGFloat(ptr[i]) / a) / 255.0
            let g = (CGFloat(ptr[i + 1]) / a) / 255.0
            let b = (CGFloat(ptr[i + 2]) / a) / 255.0

            return UIColor(red: r, green: g, blue: b, alpha: a)
        }
    }}


查看完整回答
反对 回复 2019-06-01
  • 4 回答
  • 0 关注
  • 212 浏览
我要回答
慕课专栏
更多

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信