我在StackOverflow中搜索所有问题和答案,但无法获得我想要的结果。我想使用PNG文件,在用户触摸和移动点显示为笔划。这是PNG文件:
但我在StackOverflow上做了所有的方法,即使使用CGPatternRef,但我没有我想要的结果。我的结果是:
但我想要的结果是:
这个结果我在OpenGL ES中完成了,但我不能在Core Graphics中做到这一点。我想我可以在每个点使用CGContextDrawImage,但这种方式导致性能不佳,因为我必须在用户触摸的2点之间绘制所有点的图像。我想你之前遇到过这个问题。你认为我可以在Core Graphics中应用纹理来绘制这样的笔画吗?我非常感激。
答案 0 :(得分:4)
使用图案创建线条时,它看起来像第一个图像,而不是第二个图像。该线条只是将您提供的纹理图像平铺成线条的形状。没有办法让它知道你想要将圆圈合并在一起看起来像一条实线。为此你应该只用一个纯黑色的线。
对于任何想要在第一张图片中实现图案线条的人来说,有一个很好的教程解释如何在这里执行此操作:http://blog.robertturrall.com/tag/cgcontextsetstrokepattern/
基本上你需要的是:
// first define the pattern width and height
const float kPatternWidth = 8;
const float kPatternHeight = 8;
void DrawPatternCellCallback(void *info, CGContextRef cgContext)
{
// Create a CGImage and use CGContextDrawImage() to draw it into the graphics context provided by the callback function.
UIImage *patternImage = [UIImage imageNamed:@"yourtextureimage.png"];
CGContextDrawImage(cgContext, CGRectMake(0, 0, kPatternWidth, kPatternHeight), patternImage.CGImage);
}
确保“void”周围没有括号。还要确保DrawPatternCellCallback部分在drawRect之前出现,否则它将无效。
然后你的drawRect需要以下内容:
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
const CGRect patternBounds = CGRectMake(0, 0, kPatternWidth, kPatternHeight);
const CGPatternCallbacks kPatternCallbacks = {0, DrawPatternCellCallback, NULL};
CGAffineTransform patternTransform = CGAffineTransformIdentity;
CGPatternRef strokePattern = CGPatternCreate(
NULL,
patternBounds,
patternTransform,
kPatternWidth, // horizontal spacing
kPatternHeight, // vertical spacing
kCGPatternTilingNoDistortion,
true,
&kPatternCallbacks);
CGFloat color1[] = {1.0, 1.0, 1.0, 1.0};
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
CGContextSetStrokeColorSpace(ctx, patternSpace);
CGContextSetStrokePattern(ctx, strokePattern, color1);
CGContextSetLineWidth(ctx, 4.0);
CGContextDrawPath(ctx);
// If you aren't using ARC:
CGPatternRelease(strokePattern);
strokePattern = NULL;
CGColorSpaceRelease(patternSpace);
patternSpace = NULL;
}
答案 1 :(得分:2)
严重 ......
例如,如果您正在做一个将图像的模糊版本绘制在自身上的常见问题。您几乎肯定需要这样的代码......
float isf;
isf = [[UIScreen mainScreen] bounds].size.width / wholeImageWidth;
(如果您正在全屏绘图;如果在窗口中绘图,则以明显的方式调整)其中wholeImageWidth是您正在编辑的图像的实际宽度。
然后当你创建笔划模式时,你可以像这样使用
CGAffineTransformScale( CGAffineTransformIdentity, isf, -isf)
但是请注意,你可能不得不为相机和相册重新调整它。所以像.......
if ( self.wasFromCameraNotAlbum )
{
strokePattern = CGPatternCreate(
NULL,
CGRectMake(0,0,wholeWidth,wholeHeight),
CGAffineTransformConcat(
CGAffineTransformScale( CGAffineTransformIdentity, isf, -isf),
CGAffineTransformRotate( CGAffineTransformIdentity, 90*M_PI/180 )
),
wholeWidth,wholeHeight,
kCGPatternTilingNoDistortion, true, &kPatternCallbacks);
}
else
{
strokePattern = CGPatternCreate(
NULL,
CGRectMake(0,0,wholeWidth,wholeHeight),
CGAffineTransformScale( CGAffineTransformIdentity, isf, -isf),
wholeWidth,wholeHeight,
kCGPatternTilingNoDistortion, true, &kPatternCallbacks);
}
对于谷歌搜索,这是由于相机,旋转,iPhone 6 +,iOS8,相册。
因为llama591的答案太棒了。这里有一些示例代码可能有一天会帮助某人。这是我可以为模式绘图编写的最简单的代码:
这适用于Xcode5 / iOS7(2014年1月):
这是一些非常典型的绘制蓝色线条的绘图代码:
-(void)drawRect:(CGRect)rect
{
[curImage drawAtPoint:CGPointMake(0, 0)];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context,
previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 20.0);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextStrokePath(context);
[super drawRect:rect];
}
注意调用 CGContextSetStrokeColorWithColor ,它只是将该行设置为实线,在本例中为蓝色。
接下来是相同的代码。但是,我们替换了一行代码,用于绘制模式的所有代码。 (并且还有一个新的单独的回调例程,这是微不足道的。)
为清楚起见,这里只有15行代码,它将取代单个简单的StrokeColor代码行:
const CGPatternCallbacks kPatternCallbacks = {0, simplePatternCallback, NULL};
CGFloat color1[] = {1.0, 1.0, 1.0, 1.0};
CGPatternRef strokePattern = CGPatternCreate(
NULL,
CGRectMake(0,0,100,100),
CGAffineTransformIdentity,
100,100,
kCGPatternTilingNoDistortion,
true,
&kPatternCallbacks);
CGContextSetStrokeColorSpace(UIGraphicsGetCurrentContext(),
CGColorSpaceCreatePattern(NULL););
CGContextSetStrokePattern(context, strokePattern, color1);
CGPatternRelease(strokePattern);
strokePattern = NULL;
模式应该是项目中的PNG,可以说是100x100像素,这里称为“pattern100100.png”。
同样,我用代码的15行代码替换了1行代码。 (而且还有一个单独的简单回调函数。)以下是整个事情:
-(void)drawRect:(CGRect)rect
{
[curImage drawAtPoint:CGPointMake(0, 0)];
CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
CGPoint mid2 = midPoint(currentPoint, previousPoint1);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context,
previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 20.0);
const CGPatternCallbacks kPatternCallbacks = {0, simplePatternCallback, NULL};
CGFloat color1[] = {1.0, 1.0, 1.0, 1.0};
CGPatternRef strokePattern = CGPatternCreate(
NULL,
CGRectMake(0,0,100,100),
CGAffineTransformIdentity,
100,100,
kCGPatternTilingNoDistortion,
true,
&kPatternCallbacks);
CGContextSetStrokeColorSpace(UIGraphicsGetCurrentContext(),
CGColorSpaceCreatePattern(NULL););
CGContextSetStrokePattern(context, strokePattern, color1);
CGPatternRelease(strokePattern);
strokePattern = NULL;
CGContextStrokePath(context);
[super drawRect:rect];
}
void simplePatternCallback(void *info, CGContextRef ctx)
{
UIImage *brushTexture = [UIImage imageNamed:@"pattern100100.png"];
CGContextDrawImage(ctx, CGRectMake(0, 0, 100,100), brushTexture.CGImage);
}
要在代码中包含几条有用的评论!
// re the final argument:
// from Apple doco: "If the specified pattern is a 'colored' pattern,
// pass an alpha value."
// in fact you have to pass in an array of four values.
// note, "stencil patterns" (aka "uncolored patterns") patterns
// are basically masks, rarely used
// re the "true" in CGPatternCreate, that means "coloured pattern"
// (ie not "stencil pattern")
我真的希望它有所帮助。
注意:每当您看到这样的代码示例时(即使在Apple)。他们总是“在drawRect内”完成整个事情。请注意,每次调用drawRect时都会创建“strokePattern”!对我来说,这似乎很疯狂,我总是简单地使用变量或属性“strokePattern”和其他元素。同样地,每次在回调中使用imageNamed都是荒谬的,只需使用您之前准备的属性。
我真的希望它可以帮助某人。干杯
有用的脚注:在CGPaternCreate中,示例代码显示参数3的CGAffineTransformIdentity。
通常,您会使用某些照片或其他动态图像。在那种情况下,几乎肯定会是......
CGAffineTransformScale(CGAffineTransformIdentity,1,-1),
照顾核心图形中的颠倒比例。希望它有所帮助。
答案 2 :(得分:0)
感谢您的链接,llama591。
Haisergeant,如果您正在寻找的是使用第一个示例中的纹理的粗线,那么您将需要使用kPatternWidth和kPatternHeight值,以及您在其中传递的值。 line CGContextSetLineWidth(ctx,4.0);。
我还必须修改我用过的纹理图像,以确保它的边缘上有很少的空白,因为这会在线条中引入白色间隙,如示例所示。