UIImage中的绘制区域未被正确识别。

10
我在我的项目中遇到了一个奇怪的问题。我想做的是,用户可以在图片上刷或者画图,并且我只需要从被涂色区域下面的图片中剪裁出该区域即可。我的代码只有当下面的 UIImage 视图宽度为 320 像素,即 iPhone 的宽度时才能正常工作。但是如果我改变 ImageView 的宽度,就无法得到期望的结果。
我正在使用以下代码来构建一个围绕涂过颜料部分的 CGRect
-(CGRect)detectRectForFaceInImage:(UIImage *)image{
    int l,r,t,b;
    l = r = t = b = 0;

    CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
    const UInt8* data = CFDataGetBytePtr(pixelData);

    BOOL pixelFound = NO;

    for (int i = leftX ; i < rightX; i++) {
        for (int j = topY; j < bottomY + 20; j++) {
            int pixelInfo = ((image.size.width  * j) + i ) * 4;
            UInt8 alpha = data[pixelInfo + 2];
            if (alpha) {
                NSLog(@"Left %d", alpha);
                l = i;
                pixelFound = YES;
                break;
            }
        }
        if(pixelFound) break;
    }

    pixelFound = NO;
    for (int i =  rightX ; i >= l; i--) {
        for (int j = topY; j < bottomY ; j++) {
            int pixelInfo = ((image.size.width  * j) + i ) * 4;
            UInt8 alpha = data[pixelInfo + 2];
            if (alpha) {
                NSLog(@"Right %d", alpha);
                r = i;
                pixelFound = YES;
                break;
            }
        }
        if(pixelFound) break;
    }

    pixelFound = NO;
    for (int i = topY ; i < bottomY ; i++) {
        for (int j = l; j < r; j++) {
            int pixelInfo = ((image.size.width  * i) + j ) * 4;
            UInt8 alpha = data[pixelInfo + 2];
            if (alpha) {
                NSLog(@"Top %d", alpha);
                t = i;
                pixelFound = YES;
                break;
            }
        }
        if(pixelFound) break;
    }

    pixelFound = NO;
    for (int i = bottomY ; i >= t; i--) {
        for (int j = l; j < r; j++) {
            int pixelInfo = ((image.size.width  * i) + j ) * 4;
            UInt8 alpha = data[pixelInfo + 2];
            if (alpha) {
                NSLog(@"Bottom %d", alpha);
                b = i;
                pixelFound = YES;
                break;
            }
        }
        if(pixelFound) break;
    }

    CFRelease(pixelData);


    return CGRectMake(l, t, r - l, b-t);
}

在以上代码中,leftX、rightX、topY和bottomY是从CGPoint计算出来的浮点数极值。当用户在屏幕上涂画时,这些值表示包含涂画区域的矩形边界(以最小化循环)。请注意保留HTML标签。
    leftX   -  minimum in X-axis
    rightX  -  maximum in X-axis
    topY    -  min in Y-axis
    bottom  -  max in Y-axis 

这里l、r、t、b是实际矩形的计算值。

如前所述,当绘图所用的imageview宽度为320像素且覆盖整个屏幕宽度时,此代码效果良好。但如果imageview的宽度较小,比如300,并且位于屏幕中央,则该代码会给出错误结果。

注意:我根据imageview的宽度缩放图像。

以下是NSLog输出:

  1. When imageview's width is 320 pixel (These are value for the component of color at matched pixel or non-transparent pixel):

    2013-05-17 17:58:17.170 FunFace[12103:907] Left 41
    2013-05-17 17:58:17.172 FunFace[12103:907] Right 1
    2013-05-17 17:58:17.173 FunFace[12103:907] Top 73
    2013-05-17 17:58:17.174 FunFace[12103:907] Bottom 12
    
  2. When imageview's width is 300 pixel:

    2013-05-17 17:55:26.066 FunFace[12086:907] Left 42
    2013-05-17 17:55:26.067 FunFace[12086:907] Right 255
    2013-05-17 17:55:26.069 FunFace[12086:907] Top 42
    2013-05-17 17:55:26.071 FunFace[12086:907] Bottom 255
    

我需要将ImageView居中并在两侧留有填充,你能告诉我如何解决这个问题吗?

编辑:好的,看起来我的问题是由于JPEG图像(来自相机)的方向。PNG图像可以正常工作,并且不会受到ImageView宽度变化的影响。 但即使我处理了方向,JPEG仍然无法正常工作。


图片的尺寸是多少? - Wain
当imageview的宽度为320时,图像大小为320x240。当imageview的宽度为300时,我将图像缩放为300x225(即imageview的大小)。 - Gaurav Singh
你是实际重绘图像到那个尺寸还是只是将其放在图像视图中并允许图像视图缩放它? - Wain
在将图像分配给imageView之前,我将其缩放为imageView的大小。 我的源图像为320x240。 如果imageView宽度为320像素,则不进行缩放。 如果imageView宽度为300像素,则我将按比例将图像缩放到300宽度。 - Gaurav Singh
JPEG不支持alpha通道(我想),如果这有什么提示的话。 - Kalle
1个回答

2
首先,我想知道您是否访问的是32位RGBA以外的其他内容?数据[]的索引值存储在pixelInfo中,然后移动+2个字节,而不是+3个字节。这将使您落在蓝色字节上。如果您的目的是使用RGBA,则该事实将影响代码其余部分的结果。
接下来,假设您仍然得到了有缺陷的结果,尽管具有正确的alpha组件值,似乎您的“修复”代码将给出Left、Right、Top、Bottom NSLog输出,其中alpha值小于完全的255,接近于0。在这种情况下,没有进一步的代码,我建议您的问题在于用于从320x240源缩小图像到300x225(或可能是任何其他缩放尺寸)的代码。我可以想象,如果您的“scale”代码执行裁剪而不是缩放,则图像边缘可能具有255的α值。

我已经有点解决了这个问题。在下面的链接中,将malloc更改为calloc后的方法对我有效:link - Gaurav Singh
但有时当检查像素时,我的应用程序会崩溃,我不知道原因。可能是正在访问的内存位置为空。 - Gaurav Singh
@GauravSingh 我认为你使用的CGDataProviderCopyData、CGImageGetDataProvider和CFDataGetBytePtr是适当的。现在你是否已经更改了代码?如果你更新问题,澄清你仍然存在的问题会有帮助。 - Tom Pace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接