Pergunta

Com base nas respostas a uma pergunta anterior, eu criei uma categoria em UIImageView para extrair dados de pixel. Esta multa funciona no simulador, mas não quando implantado no dispositivo. Eu não deveria dizer sempre - O estranho é que ele faz buscar a cor do pixel correto se point.x == point.y; caso contrário, ele me dá o pixel de dados para um pixel do outro lado da linha, como se espelhado. (Então, um toque em um pixel no canto inferior direito da imagem dá-me os dados de pixel para um pixel correspondente na parte superior esquerda, mas batendo em um pixel no canto inferior esquerdo retorna a cor do pixel correto). As coordenadas de toque (CGPoint) estão corretas.

O que estou fazendo de errado?

Aqui está o meu código:

@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;
}
Foi útil?

Solução

Eu acho que R B G é errado. Você tem:

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

Mas não se você realmente média R G B ? :

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

Mas, mesmo com a fixada há ainda um problema como se vê a Apple byte permutas (grande artigo) os valores de R e B quando sobre o dispositivo, mas não quando no simulador.

Eu tive um problema simulador / dispositivo semelhante com tampão de pixels de um PNG retornado por CFDataGetBytePtr.

Esta resolvido o problema para mim:

#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

Não sei se isso vai resolver o seu problema, mas o seu código de mau comportamento parece perto do que o meu parecia antes de eu fixa-lo.

Uma última coisa: Eu acredito que o simulador permitirá que você acessar seu buffer data[] pixels mesmo depois CFRelease(bitmapData) é chamado. No dispositivo este é não o caso na minha experiência. Seu código não deve ser afetado, mas caso isso ajude alguém que eu pensei que eu iria mencioná-lo.

Outras dicas

Você pode tentar o seguinte abordagem alternativa:

  • criar um CGBitmapContext
  • desenhar a imagem no contexto
  • chamar CGBitmapContextGetData do contexto para obter os dados subjacentes
  • trabalho fora o seu deslocamento para os dados brutos (com base em como você criou o contexto bitmap)
  • extrair o valor

Esta abordagem funciona para mim no simulador e no dispositivo.

Parece que no código postou as perguntas originais em vez de:

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

Ele deve ser:

NSUInteger x = (NSUInteger)floor(point.x);
NSUInteger y = (NSUInteger)floor(point.y);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top