Получение данных пикселей из UIImageView - работает на симуляторе, а не на устройстве - PullRequest
4 голосов
/ 16 декабря 2009

На основе ответов на на предыдущий вопрос я создал категорию в 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;
}

Ответы [ 3 ]

5 голосов
/ 10 июня 2010

Я думаю, что R B G не так. У вас есть:

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

Но разве вы не имеете в виду R G B ? :

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

Но даже с этим исправлением все еще остается проблема, так как выясняется, что Apple переставляет байты (отличная статья) значения R и B на устройстве, но не на тренажер.

У меня была похожая проблема симулятора / устройства с пиксельным буфером PNG, возвращаемым CFDataGetBytePtr.

Это решило проблему для меня:

#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

Не уверен, что это решит вашу проблему, но ваш некорректно работающий код выглядит примерно так, как выглядел мой, до того, как я его исправил.

И последнее: я думаю, что симулятор позволит вам получить доступ к вашему пиксельному буферу data[] даже после вызова CFRelease(bitmapData). На устройстве это не дело в моем опыте. Ваш код не должен быть затронут, но в случае, если это поможет кому-то еще, я подумал, что упомяну это.

0 голосов
/ 26 декабря 2010

Похоже, что в коде, размещенном в исходных вопросах, вместо:

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);
0 голосов
/ 17 декабря 2009

Вы можете попробовать следующий альтернативный подход:

  • создать CGBitmapContext
  • нарисовать изображение в контексте
  • вызовите CGBitmapContextGetData для контекста, чтобы получить базовые данные
  • обработать ваше смещение в необработанных данных (на основе того, как вы создали контекст растрового изображения)
  • извлечь значение

Этот подход работает для меня на тренажере и устройстве.

...