4

前の質問への回答に基づいて、ピクセルデータを抽出するためのカテゴリをUIImageViewに作成しました。これはシミュレーターでは正常に機能しますが、デバイスにデプロイされた場合は機能しません。常にではないことを言う必要があります-奇妙なことは、point.x == point.y;の場合、正しいピクセルカラーをフェッチすることです。それ以外の場合は、ミラーリングされているかのように、その線の反対側のピクセルのピクセルデータが得られます。(したがって、画像の右下隅にあるピクセルをタップすると、左上隅にある対応するピクセルのピクセルデータが得られますが、左下隅にあるピクセルをタップすると、正しいピクセルの色が返されます)。タッチ座標(CGPoint)は正しいです。

私は何が間違っているのですか?

これが私のコードです:

@interface UIImageView (PixelColor)
- (UIColor*)getRGBPixelColorAtPoint:(CGPoint)point;
@end

@implementation UIImageView (PixelColor)

- (UIColor*)getRGBPixelColorAtPoint:(CGPoint)point
{
    UIColor* color = nil;

    CGImageRef cgImage = [self.image CGImage];
    size_t width = CGImageGetWidth(cgImage);
    size_t height = CGImageGetHeight(cgImage);
    NSUInteger x = (NSUInteger)floor(point.x);
    NSUInteger y = height - (NSUInteger)floor(point.y);

    if ((x < width) && (y < height))
    {
        CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
        CFDataRef bitmapData = CGDataProviderCopyData(provider);
        const UInt8* data = CFDataGetBytePtr(bitmapData);
        size_t offset = ((width * y) + x) * 4;
        UInt8 red = data[offset];
        UInt8 blue = data[offset+1];
        UInt8 green = data[offset+2];
        UInt8 alpha = data[offset+3];
        CFRelease(bitmapData);
        color = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:alpha/255.0f];
    }

    return color;
}
4

3 に答える 3

5

R BGは間違っていると思います。あなたが持っている:

UInt8 red =   data[offset];     
UInt8 blue =  data[offset+1];
UInt8 green = data[offset+2];

でも本当に R GBじゃないの?:

UInt8 red =   data[offset];     
UInt8 green = data[offset+1];
UInt8 blue =  data[offset+2];

しかし、それが修正されたとしても、デバイス上では Appleバイトが R 値と B 値を交換する (素晴らしい記事) が、シミュレーター上ではそうではないことが判明するため、まだ問題があります。

CFDataGetBytePtr によって返される PNG のピクセル バッファで同様のシミュレータ/デバイスの問題が発生しました。

これで問題は解決しました:

#if TARGET_IPHONE_SIMULATOR
        UInt8 red =   data[offset];
        UInt8 green = data[offset + 1];
        UInt8 blue =  data[offset + 2];
#else
        //on device
        UInt8 blue =  data[offset];       //notice red and blue are swapped
        UInt8 green = data[offset + 1];
        UInt8 red =   data[offset + 2];
#endif

これで問題が解決するかどうかはわかりませんが、あなたの不正なコードは、私が修正する前のコードに近いように見えます。

最後に 1 つ:が呼び出されたdata[]後でも、シミュレーターを使用するとピクセル バッファーにアクセスできると思います。CFRelease(bitmapData)デバイスでは、これは私の経験では当てはまりません。あなたのコードは影響を受けるべきではありませんが、これが他の誰かを助ける場合に備えて、私はそれについて言及したいと思いました.

于 2010-06-10T13:01:48.550 に答える
0

次の代替アプローチを試すことができます。

  • CGBitmapContext を作成する
  • コンテキストに画像を描画する
  • コンテキストでCGBitmapContextGetDataを呼び出して、基になるデータを取得します
  • 生データへのオフセットを計算します(ビットマップコンテキストの作成方法に基づいて)
  • 値を抽出する

このアプローチは、シミュレーターとデバイスで機能します。

于 2009-12-17T08:34:50.723 に答える
0

元の質問に投稿されたコードでは、次のようになります。

NSUInteger x = (NSUInteger)floor(point.x);
NSUInteger y = height - (NSUInteger)floor(point.y);

そのはず:

NSUInteger x = (NSUInteger)floor(point.x);
NSUInteger y = (NSUInteger)floor(point.y);
于 2010-12-26T19:12:08.947 に答える