2010-11-01 58 views
6

我想在iPhone OS 3.1.3中使用CATiledLayer,并且要这样做,所有在-(void)drawLayer:(CALayer *)layer inContext:(CGContext)context中的绘图必须仅使用coregraphics完成。使用CoreGraphics绘制CATiledLayer CGContextDrawImage

现在我碰上翻转的问题协调上的iPhone系统也有一些建议,如何使用变换来解决它:

我的问题是我无法让它工作。我开始使用PhotoScroller示例代码,并仅使用coregraphics调用替换绘图方法。它看起来像这样

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context { 
CGContextSaveGState(context); 
CGRect rect = CGContextGetClipBoundingBox(context); 
CGFloat scale = CGContextGetCTM(context).a; 
CGContextConcatCTM(context, CGAffineTransformMakeTranslation(0.f, rect.size.height)); 
CGContextConcatCTM(context, CGAffineTransformMakeScale(1.f, -1.f)); 

CATiledLayer *tiledLayer = (CATiledLayer *)layer; 
CGSize tileSize = tiledLayer.tileSize; 


tileSize.width /= scale; 
tileSize.height /= scale; 
// calculate the rows and columns of tiles that intersect the rect we have been asked to draw 
int firstCol = floorf(CGRectGetMinX(rect)/tileSize.width); 
int lastCol = floorf((CGRectGetMaxX(rect)-1)/tileSize.width); 
int firstRow = floorf(CGRectGetMinY(rect)/tileSize.height); 
int lastRow = floorf((CGRectGetMaxY(rect)-1)/tileSize.height); 
for (int row = firstRow; row <= lastRow; row++) { 
    for (int col = firstCol; col <= lastCol; col++) { 
    // if (row == 0) continue; 
     UIImage *tile = [self tileForScale:scale row:row col:col]; 
     CGImageRef tileRef = [tile CGImage]; 
     CGRect tileRect = CGRectMake(tileSize.width * col, tileSize.height * row, 
            tileSize.width, tileSize.height); 
     // if the tile would stick outside of our bounds, we need to truncate it so as to avoid 
     // stretching out the partial tiles at the right and bottom edges 
     tileRect = CGRectIntersection(self.bounds, tileRect); 
     NSLog(@"row:%d, col:%d, x:%.0f y:%.0f, height:%.0f, width:%.0f", row, col,tileRect.origin.x, tileRect.origin.y, tileRect.size.height, tileRect.size.width); 

     //[tile drawInRect:tileRect]; 
     CGContextDrawImage(context, tileRect, tileRef); 
// just to draw the row and column index in the tile and mark the origin of the tile with a red line   
     if (self.annotates) { 
      CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor]CGColor]); 
      CGContextSetLineWidth(context, 6.0/scale); 
      CGContextStrokeRect(context, tileRect); 
      CGContextSetStrokeColorWithColor(context, [[UIColor redColor]CGColor]); 
      CGContextMoveToPoint(context, tileRect.origin.x, tileRect.origin.y); 
      CGContextAddLineToPoint(context, tileRect.origin.x+100.f, tileRect.origin.y+100.f); 
      CGContextStrokePath(context); 
      CGContextSetStrokeColorWithColor(context, [[UIColor redColor]CGColor]); 
      CGContextSetFillColorWithColor(context, [[UIColor whiteColor]CGColor]); 
      CGContextSelectFont(context, "Courier", 128, kCGEncodingMacRoman); 
      CGContextSetTextDrawingMode(context, kCGTextFill); 
      CGContextSetShouldAntialias(context, true); 
      char text[30]; 
      int length = sprintf(text,"row:%d col:%d",row,col); 
      CGContextSaveGState(context); 
      CGContextShowTextAtPoint(context, tileRect.origin.x+110.f,tileRect.origin.y+100.f, text, length); 
      CGContextRestoreGState(context); 
     } 
    } 
} 

CGContextRestoreGState(context); 

}

正如你可以看到我用一个尺度变换反转坐标系和平移变换到原点转移到左下角。图像正确绘制,但只绘制第一排瓷砖。我认为翻译操作存在问题,或者瓷砖的坐标计算方式有问题。

这是它的样子:

我有点糊涂了这一切转变。

奖励问题: 如何处理核心图形中的视网膜显示图片?

编辑: 得到它的工作视网膜显示我只是把原来的方法从示例代码上提供的图片:

- (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col 
{ 
// we use "imageWithContentsOfFile:" instead of "imageNamed:" here because we don't want UIImage to cache our tiles 
NSString *tileName = [NSString stringWithFormat:@"%@_%d_%d_%d", imageName, (int)(scale * 1000), col, row]; 
NSString *path = [[NSBundle mainBundle] pathForResource:tileName ofType:@"png"]; 
UIImage *image = [UIImage imageWithContentsOfFile:path]; 
return image; 
} 

原则,因为核心的显示比例被忽略图形工作在像素不是点因此,当要求绘制更多的像素时,更多的CATiledLayers(或子图层)用于填充屏幕。

非常感谢 托马斯

回答

11

托马斯,我开始跟随WWDC 2010滚动型的谈话并没有在内部drawLayer:inContext工作的iOS 3.x中很少或根本没有文件当我将演示代码从drawRect:转移到drawLayer:inContext:时,我遇到了同样的问题。

一些调查表明我内drawLayer:inContext:的大小和从CGContextGetClipBoundingBox(context)返回rect偏移量是要绘制。如果drawRect:为您提供了全范围到底是什么。

知道了这一点,您可以删除行和列迭代,以及边缘切片的CGRect交点,并在您翻译上下文后直接绘制到矩形。

这里是我已经结束了:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx { 
    CGRect rect = CGContextGetClipBoundingBox(ctx); 
    CGFloat scale = CGContextGetCTM(ctx).a; 

    CATiledLayer *tiledLayer = (CATiledLayer *)[self layer]; 
    CGSize tileSize = tiledLayer.tileSize; 
    tileSize.width /= scale; 
    tileSize.height /= scale; 

    int col = floorf((CGRectGetMaxX(rect)-1)/tileSize.width); 
    int row = floorf((CGRectGetMaxY(rect)-1)/tileSize.height); 

    CGImageRef image = [self imageForScale:scale row:row col:col]; 

    if(NULL != image) { 
    CGContextTranslateCTM(ctx, 0.0, rect.size.height); 
    CGContextScaleCTM(ctx, 1.0, -1.0); 
    rect = CGContextGetClipBoundingBox(ctx); 

    CGContextDrawImage(ctx, rect, image); 
    CGImageRelease(image); 
    } 
} 

注意rectTranslateCTMScaleCTM后重新定义。

以供参考这里是我的imageForScale:row:col功能:

- (CGImageRef) imageForScale:(CGFloat)scale row:(int)row col:(int)col { 
    CGImageRef image = NULL; 
    CGDataProviderRef provider = NULL; 
    NSString *filename = [NSString stringWithFormat:@"img_name_here%0.0f_%d_%d",ceilf(scale * 100),col,row]; 
    NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:@"png"]; 

    if(path != nil) { 
    NSURL *imageURL = [NSURL fileURLWithPath:path]; 

    provider = CGDataProviderCreateWithURL((CFURLRef)imageURL); 

    image = CGImageCreateWithPNGDataProvider(provider,NULL,FALSE,kCGRenderingIntentDefault); 
    CFRelease(provider); 
    } 
    return image; 
} 

仍然有一些工作是为了正确地支持高分辨率的图形上这两个函数完成,但它确实看起来不错的一切,但一个iPhone 4.

+0

感谢您的回答。不能只使用[[UIImage imageNamed:@“imageName”] CGImage]方法来获得正确的视网膜显示图像,因为UIImage方法应该得到正确的分辨率? – GorillaPatch 2010-11-02 10:11:04

+0

它真的很好用!谢谢!我基本上使用从示例代码中提取的方法来提供图像切片,因此在视网膜显示器上,它只是以不同的缩放比例显示更多的切片来绘制图像。我将该方法添加到原始问题中。 – GorillaPatch 2010-11-03 08:24:27

相关问题