2012-11-02 2 views
3

이것이 제 첫 질문입니다.CGImage를 비트 맵 컨텍스트에 그려서 UIBezierPath를 미리 컨텍스트에 그려 넣습니다.

기본적으로 간단한 그림 그리기 응용 프로그램을 작성하려고 시도한 Im은 전에 Core Graphics를 사용하고 있었고 유일한 문제는 너무 느리다는 것이 었습니다. 그리고 손가락으로 그렸을 때, 지옥이있었습니다!

그래서 이제는 훨씬 더 빨라 졌다고 이해 했으므로 이제 UIBezier 경로를 사용하여 그려 봅니다.

Core Graphics를 사용하여 드로잉 속도를 높이기 위해 필자가 만든 사용자 지정 비트 맵 컨텍스트로 드로잉을 진행했습니다.이 컨텍스트는 내가 그린대로 지속적으로 업데이트되었습니다.

그래서, 나는 내 사용자 지정 비트 맵 컨텍스트에 그린 다음, CGImageRef 사용하여 그 맥락에서 그려진 것과 설정 -

cacheImage = CGBitmapContextCreateImage(imageContext); 

을하고는 사용하여 다시 비트 맵 컨텍스트에 그려진 -

CGContextDrawImage(imageContext, self.bounds, cacheImage);) 

나는이 작업을 수행하여 그려지는 선의 색상을 변경했을 때, 나머지 도면은 이전에 그려진 것처럼 유지되었습니다.

이제 문제는 필자가 만났습니다. 사용하여 내 이미지 컨텍스트에 UIBezier 경로를 그릴려고

임 - 경로

imageContext = UIGraphicsGetCurrentContext(); 

UIGraphicsPushContext(imageContext); 


[path stroke]; 


if(imageContext != nil){ 
    cacheImage = CGBitmapContextCreateImage(imageContext); //invalid context here so added to solve 

} 


CGContextScaleCTM(imageContext, 1, -1); // using this as UIBezier 

CGContextDrawImage(imageContext, self.bounds, cacheImage); // draws the current context; 

[path removeAllPoints]; 

CGImageRelease(cacheImage); // releases the image to solve memory errors. 

내 UIBezierPath 것. 설정 한 모든 경로는 터치로 시작되고 터치 한 다음 이동하여 [self setNeedsDisplay]를 호출합니다. drawRect를 호출합니다.

상황에 따라 CGImageRef를 컨텍스트에 올바르게 그리지 않거나 캐시 이미지를 캡처 할 때 경로 대신에 흰색 배경을 캡처하는 경우가 있습니다. 흰색 배경 채우기와 함께 그려진 마지막 경로로 전체 이미지 위에 붙여 넣기 때문에보기 배경색이 clearColor 인 경우에도 이미지를 빌드하기 위해 그린 마지막 경로는 볼 수 없습니다.

나는 정말로 감각이 있기를 바란다. 나는 이것에 너무 많은 시간을 보냈다. Heres는 그리기 방법 내가 사용하고 -

-(CGContextRef) myCreateBitmapContext: (int) pixelsWide:(int) pixelsHigh{ 


    imageContext = NULL; 

    CGColorSpaceRef colorSpace; // creating a colorspaceref 
    void *   bitmapData; // creating bitmap data 
    int    bitmapByteCount; // the bytes per count 
    int    bitmapBytesPerRow; // number of bytes per row 

    bitmapBytesPerRow = (pixelsWide * 4); // calculating how many bytes per row the context  needs 
    bitmapByteCount  = (bitmapBytesPerRow * pixelsHigh); // how many bytes there are in  total 

    colorSpace = CGColorSpaceCreateDeviceRGB(); // setting the colourspaceRef 

    bitmapData = malloc(bitmapByteCount); // calculating the data 

    if (bitmapData == NULL) 
    { 
     //NSLog(@"Memory not allocated!"); 
     return NULL; 
    } 


    imageContext = CGBitmapContextCreate (bitmapData, 
              pixelsWide, 
              pixelsHigh, 
              8, // bits per component 
              bitmapBytesPerRow, 
              colorSpace,kCGImageAlphaPremultipliedLast); 

    if (imageContext== NULL) 
    { 
     free (bitmapData); 
     NSLog(@"context not created allocated!"); 
     return NULL; 
    } 
    CGColorSpaceRelease(colorSpace); //releasing the colorspace 

    CGContextSetRGBFillColor(imageContext, 1.0, 1.0, 1.0, 0.0); // filling the bitmap with a  white background 
    CGContextFillRect(imageContext, self.bounds); 
    CGContextSetShouldAntialias(imageContext, YES); 




    return imageContext; 
    } 

그리고 heres는 내 드로잉 - -

이 이미지 컨텍스트 만들

-(void)drawRect:(CGRect)rect 
{ 

    DataClass *data = [DataClass sharedInstance]; 



    [data.lineColor setStroke]; 
    [path setLineWidth:data.lineWidth]; 
    imageContext = UIGraphicsGetCurrentContext(); 

    UIGraphicsPushContext(imageContext); 


    [path stroke]; 


    if(imageContext != nil){ 
     cacheImage = CGBitmapContextCreateImage(imageContext); 
    } 


    CGContextScaleCTM(imageContext, 1, -1); // this one 


    CGContextDrawImage(imageContext, self.bounds, cacheImage); // draws the current  context; 



    [path removeAllPoints]; 

    CGImageRelease(cacheImage); // releases the image to solve memory errors. 



} 





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


    DataClass *data = [DataClass sharedInstance]; 

    CGContextSetStrokeColorWithColor(imageContext, [data.lineColor CGColor]); 

    ctr = 0; 
    UITouch *touch2 = [touches anyObject]; 
    pts[0] = [touch2 locationInView:self]; 

} 


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

    UITouch *touch = [touches anyObject]; 
    CGPoint p = [touch locationInView:self]; 


    ctr++; 
    pts[ctr] = p; 
    if (ctr == 4) 
    { 

     pts[3] = CGPointMake((pts[2].x + pts[4].x)/2.0, (pts[2].y + pts[4].y)/2.0); // move  the endpoint to the middle of the line joining the second control point of the first Bezier  segment and the first control point of the second Bezier segment 
     [path moveToPoint:pts[0]]; 
     [path addCurveToPoint:pts[3] controlPoint1:pts[1] controlPoint2:pts[2]]; // add a  cubic Bezier from pt[0] to pt[3], with control points pt[1] and pt[2] 
     //[data.lineColor setStroke]; 

     [self setNeedsDisplay]; 
     // replace points and get ready to handle the next segment 
     pts[0] = pts[3]; 
     pts[1] = pts[4]; 
     ctr = 1; 
    } 
} 


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

    [path removeAllPoints]; 
    [self setNeedsDisplay]; 
    ctr = 0; 
} 

'경로'를 내 UIBezierPath 'cacheImage'된다 CGImageRef 'imageContext'는 CGContextRef입니다.

어떤 도움을 많이 받으실 수 있습니다! 그리고 당신이 더 나은 방법을 생각할 수 있다면, 제게 알려주세요! 그러나 캐시 이미지에 투명한 배경이 있어야하므로 경로를 볼 수 있습니다. 나중에이 기능을 사용할 때 나중에 적용 할 예정입니다.

EDIT 또한 드로잉 속도를 유지하기 위해 매번 포인트를 제거하고 있습니다.

미리 감사드립니다. :)

답변

1

음, 이것이 큰 질문입니다. 하나의 잠재적 인 단서는 당신이 필요로하는 것 (항상 전체 이미지가 아닌)을 정확히 그리는 지, 그리고 불변 비트 맵을 여러 레이어에 걸쳐 활발히 변형되는 영역/rect로 나누는 지 확인하는 것입니다.

+0

당신이 정말로 무엇을 의미하는지 확실히 모르겠다. 나는 xcode에 대해 매우 익숙하다. 정말 짜증나는 것은 코어 그래픽에서 놀랍다. 그러나 오래된 3 세대 아이팟 터치에서만, 새로운 것은 내가 미쳐 버렸다. 이해 이유 :/ – thebigpeeler

+1

좋습니다. CALayers라는 기술이 있습니다. 변이 된 비트 맵에서 불변 비트 맵/이미지를 나눌 것을 제안했습니다. 이 작업을 올바르게 수행하면 모든 업데이트/다시 그리기가 변경된 항목 (및 더 이상 표시되지 않은 항목)으로 현지화 될 수 있습니다. 가치가있는 고려 사항 : 3 세대 iPod touch는 앱의 시각이 표시 될 때 표시 할 최소 가시 픽셀 수를 가질 가능성이 높습니다. 도구로 프로파일 링하는 것이 도움이 될 수 있지만 이미 프로그램에서 많은 시간을 소모하는 것으로 나타났습니다. – justin

+0

예, 새로운 비트 맵을 그리는 데 너무 많은 시간을 소비해야합니다. 이전의 코어 그래픽 코드에서 각 포인트 투 포인트 경로 이후에 새로운 비트 맵을 그립니다. 그리드의 그리드를 만들고 드로잉 된 직사각형에서만 업데이트 된 이미지를 그릴 것을 제안합니까? 죄송합니다. 저는이 부분에서 정말로 새로운 것입니다. – thebigpeeler

관련 문제