【发布时间】:2011-01-13 18:01:06
【问题描述】:
我正在尝试在后台线程中更改图像的颜色。
苹果文档说 UIGraphicsBeginImageContext 只能从主线程调用,我正在尝试使用 CGBitmapContextCreate:
上下文 = CGBitmapContextCreate (位图数据, 像素宽, 像素高, 8, // 每个组件的位数
bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedFirst);
我有两个版本的“changeColor”,第一个使用 UIGraphisBeginImageContext,第二个使用 CGBitmapContextCreate。
第一个正确改变颜色,但第二个没有。
这是为什么?
- (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;
}
【问题讨论】:
-
实际上,在 iOS 4.0 中,UIKit 绘图函数现在是线程安全的:cocoabuilder.com/archive/cocoa/…。这似乎包括
UIGraphicsBeginImageContext()。您可能不需要 4.0+ 中的纯 Core Graphics 实现。 -
报价是否权威? stackoverflow.com/questions/4451855/… 我猜有争论吗?我的测试代码在单独的线程上因 UIGraphicsBeginImageContext() 而死。虽然我不能 100% 确定这是真正的原因。
-
这是另一个问题,当您说 iOS 4.0 时,当我以 iOS = 4.0 编译时是否适用?或者代码应该只在 iOS >=4.0 的机器上运行?
-
David Duncan 是 Apple 的一名工程师,所以我认为他的声明以及发行说明是权威的。这仅在 iOS 4.0+ 设备上运行时是线程安全的,因为如果针对旧版本,针对 4.x SDK 构建仍然使用本地操作系统实现。如果您需要旧版操作系统支持,您仍然需要采用纯 Core Graphics 路线。
标签: ios colors cgbitmapcontextcreate