UIGraphicsBeginImageContext vs CGBitmapContextCreate

Je suis en train de changer de couleur d'une image dans un thread d'arrière-plan.

Apple doc a dit UIGraphicsBeginImageContext ne peut être appelé à partir de thread principal, et je suis en train d'utiliser CGBitmapContextCreate:

contexte = CGBitmapContextCreate
(bitmapData,
pixelsWide,
pixelsHigh,
8, //bits par composante

                             bitmapBytesPerRow,
                             colorSpace,
                             kCGImageAlphaPremultipliedFirst);

J'ai deux versions de "changeColor" premier à utiliser UIGraphisBeginImageContext, le second, à l'aide de CGBitmapContextCreate.

Le premier correctement les changements de couleur, mais le second ne l'est pas.

Pourquoi est-ce?

- (UIImage*) changeColor: (UIColor*) aColor
{
    if(aColor == nil)
        return self;

    UIGraphicsBeginImageContext(self.size);

    CGRect bounds;
    bounds.origin = CGPointMake(0,0);
    bounds.size = self.size;
    [aColor set];

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0, self.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextClipToMask(context, bounds, [self CGImage]);
    CGContextFillRect(context, bounds);

    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

- (UIImage*) changeColor: (UIColor*) aColor
{
    if(aColor == nil)
        return self;

    CGContextRef context = CreateARGBBitmapContext(self.size);

    CGRect bounds;
    bounds.origin = CGPointMake(0,0);
    bounds.size = self.size;

    CGColorRef colorRef = aColor.CGColor;
    const CGFloat *components = CGColorGetComponents(colorRef);
    float red = components[0];
    float green = components[1];
    float blue = components[2];

    CGContextSetRGBFillColor(context, red, green, blue, 1);


    CGContextClipToMask(context, bounds, [self CGImage]);
    CGContextFillRect(context, bounds);

    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage* img = [UIImage imageWithCGImage: imageRef];
    unsigned char* data = (unsigned char*)CGBitmapContextGetData (context);  
    CGContextRelease(context);
    free(data);

    return img;
}

CGContextRef CreateARGBBitmapContext(CGSize size)
{
CGContextRef    context = NULL;
CGColorSpaceRef colorSpace;
void *          bitmapData;
int             bitmapByteCount;
int             bitmapBytesPerRow;
//Get image width, height. We'll use the entire image.                                                                                                                                                                                 
size_t pixelsWide = size.width;
size_t pixelsHigh = size.height;
//Declare the number of bytes per row. Each pixel in the bitmap in this                                                                                                                                                                
//example is represented by 4 bytes; 8 bits each of red, green, blue, and                                                                                                                                                              
//alpha.                                                                                                                                                                                                                               
bitmapBytesPerRow   = (pixelsWide * 4);
bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);
//Use the generic RGB color space.                                                                                                                                                                                                     
colorSpace = CGColorSpaceCreateDeviceRGB();
if (colorSpace == NULL)
{
fprintf(stderr, "Error allocating color space\n");
return NULL;
}
//Allocate memory for image data. This is the destination in memory                                                                                                                                                                    
//where any drawing to the bitmap context will be rendered.                                                                                                                                                                            
bitmapData = malloc( bitmapByteCount );
if (bitmapData == NULL)
{
fprintf (stderr, "Memory not allocated!");
CGColorSpaceRelease( colorSpace );
return NULL;
}
//Create the bitmap context. We want pre-multiplied ARGB, 8-bits                                                                                                                                                                       
//per component. Regardless of what the source image format is                                                                                                                                                                         
//(CMYK, Grayscale, and so on) it will be converted over to the format                                                                                                                                                                 
//specified here by CGBitmapContextCreate.                                                                                                                                                                                             
context = CGBitmapContextCreate (bitmapData,
pixelsWide,
pixelsHigh,
8,      //bits per component                                                                                                                                                                          
bitmapBytesPerRow,
colorSpace,
kCGImageAlphaPremultipliedFirst);
if (context == NULL)
{
free (bitmapData);
fprintf (stderr, "Context not created!");
}
//Make sure and release colorspace before returning                                                                                                                                                                                    
CGColorSpaceRelease( colorSpace );
return context;
}
En fait, dans l'iOS 4.0 UIKit fonctions de dessin sont maintenant des threads: cocoabuilder.com/archive/cocoa/... . Cela semble inclure UIGraphicsBeginImageContext(). Vous ne pouvez pas besoin de la pure Graphiques de Base de la mise en œuvre de la version 4.0+.
est la citation d'autorité? stackoverflow.com/questions/4451855/... il y a des débats sur, je suppose?, et mon code de test est mort avec UIGraphicsBeginImageContext() sur un thread séparé. bien que je ne peux pas être sûr à 100% que c'est la vraie raison.
c'est une autre question, quand vous dites que l'iOS 4.0, il ne s'applique pas lorsque je cible iOS < 4.0 mais compiler avec iOS >= 4.0 ? ou le code doit s'exécuter sur la machine avec iOS >=4.0?
David Duncan est un ingénieur de chez Apple, donc je dirais que sa déclaration, combiné avec les notes de version, fait autorité. Ce n'est thread-safe lorsqu'il est exécuté sur iOS 4.0+, parce qu'bâtiment contre la 4.x SDK utilise toujours les locaux de l'OS de la mise en œuvre si le ciblage des versions plus anciennes. Si vous avez besoin d'anciens OS de soutien, vous aurez toujours besoin d'aller à la pure Graphiques de Base de l'itinéraire.

OriginalL'auteur eugene | 2011-01-13