gpt4 book ai didi

objective-c - 使用核心图形通过触摸删除和取消删除 UIImageVIew 中的图像

转载 作者:可可西里 更新时间:2023-11-01 03:50:01 25 4
gpt4 key购买 nike

我的问题与 here 中提到的相同.我也在我的应用程序中使用了两个图像,我只需要通过触摸删除顶部图像。然后通过触摸取消删除(如果需要)删除的部分。我正在使用以下代码删除顶部图像。这种方法也存在一个问题。这是图像很大,我正在使用 Aspect Fit 内容模式来正确显示它们。 当我触摸屏幕时,它会删除​​角落而不是触摸的地方。我认为触摸点计算需要一些修复。任何帮助将不胜感激。

第二个问题,触摸删除的部分如何取消?

UIGraphicsBeginImageContext(self.imgTop.image.size);
[self.imgTop.image drawInRect:CGRectMake(0, 0, self.imgTop.image.size.width, self.imgTop.image.size.height)];
self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
GContextSetLineWidth(UIGraphicsGetCurrentContext(), pinSize);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0, 0, 0, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeCopy);

CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.imgTop.contentMode = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

最佳答案

您的代码非常含糊:您正在创建一个内部包含 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,与 View 大小相同。此上下文用于存储将应用于前景图像的 mask 。

  • 每次您在屏幕上移动手指时,都会使用 CoreGraphics 在 CGBitmapContextRef 上绘制一条线,白色显示图像,黑色隐藏图像。通过这种方式,我们可以存储黑白绘图。

  • drawRect: 例程简单地绘制背景,然后从 CGBitmapContextRef 创建一个 CGImageRef 并将其应用于当前上下文作为面具。然后绘制前景图像。要绘制图像,它使用 - (void)drawImageScaled:(UIImage *)image,它只绘制缩放和居中的图像。

  • 如果您打算调整 View 大小,您应该实现一种方法来复制或重新创建具有新大小的 mask ,覆盖 - (void)setFrame:(CGRect)frame .

  • - (void)reset 方法只是清除掩码。

  • 即使位图上下文没有任何 alpha channel ,使用的灰度颜色空间 alpha:这就是为什么每次设置颜色时,我都必须指定两个组件。

Sample application with <code>EraseImageView</code> class

关于objective-c - 使用核心图形通过触摸删除和取消删除 UIImageVIew 中的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10032576/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com