如何将 UIBezierPath 保存到现有的 UIImageView?

发布于 2024-11-14 11:59:07 字数 1256 浏览 4 评论 0原文

我不知道如何将绘制的路径保存到 UIImage?
我知道我必须使用 UIGraphicsBeginImageContext 和类似 [drawImage drawInRect:CGRectMake(0, 0, drawImage.size.width, drawImage.size.height)];
但我不知道把它放在我的触摸功能中的哪里。

我需要保存图像的每条路径,因为我希望能够在每条绘制线之后更改颜色和 alpha 值。
使用此代码,当我更改值时,所有线条的颜色和宽度将同时调整。

- (id) initWithFrame:(CGRect)frame andImage: (UIImageView*) image
{
    ...
    paths = [[NSMutableArray alloc]init];

    drawImage = image;
    self.backgroundColor=[UIColor clearColor];
    [self addSubview:drawImage];
}
- (void)drawRect:(CGRect)rect
{
    [brushPattern setStroke];
    [myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    // Drawing code
    //[myPath stroke];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
    myPath=[[UIBezierPath alloc]init];
    [myPath moveToPoint:[mytouch locationInView:self]];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
    [myPath addLineToPoint:[mytouch locationInView:self]];
    [self setNeedsDisplay];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

    [paths addObject:myPath];
    [myPath release];
}

I can't figure out how i can save my drawn path to an UIImage?
I know that I have to use UIGraphicsBeginImageContext and something like [drawImage drawInRect:CGRectMake(0, 0, drawImage.size.width, drawImage.size.height)];
But I don't know where to put it in my touch functions.

I need to save every path to the image, because I want to be able to change the color and alpha values after each drawn line.
With this code, all the lines will be adjusted in color and width at the same time when I change the values.

- (id) initWithFrame:(CGRect)frame andImage: (UIImageView*) image
{
    ...
    paths = [[NSMutableArray alloc]init];

    drawImage = image;
    self.backgroundColor=[UIColor clearColor];
    [self addSubview:drawImage];
}
- (void)drawRect:(CGRect)rect
{
    [brushPattern setStroke];
    [myPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    // Drawing code
    //[myPath stroke];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
    myPath=[[UIBezierPath alloc]init];
    [myPath moveToPoint:[mytouch locationInView:self]];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
    [myPath addLineToPoint:[mytouch locationInView:self]];
    [self setNeedsDisplay];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{

    [paths addObject:myPath];
    [myPath release];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

焚却相思 2024-11-21 11:59:07

根据您之前的问题,我假设图像视图是此自定义视图对象的子视图。您将需要在此类中维护一个可变的路径数组。在 touchesBegan:withEvent: 处初始化它,并在 touchesEnded:withEvent: 处关闭路径。将路径推入数组。在每次触摸事件(开始、移动、结束)时,调用一个方法,在将触摸点添加到路径后更新图像视图的图像。

更新图像将涉及创建一个空图像上下文,然后在抚摸它们时迭代数组中的所有路径和当前路径。完成绘图后,从上下文生成图像对象并将其设置为图像。非常简单,直到我们注意到每条路径的属性可能不同。为了解决这个问题,您应该为路径创建一个容器类,它将保存有关路径的属性。将每个路径的此类对象推送到数组中,而不是路径本身。这样您就可以维护视图的状态。

Based on your earlier question, I am assuming that the image view is a subview of this custom view object. You will need to maintain a mutable array of paths in this class. Initialize it at touchesBegan:withEvent: and close the path at touchesEnded:withEvent:. Push the path into the array. At every touch event (began, moved, ended), call a method that updates the image view's image after adding the touch point to the path.

Updating the image will involve creating an empty image context and then iterating over all paths in your array and the current path while stroking them. Once you're done drawing, generate the image object from the context and set it to the image. Pretty straightforward until we notice that each path might differ in attributes. To deal with this you should create a container class for the path which will hold the attributes about the path. Push an object of this class for every path into the array rather than the path itself. This way you can maintain state for your view.

_畞蕅 2024-11-21 11:59:07

事实上,有一种方法非常简单,每次绘制路径对象时,您都可以将其保存在增量图像中,只需在需要的位置创建它,然后在绘制其他内容之前在绘制矩形中显示该图像。

示例代码如下:

  - (void)drawBitmap 
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
    [strokeColor setStroke];
    if (!incrementalImage) // first time draw; paint background white by ...
    {
        UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
        [[UIColor colorWithPatternImage:[UIImage imageNamed:@"two.jpg"]] setFill];
        //[[UIColor whiteColor] setFill];
        [rectpath fill]; // filling it with white
        NSLog(@"========== ... drawBitmap .. CALLED=======");
    }
    [incrementalImage drawAtPoint:CGPointZero];

    for(NSDictionary *_pathDict in pathArray)
    {
        [((UIColor *)[_pathDict valueForKey:@"color"]) setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)
        [[_pathDict valueForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    }
    incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    }

然后在drawRect:中调用这个增量图像,让用户有一种连续绘制的错觉,然后你可以保存这个图像的时间点:

    - (void)drawRect:(CGRect)rect
{

     [incrementalImage drawInRect:rect];
     [[dict_path objectForKey:@"color"] setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)

     [[dict_path objectForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];

}

可能你需要根据自己的需要修改一些代码.希望这对某人有帮助

There is one way out and very simple infact , each time you draw a path object you can save it in an increamental image , just create it at a place where needed and then show this image in draw rect before drawing something else.

here is the sample code:

  - (void)drawBitmap 
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
    [strokeColor setStroke];
    if (!incrementalImage) // first time draw; paint background white by ...
    {
        UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
        [[UIColor colorWithPatternImage:[UIImage imageNamed:@"two.jpg"]] setFill];
        //[[UIColor whiteColor] setFill];
        [rectpath fill]; // filling it with white
        NSLog(@"========== ... drawBitmap .. CALLED=======");
    }
    [incrementalImage drawAtPoint:CGPointZero];

    for(NSDictionary *_pathDict in pathArray)
    {
        [((UIColor *)[_pathDict valueForKey:@"color"]) setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)
        [[_pathDict valueForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    }
    incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    }

After that just call this increamental image in drawRect: , so that user has a illusion of continuous drawing and you can then save this image point of time:

    - (void)drawRect:(CGRect)rect
{

     [incrementalImage drawInRect:rect];
     [[dict_path objectForKey:@"color"] setStroke]; // this method will choose the color from the receiver color object (in this case this object is :strokeColor)

     [[dict_path objectForKey:@"path"] strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];

}

May be you need to modify some code according to your own need.Hope this help someone

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文