【问题标题】:How to erase part of an image as the user touches it如何在用户触摸图像时擦除图像的一部分
【发布时间】:2010-06-04 23:24:10
【问题描述】:

我的总体目标是在图像上设置一个灰色区域,然后当用户在该灰色区域上摩擦时,它会显示下面的图像。基本上就像一张彩票刮刮卡。我已经通过文档以及此站点进行了大量搜索,但找不到解决方案。

以下只是一个概念验证,用于测试根据用户触摸的位置“擦除”图像,但它不起作用。 :(

我有一个检测触摸的 UIView,然后通过执行以下操作将移动的坐标发送到 UIViewController,该 UIViewController 在 UIImageView 中剪辑图像:

- (void) moveDetectedFrom:(CGPoint) from to:(CGPoint) to
{
    UIImage* image = bkgdImageView.image;
    CGSize s = image.size;
    UIGraphicsBeginImageContext(s);
    CGContextRef g = UIGraphicsGetCurrentContext();

    CGContextMoveToPoint(g, from.x, from.y);
    CGContextAddLineToPoint(g, to.x, to.y);
    CGContextClosePath(g);
    CGContextAddRect(g, CGRectMake(0, 0, s.width, s.height));
    CGContextEOClip(g);
    [image drawAtPoint:CGPointZero];
    bkgdImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [bkgdImageView setNeedsDisplay];
}

问题是触摸被发送到这个方法就好了,但在原件上没有任何反应。

我做的剪辑路径不正确吗?或者?

不太确定……因此,我们将不胜感激。

提前致谢, 乔尔

【问题讨论】:

    标签: iphone objective-c uiimageview uiimage cgcontext


    【解决方案1】:

    很久以前我一直在尝试做同样的事情,只使用Core Graphics,并且可以做到,但是相信我,效果并不像用户期望的那样流畅和柔和。所以,我知道如何使用 OpenCV(开放计算机视觉库),并且因为它是用 C 语言编写的,我知道我可以在 iPhone 上使用它。 用 OpenCV 做你想做的事非常容易。 首先,您需要几个函数来将 UIImage 转换为 IplImage,这是 OpenCV 中用来表示各种图像的类型,反之亦然。

    + (IplImage *)CreateIplImageFromUIImage:(UIImage *)image {
    CGImageRef imageRef = image.CGImage;
    //This is the function you use to convert a UIImage -> IplImage
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
    IplImage *iplimage = cvCreateImage(cvSize(image.size.width, image.size.height), IPL_DEPTH_8U, 4);
    CGContextRef contextRef = CGBitmapContextCreate(iplimage->imageData, iplimage->width, iplimage->height,
                                                    iplimage->depth, iplimage->widthStep,
                                                    colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault);
    CGContextDrawImage(contextRef, CGRectMake(0, 0, image.size.width, image.size.height), imageRef);
    
    
    CGContextRelease(contextRef);
    
    CGColorSpaceRelease(colorSpace);
    
    return iplimage;}
    
    
    
    + (UIImage *)UIImageFromIplImage:(IplImage *)image {
    
    //Convert a IplImage -> UIImage
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    NSData * data = [[NSData alloc] initWithBytes:image->imageData length:image->imageSize];
    //NSData *data = [NSData dataWithBytes:image->imageData length:image->imageSize];
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
    CGImageRef imageRef = CGImageCreate(image->width, image->height,
                                        image->depth, image->depth * image->nChannels, image->widthStep,
                                        colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault,
                                        provider, NULL, false, kCGRenderingIntentDefault);
    UIImage *ret = [[UIImage alloc] initWithCGImage:imageRef];
    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);
    [data release];
    return ret;}
    

    现在您已经具备了所需的两个基本功能,您可以使用 IplImage 为所欲为: 这就是你想要的:

    +(UIImage *)erasePointinUIImage:(IplImage *)image :(CGPoint)point :(int)r{
    //r is the radious of the erasing
        int a = point.x;
     int b = point.y;
     int position;
     int minX,minY,maxX,maxY;
     minX = (a-r>0)?a-r:0;
     minY = (b-r>0)?b-r:0;
     maxX = ((a+r) < (image->width))? a+r : (image->width);
     maxY = ((b+r) < (image->height))? b+r : (image->height);
    
     for (int i = minX; i < maxX ; i++)
     {
        for(int j=minY; j<maxY;j++)
        {
            position =  ((j-b)*(j-b))+((i-a)*(i-a));
            if (position <= r*r)
            {
                uchar* ptr =(uchar*)(image->imageData) + (j*image->widthStep + i*image->nChannels);
                ptr[1] = ptr[2] = ptr[3] = ptr[4] = 0;
            }
        }
    }
    UIImage * res = [self UIImageFromIplImage:image]; 
    return res;}
    

    抱歉格式化。

    如果你想知道如何将 OpenCV 移植到 iPhone Yoshimasa Niwa's

    如果您想在 AppStore 上查看当前使用 OpenCV 的应用,请获取:Flags&Faces

    【讨论】:

      【解决方案2】:

      您通常希望在 drawRect: 方法中绘制到当前图形上下文中,而不仅仅是任何旧方法。此外,剪辑区域仅影响绘制到当前图形上下文的内容。但是,与其深入探讨为什么这种方法不起作用,我建议以不同的方式进行。

      我要做的是有两种观点。一个带有图像,一个带有透明的灰色。这允许图形硬件缓存图像,而不是每次修改灰色填充时都尝试重新绘制图像。

      灰色的将是带有 CGBitmapContext 的 UIView 子类,您可以将其绘制到其中以使用户触摸的像素清晰。

      可能有几种方法可以做到这一点。我只是在上面建议一种方法。

      【讨论】:

      • 感谢您为我指明正确的方向。我之前研究过,但找不到正确的方法来 1)创建一个 ARGB 位图(它似乎总是一个 RGB)和 2)一旦我有了像素数据的二维数组,就操纵像素的 alpha 值。我会继续挖掘并发布我发现的内容。谢谢。
      • 如果您发布您的解决方案将会非常方便,Joel。 (或者至少是相关的 drawRect 方法。)
      猜你喜欢
      • 1970-01-01
      • 2012-07-21
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多