只为绘制的特定区域边界获取 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的主要内容,如果未能解决你的问题,请参考以下文章