Do twojej wiadomości, połączyłem odpowiedź Keremka z moim oryginalnym konturem, posprzątałem literówki, uogólniłem go, aby zwrócić tablicę kolorów i wszystko skompilowałem. Oto wynik:
+ (NSArray*)getRGBAsFromImage:(UIImage*)image atX:(int)x andY:(int)y count:(int)count
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity:count];
// First get the image into your data buffer
CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
// Now your rawData contains the image data in the RGBA8888 pixel format.
NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
for (int i = 0 ; i < count ; ++i)
{
CGFloat alpha = ((CGFloat) rawData[byteIndex + 3] ) / 255.0f;
CGFloat red = ((CGFloat) rawData[byteIndex] ) / alpha;
CGFloat green = ((CGFloat) rawData[byteIndex + 1] ) / alpha;
CGFloat blue = ((CGFloat) rawData[byteIndex + 2] ) / alpha;
byteIndex += bytesPerPixel;
UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
[result addObject:acolor];
}
free(rawData);
return result;
}
getRGBAsFromImage:image atX:0 andY:0 count:image.size.width*image.size.height
Aby uzyskać RGBA dla ostatniego wiersza obrazu:getRGBAsFromImage:image atX:0 andY:image.size.height-1 count:image.size.width
Jednym ze sposobów jest narysowanie obrazu w kontekście bitmapy, który jest wspierany przez dany bufor dla danej przestrzeni kolorów (w tym przypadku jest to RGB): (zauważ, że spowoduje to skopiowanie danych obrazu do tego bufora, więc robisz to chcesz buforować go zamiast wykonywać tę operację za każdym razem, gdy potrzebujesz wartości pikseli)
Zobacz poniżej jako przykład:
źródło
CGContextDrawImage
wymaga trzech argumentów, a powyżej podane są tylko dwa ... Myślę, że tak powinno byćCGContextDrawImage(context, CGRectMake(0, 0, width, height), image)
Apple Q & A Techniczne QA1509 przedstawia następujące proste podejście:
Użyj,
CFDataGetBytePtr
aby przejść do rzeczywistych bajtów (i różnychCGImageGet*
metod, aby zrozumieć, jak je interpretować).źródło
Nie mogłem uwierzyć, że nie ma tu ani jednej poprawnej odpowiedzi . Nie ma potrzeby przydzielania wskaźników, a niezmnożone wartości nadal wymagają normalizacji. Aby przejść do sedna, oto odpowiednia wersja dla Swift 4.
UIImage
Tylko do użytku.cgImage
.Powodem, dla którego musisz najpierw narysować / przekonwertować obraz na bufor, jest to, że obrazy mogą mieć kilka różnych formatów. Ten krok jest wymagany do przekonwertowania go na spójny format, który można odczytać.
źródło
let imageObj = UIImage(named:"greencolorImg.png"); imageObj.cgImage?.colors(at: [pt1, pt2])
pt1
ipt2
są toCGPoint
zmienne.Oto wątek SO, w którym @Matt renderuje tylko pożądany piksel w kontekście 1x1 poprzez przemieszczenie obrazu, tak aby żądany piksel był wyrównany z jednym pikselem w kontekście.
źródło
źródło
UIImage to opakowanie, bajty to CGImage lub CIImage
Według Apple Reference na UIImage obiekt jest niezmienny i nie masz dostępu do bajtów kopii zapasowej. Chociaż prawdą jest, że możesz uzyskać dostęp do danych CGImage, jeśli zapełniłeś
UIImage
jeCGImage
(jawnie lub niejawnie), zwróci je,NULL
jeśliUIImage
jest poparte przezCIImage
i odwrotnie.Typowe wskazówki pozwalające obejść ten problem
Jak już wspomniano, dostępne są opcje
Żadne z tych nie są szczególnie dobrymi sztuczkami, jeśli chcesz uzyskać dane wyjściowe, które nie są danymi ARGB, PNG lub JPEG, a dane nie są jeszcze wspierane przez CIImage.
Moja rekomendacja, spróbuj CIImage
Opracowując projekt, sensowniejsze może być całkowite uniknięcie UIImage i wybranie czegoś innego. UIImage, jako opakowanie obrazu Obj-C, jest często wspierane przez CGImage do tego stopnia, że uznajemy to za coś oczywistego. CIImage jest zwykle lepszym formatem opakowania, ponieważ można użyć CIContext, aby uzyskać pożądany format bez konieczności poznawania sposobu jego utworzenia. W twoim przypadku uzyskanie mapy bitowej byłoby kwestią sprawdzenia
- render: toBitmap: rowBytes: bounds: format: colorSpace:
Jako dodatkowy bonus możesz zacząć robić fajne manipulacje obrazem, łącząc filtry z obrazem. Rozwiązuje to wiele problemów, w których obraz jest odwrócony do góry nogami lub wymaga obracania / skalowania itp.
źródło
Opierając się na odpowiedzi Olie i Algala, oto zaktualizowana odpowiedź dla Swift 3
szybki
źródło
Wersja Swift 5
Podane tutaj odpowiedzi są nieaktualne lub niepoprawne, ponieważ nie uwzględniają następujących elementów:
image.size.width
/image.size.height
.UIView.drawHierarchy(in:afterScreenUpdates:)
metoda może generować obrazy BGRA.CGImage
, rozmiar rzędu pikseli w bajtach może być większy niż zwykłe pomnożenie szerokości piksela przez 4.Poniższy kod ma zapewnić uniwersalne rozwiązanie Swift 5, aby uzyskać
UIColor
piksel dla wszystkich takich specjalnych przypadków. Kod jest zoptymalizowany pod kątem użyteczności i przejrzystości, a nie wydajności.źródło
componentLayout
brakuje przypadek, gdy istnieje tylko alfa.alphaOnly
.UIImage
, co należy zrobić przed rozpoczęciem czytania kolorów pikseli.Na podstawie różnych odpowiedzi, ale głównie na tym , działa to, czego potrzebuję:
W wyniku tych linii będziesz miał piksel w formacie AARRGGBB z wartością alfa zawsze ustawioną na FF w 4-bajtowej liczbie całkowitej bez znaku
pixel1
.źródło
Aby uzyskać dostęp do surowych wartości RGB obrazu UIImage w Swift 5, użyj bazowego CGImage i jego dataProvider:
https://www.ralfebert.de/ios/examples/image-processing/uiimage-raw-pixels/
źródło