Ich versuche, die Farbe eines Bildes in einem Hintergrund-Thread zu ändern.
Apple-doc sagt UIGraphicsBeginImageContext kann nur von Haupt-Thread aufgerufen werden, und ich versuche, CGBitmapContextCreate zu verwenden:UIGraphicsBeginImageContext vs CGBitmapContextCreate
context = CGBitmapContextCreate (bitmapdata, pixelsWide, pixelsHigh, 8 // Bits pro Komponente
bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst);
ich habe zwei Versionen von "changeColor" ersten mit UIGraphisBeginImageContext, zweitem CGBitmapContext mit Erstellen.
Die erste ändert korrekt die Farbe, die zweite jedoch nicht.
Warum ist das?
- (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;
}
Tatsächlich sind UIKit Zeichenfunktionen jetzt in iOS 4.0 threadsafe: http://www.cocoabuilder.com/archive/cocoa/296299-drawing-thread-safety-in-ios.html. Dies scheint 'UIGraphicsBeginImageContext()' zu enthalten. Möglicherweise benötigen Sie die reine Core Graphics-Implementierung in 4.0+ nicht. –
ist das Zitat maßgebend? http://StackOverflow.com/Questions/4451855/uigraphicsbegeimagecontext-vs-cgbitmapcontextcreate-on-ios Es gibt Debatten darüber, denke ich ?, und mein Testcode starb mit UIGraphicsBeginImageContext() auf separaten Thread. obwohl ich nicht hundertprozentig sicher sein kann, dass das der wahre Grund ist. – eugene
das ist eine andere Frage, wenn Sie sagen, iOS 4.0, gilt es, wenn ich iOS <4.0 Ziel, aber kompilieren mit iOS> = 4.0? oder der Code sollte nur auf einem Rechner mit iOS> = 4.0 laufen? – eugene