你的代碼是相當含糊:你創建上下文與imgTop裏面,然後用kCGBlendModeCopy
黑混色?這會導致黑色被複制到imgTop。我假設你想設置圖層的content
屬性呢?
無論如何,這個班級做你所需要的。只有一些有趣的方法(他們在頂部),其他只是屬性或init...
例程。
@interface EraseImageView : UIView {
CGContextRef context;
CGRect contextBounds;
}
@property (nonatomic, retain) UIImage *backgroundImage;
@property (nonatomic, retain) UIImage *foregroundImage;
@property (nonatomic, assign) CGFloat touchWidth;
@property (nonatomic, assign) BOOL touchRevealsImage;
- (void)resetDrawing;
@end
@interface EraseImageView()
- (void)createBitmapContext;
- (void)drawImageScaled:(UIImage *)image;
@end
@implementation EraseImageView
@synthesize touchRevealsImage=_touchRevealsImage, backgroundImage=_backgroundImage, foregroundImage=_foregroundImage, touchWidth=_touchWidth;
#pragma mark - Main methods -
- (void)createBitmapContext
{
// create a grayscale colorspace
CGColorSpaceRef grayscale=CGColorSpaceCreateDeviceGray();
/* TO DO: instead of saving the bounds at the moment of creation,
override setFrame:, create a new context with the right
size, draw the previous on the new, and replace the old
one with the new one.
*/
contextBounds=self.bounds;
// create a new 8 bit grayscale bitmap with no alpha (the mask)
context=CGBitmapContextCreate(NULL,
(size_t)contextBounds.size.width,
(size_t)contextBounds.size.height,
8,
(size_t)contextBounds.size.width,
grayscale,
kCGImageAlphaNone);
// make it white (touchRevealsImage==NO)
CGFloat white[]={1., 1.};
CGContextSetFillColor(context, white);
CGContextFillRect(context, contextBounds);
// setup drawing for that context
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGColorSpaceRelease(grayscale);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=(UITouch *)[touches anyObject];
// the new line that will be drawn
CGPoint points[]={
[touch previousLocationInView:self],
[touch locationInView:self]
};
// setup width and color
CGContextSetLineWidth(context, self.touchWidth);
CGFloat color[]={(self.touchRevealsImage ? 1. : 0.), 1.};
CGContextSetStrokeColor(context, color);
// stroke
CGContextStrokeLineSegments(context, points, 2);
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
if (self.foregroundImage==nil || self.backgroundImage==nil) return;
// draw background image
[self drawImageScaled:self.backgroundImage];
// create an image mask from the context
CGImageRef mask=CGBitmapContextCreateImage(context);
// set the current clipping mask to the image
CGContextRef ctx=UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextClipToMask(ctx, contextBounds, mask);
// now draw image (with mask)
[self drawImageScaled:self.foregroundImage];
CGContextRestoreGState(ctx);
CGImageRelease(mask);
}
- (void)resetDrawing
{
// draw black or white
CGFloat color[]={(self.touchRevealsImage ? 0. : 1.), 1.};
CGContextSetFillColor(context, color);
CGContextFillRect(context, contextBounds);
[self setNeedsDisplay];
}
#pragma mark - Helper methods -
- (void)drawImageScaled:(UIImage *)image
{
// just draws the image scaled down and centered
CGFloat selfRatio=self.frame.size.width/self.frame.size.height;
CGFloat imgRatio=image.size.width/image.size.height;
CGRect rect={0.,0.,0.,0.};
if (selfRatio>imgRatio) {
// view is wider than img
rect.size.height=self.frame.size.height;
rect.size.width=imgRatio*rect.size.height;
} else {
// img is wider than view
rect.size.width=self.frame.size.width;
rect.size.height=rect.size.width/imgRatio;
}
rect.origin.x=.5*(self.frame.size.width-rect.size.width);
rect.origin.y=.5*(self.frame.size.height-rect.size.height);
[image drawInRect:rect];
}
#pragma mark - Initialization and properties -
- (id)initWithCoder:(NSCoder *)aDecoder
{
if ((self=[super initWithCoder:aDecoder])) {
[self createBitmapContext];
_touchWidth=10.;
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
if ((self=[super initWithFrame:frame])) {
[self createBitmapContext];
_touchWidth=10.;
}
return self;
}
- (void)dealloc
{
CGContextRelease(context);
[super dealloc];
}
- (void)setBackgroundImage:(UIImage *)value
{
if (value!=_backgroundImage) {
[_backgroundImage release];
_backgroundImage=[value retain];
[self setNeedsDisplay];
}
}
- (void)setForegroundImage:(UIImage *)value
{
if (value!=_foregroundImage) {
[_foregroundImage release];
_foregroundImage=[value retain];
[self setNeedsDisplay];
}
}
- (void)setTouchRevealsImage:(BOOL)value
{
if (value!=_touchRevealsImage) {
_touchRevealsImage=value;
[self setNeedsDisplay];
}
}
@end
一些注意事項:
該類保留你所需要的兩個圖像。它有一個touchRevealsImage
屬性將模式設置爲繪製或擦除,並且可以設置線條的寬度。
初始化時,它創建一個CGBitmapContextRef
,灰度,8bpp,沒有alpha,具有相同大小的視圖。此上下文用於存儲將應用於前景圖像的遮罩。
每次在屏幕上移動手指時,使用CoreGraphics在CGBitmapContextRef
上畫一條線,白色顯示圖像,黑色隱藏圖像。這樣我們就可以存儲黑白圖。
drawRect:
例程簡單地繪製背景,然後從CGBitmapContextRef
創建CGImageRef
並將其作爲掩碼應用於當前上下文。然後繪製前景圖像。爲了繪製圖像,它使用- (void)drawImageScaled:(UIImage *)image
,它只是繪製縮放和居中的圖像。
如果您打算調整視圖的大小,應該實施一種方法來複制或重新創建具有新大小的蒙版,覆蓋- (void)setFrame:(CGRect)frame
。
- (void)reset
方法只是清除掩碼。
即使位圖背景下也沒有任何alpha通道,用於灰度色彩空間有阿爾法:這就是爲什麼每一個顏色設定的時間,我必須指定兩個組成部分。
你有沒有找到解決這個問題?如果你找到一個解決方案,你能分享一下解決方案嗎我面臨完全相同的問題,無法找到合適的解決方案。 – Anuj 2012-09-11 12:06:04
如果您有解決方案,請回復。 – Muzammil 2012-11-02 12:14:13