0

我正在获取图像并将其保存到后台线程中的临时目录中。在保存之前,我想给这个 UIImage 添加一点白色边框。我正在这样做:

    - (UIImage *)imageWithBorder:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width, image.size.height);
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale); {
        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextBeginTransparencyLayer (context, NULL);
        //Draw
        [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextStrokeRectWithWidth(context, rect, 10);
        CGContextEndTransparencyLayer(context);
    }
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

invalid context 0x0一切都很好,从临时目录加载该图像后,我可以看到图像的边框,但在控制台中,当下面的代码实现时,我得到了。这里有什么问题?


更新01

- (UIImage *)imageWithBorder:(UIImage *)image {
    CGSize newSize = CGSizeMake(image.size.width, image.size.height);
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale); {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextDrawImage (context, rect, [image CGImage]);
        CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
        CGContextStrokeRectWithWidth(context, rect, 10);
    }
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}
4

2 回答 2

1

UIGraphicsGetCurrentContext 返回当前的图形上下文。

CGContextRef UIGraphicsGetCurrentContext ( 无效 ); 返回值 当前图形上下文。

讨论 当前图形上下文默认为 nil。在调用它的 drawRect: 方法之前,视图对象将一个有效的上下文压入堆栈,使其成为当前的。但是,如果您不使用 UIView 对象进行绘图,则必须使用 UIGraphicsPushContext 函数手动将有效上下文推送到堆栈上。

您应该只从应用程序的主线程调用此函数。

这是来自UIKit 函数参考

于 2012-08-27T17:12:40.173 回答
1

尝试改变:

[image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];

CGContextDrawImage (context, rect, [image CGImage]);

另外,为什么要使用透明层?您将 alpha 设置为 1,因此您可以覆盖原始图像,不是吗?

编辑:我只是在我的应用程序中运行相同的代码,在后台,它完美地工作:

- (UIImage *)imageWithBorder:(UIImage *)image
{
    NSLog(@"Thread %@", [NSThread currentThread]);

    CGSize newSize = CGSizeMake(image.size.width, image.size.height);
    CGRect rect = CGRectMake(0.0, 0.0, image.size.width, image.size.height);

    UIGraphicsBeginImageContextWithOptions(newSize, NO, image.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();

    //Draw
    CGContextDrawImage(context, rect, [image CGImage]);
    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    CGContextStrokeRectWithWidth(context, rect, 10);
    UIImage *result =  UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
assert(result);
    return result;
}

当我在 viewDidAppear 中执行此操作时:(但它是一个小图像,也许大小相关?)

dispatch_async(dispatch_get_global_queue(0, 0), ^{ [self imageWithBorder:[UIImage imageNamed:@"02-redo.png"]] ; } );

这就是我在日志中看到的全部内容:

2012-08-27 13:48:04.679 Searcher[32825:11103] Thread <NSThread: 0x6d30e30>{name = (null), num = 4}

因此,您的代码正在发生其他事情。我正在使用 Xcode 4.4.1 构建,部署目标是 5.1

编辑:在您的块中,您不能引用“单元格”,因为单元格是临时的 - 通过回收它甚至可能不可见。因此,图像名称将通过本地 NSString 路由,最后,您需要另一个可以将图像发布到的方法,以及单元格 indexPath。该方法将查看该 indexPath 是否在 table 的 visibleCells 中,如果是,则更新图像,如果不是,则要存储图像以便它可以与 tableView 一起使用,然后请求单元格。

EDIT2:此代码:

dispatch_async(queue, ^{ 
  UIImage *image = [_thumbnailMaster thumbnailForItemWithFilename:cell.label.text];
  dispatch_sync(dispatch_get_main_queue(), ^{ cell.thumbnailView.image = image; }); 
});

应该变成不涉及“单元格”的东西,因为单元格可能超出范围或被另一个索引使用(假设回收)。像这样的东西:

NSString *text = cell.label.text;
NSIndexPath *path = ...;

dispatch_async(queue, ^{ 
  UIImage *image = [_thumbnailMaster thumbnailForItemWithFilename:text];  
   dispatch_sync(dispatch_get_main_queue(), ^{ [self updateCellImage:image withPath"path]; }); 
});

您的方法确定该单元格是否可见,如果是则更新图像,如果不保存则下次您需要它时拥有它。

于 2012-08-27T17:20:59.460 回答