在 ios 中从 UIImage 中删除线条
Removing lines from UIImage in ios
我在 UIImageView 中有一张图片。我在图像上画了线条 sucdcessfully.Now 我想删除用户将在其上执行长按手势的特定线条。我怎样才能做到这一点 ?我的代码是:
{
// gets the location in the form of (x,y) coordinates
CGPoint location=[sender locationInView:imageView];
// convetrs the location relative to the image
CGPoint contextLocation = CGPointMake(location.x*imageView.image.size.width/imageView.frame.size.width, location.y*imageView.image.size.height/imageView.frame.size.height);
// converts the location point into NSValue
NSValue *imagePoint=[NSValue valueWithCGPoint:contextLocation];
// Adds the image into NSMutable Array
[imageLocations addObject:imagePoint];
// color of line
UIColor * linearcolor=[UIColor blueColor];
UIGraphicsBeginImageContext(imageView.image.size);
[imageView.image drawAtPoint:CGPointMake(0, 0)];
CGContextRef context=UIGraphicsGetCurrentContext();
// Brush widt
CGContextSetLineWidth(context, 3.0);
// Line Color
CGContextSetStrokeColorWithColor(context, [linearcolor CGColor]);
// Hard coded point for location 2
CGPoint location2=CGPointMake(300, 400);
CGContextMoveToPoint(context, contextLocation.x, contextLocation.y);
CGContextAddLineToPoint(context, location2.x, location2.y);
CGContextStrokePath(context);
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image=newImage;
}
很简单。我在下面添加我的代码作为您的问题。
// gets the location in the form of (x,y) coordinates
CGPoint location=[sender locationInView:imageView];
// convetrs the location relative to the image
CGPoint contextLocation = CGPointMake(location.x*imageView.image.size.width/imageView.frame.size.width, location.y*imageView.image.size.height/imageView.frame.size.height);
// converts the location point into NSValue
NSValue *imagePoint=[NSValue valueWithCGPoint:contextLocation];
// Adds the image into NSMutable Array
[imageLocations addObject:imagePoint];
// color of line
UIColor * linearcolor=[UIColor blueColor];
UIGraphicsBeginImageContext(imageView.image.size);
[imageView.image drawAtPoint:CGPointMake(0, 0)];
CGContextRef context=UIGraphicsGetCurrentContext();
// Brush widt
CGContextSetLineWidth(context, 3.0);
**CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);**
// Hard coded point for location 2
CGPoint location2=CGPointMake(300, 400);
CGContextMoveToPoint(context, contextLocation.x, contextLocation.y);
CGContextAddLineToPoint(context, location2.x, location2.y);
CGContextStrokePath(context);
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image=newImage;
}
希望这是 helpful.Enjoy。
您需要做的是找到按下的线并将其从您拥有的点数组中删除,然后使用这些线重新绘制整个图像。
我想问题在于如何找到正确的行:
假设您有一个位置 L
从手势中获取。那么你需要的是遍历所有的点对如
for(NSInteger i=0; i< imageLocations.count.count-1; i+=2)
{
CGPoint T1 = [imageLocations[i] CGPointValue];
CGPoint T2 = [imageLocations[i+1] CGPointValue];
}
现在您有积分 L
、T1
、T2
。从这里开始,有很多方法可以检测线是否被击中。我最喜欢的是首先使用点积来查看印刷机是否在线附近,如下所示:
CGFloat dotValue = dot(normalized(T1-L), normalized(T2-L))
在网上找到点积和点归一化的程序。现在 dotValue
应该接近 -1 才能命中该行。你应该使用 if(dotValue > -.7f) continue;
之类的东西来删除所有离印刷机太远的线。
接下来就是实际求出点到线的距离。这实际上是一个叉积的 Z 分量:
CGFloat crossValue = fabsf(cross((L-T1), normalized(T2-T1)).z);
我知道你没有 Z 组件所以使用:
crossValue = A.x*B.y - A.y*B.x
所以现在你已经有了所有这些伪代码应该是这样的:
CGPoint L;
NSInteger bestLineIndex = -1;
CGFloat bestLineDistance = 10000.0f; // something large
for (CGPoint T1, T2; NSInteger index)
{
dotValue = ...
if(dotValue < -.7)
{
crossValue = ...
if(crossValue < bestLineDistance)
{
bestLineDistance = crossValue;
bestLineIndex = index;
}
}
}
所以最后你有第一条线点的索引,如果不是 -1(如果 -1 在触摸附近没有找到线),应该删除它。
对于使用叉积的点的直线距离:
- (CGFloat)distanceBetweenPoint:(CGPoint)L andLineWithStart:(CGPoint)T1 end:(CGPoint)T2
{
CGPoint T1toL = CGPointMake(L.x-T1.x, L.y-T1.y);
CGPoint T2toL = CGPointMake(L.x-T2.x, L.y-T2.y);
CGFloat T2toLDistance = sqrt(T2toL.x*T2toL.x + T2toL.y*T2toL.y);
CGPoint T2toLNormalized = CGPointMake(T2toL.x/T2toLDistance, T2toL.y/T2toLDistance);
CGFloat zComponentOfCross = T1toL.x*T2toLNormalized.y - T1toL.y*T2toLNormalized.x;
return fabs(zComponentOfCross);
}
我在 UIImageView 中有一张图片。我在图像上画了线条 sucdcessfully.Now 我想删除用户将在其上执行长按手势的特定线条。我怎样才能做到这一点 ?我的代码是:
{
// gets the location in the form of (x,y) coordinates
CGPoint location=[sender locationInView:imageView];
// convetrs the location relative to the image
CGPoint contextLocation = CGPointMake(location.x*imageView.image.size.width/imageView.frame.size.width, location.y*imageView.image.size.height/imageView.frame.size.height);
// converts the location point into NSValue
NSValue *imagePoint=[NSValue valueWithCGPoint:contextLocation];
// Adds the image into NSMutable Array
[imageLocations addObject:imagePoint];
// color of line
UIColor * linearcolor=[UIColor blueColor];
UIGraphicsBeginImageContext(imageView.image.size);
[imageView.image drawAtPoint:CGPointMake(0, 0)];
CGContextRef context=UIGraphicsGetCurrentContext();
// Brush widt
CGContextSetLineWidth(context, 3.0);
// Line Color
CGContextSetStrokeColorWithColor(context, [linearcolor CGColor]);
// Hard coded point for location 2
CGPoint location2=CGPointMake(300, 400);
CGContextMoveToPoint(context, contextLocation.x, contextLocation.y);
CGContextAddLineToPoint(context, location2.x, location2.y);
CGContextStrokePath(context);
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image=newImage;
}
很简单。我在下面添加我的代码作为您的问题。
// gets the location in the form of (x,y) coordinates
CGPoint location=[sender locationInView:imageView];
// convetrs the location relative to the image
CGPoint contextLocation = CGPointMake(location.x*imageView.image.size.width/imageView.frame.size.width, location.y*imageView.image.size.height/imageView.frame.size.height);
// converts the location point into NSValue
NSValue *imagePoint=[NSValue valueWithCGPoint:contextLocation];
// Adds the image into NSMutable Array
[imageLocations addObject:imagePoint];
// color of line
UIColor * linearcolor=[UIColor blueColor];
UIGraphicsBeginImageContext(imageView.image.size);
[imageView.image drawAtPoint:CGPointMake(0, 0)];
CGContextRef context=UIGraphicsGetCurrentContext();
// Brush widt
CGContextSetLineWidth(context, 3.0);
**CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);**
// Hard coded point for location 2
CGPoint location2=CGPointMake(300, 400);
CGContextMoveToPoint(context, contextLocation.x, contextLocation.y);
CGContextAddLineToPoint(context, location2.x, location2.y);
CGContextStrokePath(context);
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image=newImage;
}
希望这是 helpful.Enjoy。
您需要做的是找到按下的线并将其从您拥有的点数组中删除,然后使用这些线重新绘制整个图像。
我想问题在于如何找到正确的行:
假设您有一个位置 L
从手势中获取。那么你需要的是遍历所有的点对如
for(NSInteger i=0; i< imageLocations.count.count-1; i+=2)
{
CGPoint T1 = [imageLocations[i] CGPointValue];
CGPoint T2 = [imageLocations[i+1] CGPointValue];
}
现在您有积分 L
、T1
、T2
。从这里开始,有很多方法可以检测线是否被击中。我最喜欢的是首先使用点积来查看印刷机是否在线附近,如下所示:
CGFloat dotValue = dot(normalized(T1-L), normalized(T2-L))
在网上找到点积和点归一化的程序。现在 dotValue
应该接近 -1 才能命中该行。你应该使用 if(dotValue > -.7f) continue;
之类的东西来删除所有离印刷机太远的线。
接下来就是实际求出点到线的距离。这实际上是一个叉积的 Z 分量:
CGFloat crossValue = fabsf(cross((L-T1), normalized(T2-T1)).z);
我知道你没有 Z 组件所以使用:
crossValue = A.x*B.y - A.y*B.x
所以现在你已经有了所有这些伪代码应该是这样的:
CGPoint L;
NSInteger bestLineIndex = -1;
CGFloat bestLineDistance = 10000.0f; // something large
for (CGPoint T1, T2; NSInteger index)
{
dotValue = ...
if(dotValue < -.7)
{
crossValue = ...
if(crossValue < bestLineDistance)
{
bestLineDistance = crossValue;
bestLineIndex = index;
}
}
}
所以最后你有第一条线点的索引,如果不是 -1(如果 -1 在触摸附近没有找到线),应该删除它。
对于使用叉积的点的直线距离:
- (CGFloat)distanceBetweenPoint:(CGPoint)L andLineWithStart:(CGPoint)T1 end:(CGPoint)T2
{
CGPoint T1toL = CGPointMake(L.x-T1.x, L.y-T1.y);
CGPoint T2toL = CGPointMake(L.x-T2.x, L.y-T2.y);
CGFloat T2toLDistance = sqrt(T2toL.x*T2toL.x + T2toL.y*T2toL.y);
CGPoint T2toLNormalized = CGPointMake(T2toL.x/T2toLDistance, T2toL.y/T2toLDistance);
CGFloat zComponentOfCross = T1toL.x*T2toLNormalized.y - T1toL.y*T2toLNormalized.x;
return fabs(zComponentOfCross);
}