Un peu plus de détail...
J'ai posté plus tôt ce soir avec une consolidation et une petite addition à ce qui avait été dit sur cette page - qui peut être trouvée en bas de ce post. Je suis en train d'éditer le post à ce stade, cependant, pour poster ce que je propose est (au moins pour mes besoins, qui incluent la modification des données de pixels) une meilleure méthode, car elle fournit des données inscriptibles (alors que, tel que je le comprends, la méthode fournie par les posts précédents et en bas de ce post fournit une référence en lecture seule aux données).
Méthode 1 : Informations sur les pixels inscriptibles
-
J'ai défini des constantes
#define RGBA 4
#define RGBA_8_BIT 8
-
Dans ma sous-classe UIImage j'ai déclaré des variables d'instance :
size_t bytesPerRow;
size_t byteCount;
size_t pixelCount;
CGContextRef context;
CGColorSpaceRef colorSpace;
UInt8 *pixelByteData;
// Un pointeur vers un tableau d'octets RGBA en mémoire
RPVW_RGBAPixel *pixelData;
-
La structure de pixel (avec alpha dans cette version)
typedef struct RGBAPixel {
byte red;
byte green;
byte blue;
byte alpha;
} RGBAPixel;
-
Fonction de bitmap (retourne RGBA précalculé ; diviser RGB par A pour obtenir RGB non modifié) :
-(RGBAPixel*) bitmap {
NSLog( @"Retourner la représentation bitmap de UIImage." );
// 8 bits pour le rouge, le vert, le bleu et l'alpha.
[self setBytesPerRow:self.size.width * RGBA];
[self setByteCount:bytesPerRow * self.size.height];
[self setPixelCount:self.size.width * self.size.height];
// Créer un espace couleur RGB
[self setColorSpace:CGColorSpaceCreateDeviceRGB()];
if (!colorSpace)
{
NSLog(@"Erreur d'allocation de l'espace couleur.");
return nil;
}
[self setPixelData:malloc(byteCount)];
if (!pixelData)
{
NSLog(@"Erreur d'allocation de la mémoire du bitmap. Libération de l'espace couleur.");
CGColorSpaceRelease(colorSpace);
return nil;
}
// Créer le contexte de bitmap.
// RGBA pré-multiplié, 8 bits par composant.
// Le format d'image source sera converti en format spécifié ici par CGBitmapContextCreate.
[self setContext:CGBitmapContextCreate(
(void*)pixelData,
self.size.width,
self.size.height,
RGBA_8_BIT,
bytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedLast
)];
// Assurez-vous que nous avons notre contexte
if (!context) {
free(pixelData);
NSLog(@"Contexte non créé !");
}
// Dessiner l'image dans le contexte de bitmap.
// La mémoire allouée pour le contexte de rendu contiendra alors les données brutes de l'image pixelData dans l'espace couleur spécifié.
CGRect rect = { { 0 , 0 }, { self.size.width, self.size.height } };
CGContextDrawImage( context, rect, self.CGImage );
// Maintenant, nous pouvons obtenir un pointeur vers les données de pixels d'image associées au contexte de bitmap.
pixelData = (RGBAPixel*) CGBitmapContextGetData(context);
return pixelData;
}
Données en lecture seule (Informations précédentes) - méthode 2 :
Étape 1. J'ai déclaré un type pour octet :
typedef unsigned char byte;
Étape 2. J'ai déclaré une structure correspondant à un pixel :
typedef struct RGBPixel{
byte red;
byte green;
byte blue;
}
RGBPixel;
Étape 3. J'ai sous-classé UIImageView et déclaré (avec les propriétés synthétisées correspondantes) :
// Référence au Quartz CGImage pour le receveur (self)
CFDataRef bitmapData;
// Tampon contenant les données brutes de pixels copiées du Quartz CGImage contenues dans le receveur (self)
UInt8* pixelByteData;
// Un pointeur vers le premier élément de pixel dans un tableau
RGBPixel* pixelData;
Étape 4. Code de sous-classe mis dans une méthode nommée bitmap (pour retourner les données de pixels de l'image) :
// Obtenir les données de l'image bitmap du CGImage du receveur (voir la documentation UIImage)
[self setBitmapData: CGDataProviderCopyData(CGImageGetDataProvider([self CGImage]))];
// Créer un tampon pour stocker les données de l'image bitmap (mémoire non initialisée aussi longtemps que les données)
[self setPixelBitData:malloc(CFDataGetLength(bitmapData))];
// Copier les données de l'image dans le tampon alloué
CFDataGetBytes(bitmapData,CFRangeMake(0,CFDataGetLength(bitmapData)),pixelByteData);
// Convertir un pointeur vers le premier élément de pixelByteData
// Essentiellement ce que nous faisons, c'est de créer un deuxième pointeur qui divise les unités de byteData différemment - au lieu de diviser chaque unité comme 1 octet, nous allons diviser chaque unité comme 3 octets (1 pixel).
pixelData = (RGBPixel*) pixelByteData;
// Maintenant vous pouvez accéder aux pixels par index : pixelData[ index ]
NSLog(@"Données du pixel un rouge (%i), vert (%i), bleu (%i).", pixelData[0].red, pixelData[0].green, pixelData[0].blue);
// Vous pouvez déterminer l'index souhaité en multipliant ligne * colonne.
return pixelData;
Étape 5. J'ai créé une méthode d'accessibilité :
-(RGBPixel*)pixelDataForRow:(int)row column:(int)column{
// Retourner un pointeur vers les données du pixel
return &pixelData[row * column];
}