Pixeldaten von UIImageView abrufen – funktioniert auf dem Simulator, nicht auf dem Gerät

StackOverflow https://stackoverflow.com/questions/1911360

  •  19-09-2019
  •  | 
  •  

Frage

Basierend auf den Antworten auf eine vorherige Frage, ich habe auf UIImageView eine Kategorie zum Extrahieren von Pixeldaten erstellt.Dies funktioniert im Simulator einwandfrei, jedoch nicht bei der Bereitstellung auf dem Gerät.Ich sollte nein sagen stets – Das Seltsame ist, dass die richtige Pixelfarbe abgerufen wird, wenn point.x == point.y;Andernfalls erhalte ich Pixeldaten für ein Pixel auf der anderen Seite dieser Linie, als ob sie gespiegelt wären.(Wenn ich also auf ein Pixel in der unteren rechten Ecke des Bildes tippe, erhalte ich die Pixeldaten für ein entsprechendes Pixel in der oberen linken Ecke, aber wenn ich auf ein Pixel in der unteren linken Ecke tippe, wird die richtige Pixelfarbe zurückgegeben.)Die Berührungskoordinaten (CGPoint) sind korrekt.

Was mache ich falsch?

Hier ist mein Code:

@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;
}
War es hilfreich?

Lösung

Ich denke R B G ist falsch.Du hast:

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

Aber meinst du nicht wirklich R? G B? :

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

Aber selbst wenn das behoben ist, gibt es immer noch ein Problem, wie sich herausstellt, Apple Byte-Swaps (toller Artikel) die R- und B-Werte auf dem Gerät, aber nicht wenn man am Simulator ist.

Ich hatte ein ähnliches Simulator-/Geräteproblem mit dem von CFDataGetBytePtr zurückgegebenen PNG-Pixelpuffer.

Dies hat das Problem für mich gelöst:

#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

Ich bin mir nicht sicher, ob Ihr Problem dadurch behoben wird, aber Ihr Code, der sich schlecht verhält, sieht in etwa so aus, wie meiner aussah, bevor ich ihn behoben habe.

Eine letzte Sache:Ich glaube, dass Sie mit dem Simulator auf Ihren Pixelpuffer zugreifen können data[] selbst nach CFRelease(bitmapData) wird genannt.Auf dem Gerät ist dies der Fall nicht meiner Erfahrung nach der Fall.Ihr Code sollte nicht betroffen sein, aber falls dies jemand anderem hilft, dachte ich, ich würde es erwähnen.

Andere Tipps

Sie könnten den folgenden alternativen Ansatz ausprobieren:

  • Erstellen Sie einen CGBitmapContext
  • Ziehen Sie das Bild in den Kontext
  • Rufen Sie CGBitmapContextGetData für den Kontext auf, um die zugrunde liegenden Daten abzurufen
  • Berechnen Sie Ihren Offset in den Rohdaten (basierend darauf, wie Sie den Bitmap-Kontext erstellt haben).
  • Extrahieren Sie den Wert

Dieser Ansatz funktioniert für mich auf dem Simulator und dem Gerät.

Im Code, der in den ursprünglichen Fragen gepostet wurde, sieht es so aus, statt:

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

Es sollte sein:

NSUInteger x = (NSUInteger)floor(point.x);
NSUInteger y = (NSUInteger)floor(point.y);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top