2011-07-09 33 views
3

我搜索StackOverflow中的所有問題和答案,但無法獲得我想要的結果。我想使用PNG文件,在用戶觸摸和移動的位置顯示爲筆劃。這是PNG文件:iphone:將紋理應用到CGContextStrokePath

enter image description here

但我確實在計算器上,即使使用CGPatternRef所有的方式,但我沒有我想要的結果。結果我就在這裏:

enter image description here

但我想有結果是在這裏:

enter image description here

這個結果我已經在OpenGL ES做,但我不能這樣做在覈心圖形。我認爲我可以在每個點使用CGContextDrawImage,但這種方式會導致較差的性能,因爲我必須繪製圖像中用戶觸摸的2個點之間的所有點。我想你以前遇到過這個問題。你認爲我可以在Core Graphics中應用紋理來繪製這種筆畫嗎?我非常感謝。

+0

hai sergeant!你有沒有解決這個問題?它花了很長時間回答:) – Fattie

回答

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); 
} 

確保「無效「周圍沒有括號。還要確保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; 
} 
+2

我很確定你需要「CGPatternRelease(strokePattern);」即使你使用ARC。它只適用於objetive-c對象,而不是象CoreGraphics這樣的直接C代碼。 – Ralphleon

+0

我相信這是「singleton」示例代碼:這是在整個互聯網上模式繪製的唯一簡單示例代碼:)幹得好,恭喜... – Fattie

0

感謝您的鏈接,llama591。如果你正在尋找的是使用第一個例子中的紋理的好粗線,那麼你需要使用kPatternWidth和kPatternHeight值,以及你通過的值行CGContextSetLineWidth(ctx,4.0);.

我還必須修改紋理圖像,以確保邊緣上幾乎沒有空白,因爲這會在行中引入白色間隙,如示例中所示。

2

關鍵 ...

,如果你正在做的繪製圖像的模糊版本超過本身,例如常見的事情。

你幾乎肯定會需要這樣的代碼...

float isf; 
isf = [[UIScreen mainScreen] bounds].size.width/wholeImageWidth; 

(也就是,如果你正在繪製全屏;調整明顯的方式,如果在一個窗口中繪製),其中wholeImageWidth是您正在編輯的圖像的實際寬度。

那麼當您創建行程模式使用,像這樣

CGAffineTransformScale(CGAffineTransformIdentity, isf, -isf) 

,但指出的是煩人,你可能需要不同的reotate它的攝像頭和專輯。所以像.......

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,示例代碼顯示CGAffineTransformIdentity爲參數3。

通常,你會使用一些照片或其他動態圖像。在這種情況下,幾乎可以肯定它會...

CGAffineTransformScale(CGAffineTransformIdentity,1,-1), 

照顧核心圖形的顛倒規模。希望能幫助到你。