首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UIGraphicsBeginImageContext对CGBitmapContextCreate

UIGraphicsBeginImageContext对CGBitmapContextCreate
EN

Stack Overflow用户
提问于 2011-01-13 18:01:06
回答 1查看 12.7K关注 0票数 4

我试图在后台线程中改变图像的颜色。

Apple说,只能从主线程调用UIGraphicsBeginImageContext,我正在尝试使用CGBitmapContextCreate:

context = CGBitmapContextCreate (bitmapData,pixelsWide,pixelsHigh,8,//位每个组件bitmapBytesPerRow,colorSpace,kCGImageAlphaPremultipliedFirst);

我有两个版本的"changeColor“,第一个版本使用UIGraphisBeginImageContext,第二个版本使用CGBitmapContextCreate。

第一个正确改变颜色,但第二个没有。

为什么会这样呢?

代码语言:javascript
复制
- (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;
}

代码语言:javascript
复制
- (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;
}

代码语言:javascript
复制
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

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-13 20:20:06

第二种方法是做第一种从未做过的工作。下面是第二种方法的调整,以更接近第一种方法:

代码语言:javascript
复制
- (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;

    CGContextSetFillColorWithColor(aColor.CGColor);

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

    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    UIImage* img = [UIImage imageWithCGImage: imageRef];
    CGContextRelease(context);

    return img;
}

我所做的两个更改是将其转换为使用CGContextSetFillColorWithColor(),并删除位图上下文中支持数据的危险和不正确的free()。如果这个代码片段的行为与第一个代码片段不同,那么您必须查看CreateARGBBitmapContext()的实现,以验证它是正确的。

当然,正如Brad在评论中提到的,如果您的目标是iOS 4.0和更高版本,那么UIKit图形方法(根据发布说明)是线程安全的,您应该能够很好地使用第一个方法。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4683448

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档