只为绘制的特定区域边界获取 UIImage - PaintView

Posted

技术标签:

【中文标题】只为绘制的特定区域边界获取 UIImage - PaintView【英文标题】:Getting UIImage for only particular area bounds drawn - PaintView 【发布时间】:2016-06-30 15:29:53 【问题描述】:

我已经实现了绘画/绘图使用:

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

现在的问题是,对于任何绘制的线条,我都想获得那条特定的线条/绘画图像。我不想要整个屏幕的图像,只绘制线条/油漆的区域/边界。

原因是我想在那条线/绘制的油漆上执行平移手势/删除功能。

用户可以画多条线,所以需要UIImage分别为所有这些线。

任何逻辑或代码 sn-p 都会很有帮助

提前致谢

【问题讨论】:

【参考方案1】:

根据您的应用程序,尤其是您计划连续执行多少次,您可以为每条油漆线创建不同的图像/图层。您的最终图像基本上是所有单独绘制的线。

创建自定义视图来捕获触摸事件可能更有效。您可以存储每条绘制线的触摸坐标列表,并在自定义 drawRect 中一次渲染它们。这样,您就可以存储每条油漆线的坐标列表,并且仍然可以访问每个坐标,而不是图像列表。您可以根据用于渲染线条的坐标计算面积/边界。

其他上下文和代码可能会有所帮助,我不确定我是否完全理解您要完成的任务!

【讨论】:

如果您发布您的绘画/绘图方法会很有帮助,以便我自己或其他人可以更轻松地完成。【参考方案2】:

我看看 MVPaint 项目。看来你有一个对象:

MVPaintDrawing_drawing;

其中包含MVPaintTransaction 的数组。您可以迭代那些MVPaintTransaction 以绘制UIImage

所以首先你可以添加一个从MVPaintTransaction获取图像的方法:

- (UIImage *) imageToDrawWithSize:(CGSize) size xScale:(CGFloat)xScale yScale:(CGFloat)yScale 

    UIGraphicsBeginImageContext(size);
    CGContextScaleCTM(UIGraphicsGetCurrentContext(), xScale, yScale);

    // call the existing draw method    
    [self draw];

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;

然后在MVPaintDrawing类中添加一个方法,从MVPaintTransaction的数组中获取图片数组:

- (NSArray *) getImagesFromDrawingOnSurface: (UIImageView *) surface xScale: (CGFloat) xScale yScale: (CGFloat) yScale

    NSMutableArray *imageArray = [NSMutableArray new];
    for (MVPaintTransaction * transaction in _drawing) 
        UIImage *image = [transaction imageToDrawWithSize:surface.frame.size xScale:xScale yScale:yScale];
        [imageArray addObject:image];
    

    return imageArray;

通过这种方式,您将拥有一个 UIImage 数组,对应于您绘制的每条线。如果您希望这些图像具有“最小”可能的尺寸(我的意思是没有额外的 alpha 部分),您可以申请 this method(我在 MVPaintTransaction 类中添加了它):

- (UIImage *)trimmedImage:(UIImage *)img 

    CGImageRef inImage = img.CGImage;
    CFDataRef m_DataRef;
    m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));

    UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef);

    size_t width = CGImageGetWidth(inImage);
    size_t height = CGImageGetHeight(inImage);

    CGPoint top,left,right,bottom;

    BOOL breakOut = NO;
    for (int x = 0;breakOut==NO && x < width; x++) 
        for (int y = 0; y < height; y++) 
            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) 
                left = CGPointMake(x, y);
                breakOut = YES;
                break;
            
        
    

    breakOut = NO;
    for (int y = 0;breakOut==NO && y < height; y++) 

        for (int x = 0; x < width; x++) 

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) 
                top = CGPointMake(x, y);
                breakOut = YES;
                break;
            

        
    

    breakOut = NO;
    for (int y = height-1;breakOut==NO && y >= 0; y--) 

        for (int x = width-1; x >= 0; x--) 

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) 
                bottom = CGPointMake(x, y);
                breakOut = YES;
                break;
            

        
    

    breakOut = NO;
    for (int x = width-1;breakOut==NO && x >= 0; x--) 

        for (int y = height-1; y >= 0; y--) 

            int loc = x + (y * width);
            loc *= 4;
            if (m_PixelBuf[loc + 3] != 0) 
                right = CGPointMake(x, y);
                breakOut = YES;
                break;
            

        
    


    CGFloat scale = img.scale;

    CGRect cropRect = CGRectMake(left.x / scale, top.y/scale, (right.x - left.x)/scale, (bottom.y - top.y) / scale);
    UIGraphicsBeginImageContextWithOptions( cropRect.size,
                                           NO,
                                           scale);
    [img drawAtPoint:CGPointMake(-cropRect.origin.x, -cropRect.origin.y)
            blendMode:kCGBlendModeCopy
                alpha:1.];
    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CFRelease(m_DataRef);
    return croppedImage;

然后在第一种方法中简单地替换:

return result;

通过

return [self trimmedImage:result];

【讨论】:

好吧,我在发布之前也尝试过,如果我调用 getImagesFromDrawingOnSurface,我会得到一个 UIImage 数组(每个图像代表一条绘制的线,这就是你所要求的)。我的代码不会改变线条的显示方式(例如,您可能需要创建 UIImageView 数组)。

以上是关于只为绘制的特定区域边界获取 UIImage - PaintView的主要内容,如果未能解决你的问题,请参考以下文章

iOS - Swift - UIImage 上的可点击区域

百度地图行政区绘制

如何获取特定点击点中UIImage的RGBA值

创建特定大小的 UIImage

查找具有内容的区域并获取其边界矩形

在 UIImage 上突出显示(覆盖)特定区域