Pour info, j'ai combiné la réponse de Keremk avec mon contour d'origine, nettoyé les fautes de frappe, généralisé pour retourner un tableau de couleurs et obtenu le tout à compiler. Voici le résultat:
+ (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
Pour obtenir des RGBAs pour la dernière ligne d'une image:getRGBAsFromImage:image atX:0 andY:image.size.height-1 count:image.size.width
Une façon de le faire est de dessiner l'image dans un contexte bitmap qui est soutenu par un tampon donné pour un espace colorimétrique donné (dans ce cas, il est RVB): (notez que cela copiera les données d'image dans ce tampon, donc vous faites voulez le mettre en cache au lieu de faire cette opération chaque fois que vous avez besoin d'obtenir des valeurs en pixels)
Voir ci-dessous comme exemple:
la source
CGContextDrawImage
nécessite trois arguments et au-dessus, seuls deux sont donnés ... Je pense que cela devrait êtreCGContextDrawImage(context, CGRectMake(0, 0, width, height), image)
Apple technique Q & A QA1509 montre l'approche simple suivante:
Utilisez
CFDataGetBytePtr
pour accéder aux octets réels (et diversesCGImageGet*
méthodes pour comprendre comment les interpréter).la source
Je ne pouvais pas croire qu'il n'y a pas une seule bonne réponse ici. Pas besoin d'allouer des pointeurs et les valeurs non multipliées doivent encore être normalisées. Pour aller droit au but, voici la version correcte pour Swift 4. Pour
UIImage
une utilisation juste.cgImage
.La raison pour laquelle vous devez d'abord dessiner / convertir l'image dans un tampon est que les images peuvent avoir plusieurs formats différents. Cette étape est nécessaire pour le convertir dans un format cohérent que vous pouvez lire.
la source
let imageObj = UIImage(named:"greencolorImg.png"); imageObj.cgImage?.colors(at: [pt1, pt2])
pt1
etpt2
sont desCGPoint
variables.Voici un thread SO où @Matt rend uniquement le pixel souhaité dans un contexte 1x1 en déplaçant l'image de sorte que le pixel souhaité s'aligne avec le pixel du contexte.
la source
la source
UIImage est un wrapper dont les octets sont CGImage ou CIImage
Selon la référence Apple sur UIImage, l'objet est immuable et vous n'avez pas accès aux octets de support. S'il est vrai que vous pouvez accéder aux données CGImage si vous avez rempli le
UIImage
avec unCGImage
(explicitement ou implicitement), il reviendraNULL
si leUIImage
est soutenu par unCIImage
et vice-versa.Astuces courantes pour contourner ce problème
Comme indiqué, vos options sont
Aucun de ces éléments n'est particulièrement bon si vous voulez une sortie qui n'est pas des données ARGB, PNG ou JPEG et les données ne sont pas déjà sauvegardées par CIImage.
Ma recommandation, essayez CIImage
Lors du développement de votre projet, il peut être plus judicieux d'éviter complètement UIImage et de choisir autre chose. UIImage, en tant que wrapper d'image Obj-C, est souvent soutenu par CGImage au point où nous le tenons pour acquis. CIImage a tendance à être un meilleur format de wrapper dans la mesure où vous pouvez utiliser un CIContext pour obtenir le format souhaité sans avoir besoin de savoir comment il a été créé. Dans votre cas, obtenir le bitmap reviendrait à appeler
- render: toBitmap: rowBytes: bounds: format: colorSpace:
En prime, vous pouvez commencer à faire de belles manipulations sur l'image en enchaînant les filtres sur l'image. Cela résout un grand nombre des problèmes où l'image est à l'envers ou doit être tournée / mise à l'échelle, etc.
la source
S'appuyant sur la réponse d'Olie et d'Algal, voici une réponse mise à jour pour Swift 3
rapide
la source
Version Swift 5
Les réponses données ici sont obsolètes ou incorrectes car elles ne prennent pas en compte les éléments suivants:
image.size.width
/image.size.height
.UIView.drawHierarchy(in:afterScreenUpdates:)
méthode peut produire des images BGRA.CGImage
, la taille d'une ligne de pixels en octets peut être supérieure à la simple multiplication de la largeur de pixel par 4.Le code ci-dessous est de fournir une solution Swift 5 universelle pour obtenir le
UIColor
pixel pour tous ces cas spéciaux. Le code est optimisé pour la convivialité et la clarté, pas pour les performances.la source
componentLayout
manque le cas où il n'y a que l' alpha,.alphaOnly
.UIImage
, ce que vous feriez avant de commencer à lire ses couleurs de pixels.Basé sur différentes réponses mais principalement sur cela , cela fonctionne pour ce dont j'ai besoin:
À la suite de ces lignes, vous aurez un pixel au format AARRGGBB avec alpha toujours défini sur FF dans l'entier non signé de 4 octets
pixel1
.la source
Pour accéder aux valeurs RVB brutes d'un UIImage dans Swift 5, utilisez le CGImage sous-jacent et son dataProvider:
https://www.ralfebert.de/ios/examples/image-processing/uiimage-raw-pixels/
la source