在 touchesMoved 委托中获取像素的 RGB

Posted

技术标签:

【中文标题】在 touchesMoved 委托中获取像素的 RGB【英文标题】:Getting RGB of a pixel in touchesMoved delegate 【发布时间】:2013-05-22 10:21:11 【问题描述】:

我创建了一个选择像素 RGB 值的页面。它允许用户移动他的手指并选择所选图像的像素颜色。还将因此获得的 RGB 设置为显示他的选择的小图像视图。

这是一段代码。

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

    UITouch *touch = [[event allTouches] anyObject];

    // Get Touch location
    CGPoint touchLocation = [touch locationInView:touch.view];

    // Set touch location's center to ImageView
    if (CGRectContainsPoint(imageViewColorPicker.frame, touchLocation))
    
        imageViewColorPicker.center = touchLocation;

        CGImageRef image = [imageViewSelectedImage.image 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),image);
        CGContextRelease(context);

        int byteIndex = (bytesPerRow * (int)touchLocation.y) + (int)touchLocation.x * bytesPerPixel;
        red = rawData[byteIndex];
        green = rawData[byteIndex + 1];
        blue = rawData[byteIndex + 2];
        alpha = rawData[byteIndex + 3];


        imgPixelColor.backgroundColor=[UIColor colorWithRed:red/255.0 green:green/255.0 blue:blue/255.0 alpha:alpha];
    

它正在解决我的问题。但问题是它有时会在手指移动时崩溃,在日志窗口中显示 3 次 Received Memory Warning 消息。

我做错了吗?有没有其他方法可以让 RGB 解决此类问题?有没有图书馆?

感谢您的快速帮助。

【问题讨论】:

【参考方案1】:

mallocing 图形上下文的像素缓冲区 (rawData),但你从来没有 free 它,所以你基本上是在泄漏整个图像的副本,每次触摸移动 (这可能很快就会占用大量内存)。

在 if 语句的末尾添加。

free(rawData);

顺便说一句,您可能需要考虑只创建一次位图上下文并重复使用它。每次触摸移动时都重新绘制图像,如果它始终保持不变的话,那是非常浪费的。

【讨论】:

感谢 man..释放 (rawData) 有助于避免崩溃。但是,您能否详细说明如何重用 context 。我这样做是我猜错了: if(!context) context= CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height),image); CGContextRelease(上下文);另外,由于我一次又一次地绘制图像,因此移动图像视图以选择颜色的工作非常缓慢。请建议,【参考方案2】:

@David:RinoTom 是对的。将您的询问作为答案发布是没有意义的。

无论如何,回到您的问题,我为这个问题创建了一个替代解决方案。我使用平移手势移动视图并使用以下方法选择其中心点的 RGB:

-(UIColor *)colorOfTappedPoint:(CGPoint)point

    unsigned char pixel[4] = 0;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast);

    CGContextTranslateCTM(context, -point.x, -point.y);

    [self.view.layer renderInContext:context];

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    UIColor *color = [UIColor colorWithRed:pixel[0]/255.0 green:pixel[1]/255.0 blue:pixel[2]/255.0 alpha:pixel[3]/255.0];

    red = pixel[0];
    green = pixel[1];
    blue = pixel[2];
    alpha = pixel[3];

    NSLog(@"%d %d %d %d",red,green,blue,alpha);
    return color;

希望这会有所帮助。

【讨论】:

以上是关于在 touchesMoved 委托中获取像素的 RGB的主要内容,如果未能解决你的问题,请参考以下文章

SetNeedsDisplay导致应用程序在TouchesMoved事件中崩溃

从 TouchesMoved 获取子视图参考

获取BMP文件的像素值

OpenGL获取像素的原始3d坐标

在 Swift 中使用 touchesMoved 跟踪触摸

如何在 Swift 和 SpriteKit 中使用 UISwipeGestureRecognizer 而不是 touchesMoved?