Ich möchte ein CATiledLayer in iPhone OS 3.1.3 verwenden, und dazu muss alle Zeichnung in -(void)drawLayer:(CALayer *)layer inContext:(CGContext)context
nur mit Core Graphics getan werden.Zeichnen in CATiledLayer mit CoreGraphics CGContextDrawImage
Jetzt laufe ich in die Probleme der gewendeten Koordinatensystem auf dem iPhone, und es gibt einige Vorschläge, wie man es beheben Transformationen mit:
Mein Problem ist, dass ich es nicht zur Arbeit bringen kann. Ich habe den PhotoScroller-Beispielcode verwendet und die Zeichenmethode nur durch coregraphics-Aufrufe ersetzt. Es sieht aus wie dieses
- (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);
}
Wie man sehen kann ich ein Scale-Transformation bin mit dem Koordinatensystem invertieren und eine Übersetzung verwandeln den Ursprung der linken unteren Ecke zu verschieben. Die Bilder werden korrekt gezeichnet, aber nur die erste Reihe von Kacheln wird gezeichnet. Ich denke, es gibt ein Problem mit der Übersetzungsoperation oder der Art, wie die Koordinaten der Kacheln berechnet werden.
Dies ist, wie es aussieht:
ich ein wenig verwirrt bin mit all diesen Transformationen.
Bonus Frage: Wie würde man die Retina-Display-Bilder in Kerngrafiken behandeln?
EDIT: Um es auf dem Retina-Display arbeitet Ich habe gerade die ursprüngliche Methode aus dem Beispielcode die Bilder zur Verfügung zu stellen:
- (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;
}
Im Prinzip ist die Skalierung der Anzeige, da Kern ignoriert Die Grafik arbeitet in Pixel nicht Punkte also, wenn aufgefordert, mehr Pixel zu zeichnen, mehr CATiledLayers (oder Sublayer) werden verwendet, um den Bildschirm zu füllen.
Thanks a lot Thomas
Danke für Ihre Antwort. Kann man nicht einfach die Methode [[UIImage imageNamed: @ "imageName"] CGImage] verwenden, um das richtige Bild für die Retina-Anzeige zu erhalten, da die UIImage-Methode die richtige Auflösung erhalten sollte? – GorillaPatch
Es funktioniert wirklich gut! Vielen Dank! Ich benutze grundsätzlich die Methode aus dem Beispielcode, um die Bildkacheln bereitzustellen, so dass auf einem Retina-Display nur mehr Kacheln auf einer anderen Zoomskala angezeigt werden, um das Bild zu zeichnen. Ich habe die Methode zur ursprünglichen Frage hinzugefügt. – GorillaPatch