2011-12-17 24 views
6

chłopaki, to mój kod:CGContext i wyświetlacz Retina

- (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx { 
    //background 
    CGContextSetFillColorWithColor(ctx, [[UIColor colorWithRed:((float)238/255.0f) green:((float)233/255.0f) blue:((float)215/255.0f) alpha:1] CGColor]); 
    CGContextFillRect(ctx, CGRectInset(leavesView.bounds, 0, 0)); 
    //text 
    CGContextSetTextDrawingMode(ctx, kCGTextFill); 
    CGContextSetTextMatrix(ctx, CGAffineTransformMake(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)); 
    CGContextSetFillColorWithColor(ctx, [[UIColor blackColor] CGColor]); 
    UIGraphicsPushContext(ctx); 

    CGContextSaveGState(ctx); 
    CGContextTranslateCTM(ctx, 0.1f, leavesView.bounds.size.height); 
    CGContextScaleCTM(ctx, 1.0f, -1.0f); 

    CGRect textRect = CGRectMake(5, 5, leavesView.bounds.size.width-10, leavesView.bounds.size.height-10); 
    if (pages.count > 0 && pages.count-1 >= index) { 
     [[pages objectAtIndex:index] drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft]; 
    } 

    CGContextRestoreGState(ctx); 

    UIGraphicsPopContext(); 
} 

Działa on idealny na iPhone 2G, 3G, 3GS, ale na nowych modelach mam problemy.

Na tekście siatkówki narysowano, aby nie podwoić rozdzielczości, tak jak w standardzie.

Masz jakieś pomysły?

Odpowiedz

16

Spróbuj ustawić zmienną warstwy contentScale tak:

layer.contentsScale = [UIScreen mainScreen].scale; 

ten powinien uczynić kod dostosować do siatkówki/wyświetlaczy nonretina.

+0

o człowieku! Uratowałeś mi dzień. Naprawdę nie takie oczywiste. – orkenstein

+0

Podklasowałem CALayer i musiałem to zrobić w metodzie init. W metodzie drawWithContext zgłaszano błąd tylko do odczytu. –

3

Wygląda na to, że korzystasz z projektu Leaves na Git. Miałem ten sam problem w moim projekcie i rozwiązałem go w następujący sposób.

Najpierw należy powiększyć i skalować oryginalny kontekst Core Graphics utworzony w imageForPageIndex: w LeavesCache.m zgodnie ze skalą ekranu urządzeń. Upewnij się, że skalujesz także CGContextClipToRect.

- (CGImageRef) imageForPageIndex:(NSUInteger)pageIndex { 
    CGFloat scale = [[UIScreen mainScreen] scale]; // we need to size the graphics context according to the device scale 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(NULL, 
              pageSize.width*scale, 
              pageSize.height*scale, 
              8,      /* bits per component*/ 
              pageSize.width*scale * 4, /* bytes per row */ 
              colorSpace, 
              kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 

    CGColorSpaceRelease(colorSpace); 
    CGContextClipToRect(context, CGRectMake(0, 0, pageSize.width*scale, pageSize.height*scale)); 

    CGContextScaleCTM(context, scale, scale); 

    [dataSource renderPageAtIndex:pageIndex inContext:context]; 

    CGImageRef image = CGBitmapContextCreateImage(context); 
    CGContextRelease(context); 

    [UIImage imageWithCGImage:image]; 
    CGImageRelease(image); 

    return image; 
} 

Następnie w setUpLayers w LeavesView.m, będziesz musiał zastosować skalę ekranu urządzenie do każdego CALayer który pobiera zainicjowany. Jak opublikował Brad Larson w similar question:

Domyślnie Twoja CALayer nie renderuje zawartości Quartz w wyższej rozdzielczości ekranu wyświetlacza Retina. Można włączyć to przy użyciu kodu tak:

layer.contentsScale = [[UIScreen mainScreen] scale]; 

Więc oto kilka pierwszych linii od setUpLayers w LeavesView.m gdzie mogę zastosować skalę urządzenia do topPage CALayer. Musisz to zrobić dla wszystkich CALayers i CAGradientLayers zainicjowane w setUpLayers:

- (void) setUpLayers { 
    // Set the backgound image of the leave view to the book page 
    UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"open_book_page_turn.png"]]; 

    self.clipsToBounds = YES; 

    topPage = [[CALayer alloc] init]; 
    topPage.contentsScale = [[UIScreen mainScreen] scale]; // We need to apply the device display scale to each layer 
    topPage.masksToBounds = YES; 
    topPage.contentsGravity = kCAGravityLeft; 
    topPage.backgroundColor = [[UIColor whiteColor] CGColor]; 
    topPage.backgroundColor = [background CGColor]; 

    ... 

} 
2

można po prostu ustawić skalę po uruchomieniu kontekst

+ (UIImage *)imageWithView:(UIView *)view { 
    UIGraphicsBeginImageContextWithOptions([view bounds].size, NO, [[UIScreen mainScreen] scale]); 

    [[view layer] renderInContext:UIGraphicsGetCurrentContext()]; 

    UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return result; 
} 
0

Dla Swift 3

func getImageFromContext() -> UIImage{ 

    UIGraphicsBeginImageContextWithOptions(self.frame.size, false, UIScreen.main.scale) 
    self.drawHierarchy(in: self.bounds, afterScreenUpdates: true) 
    self.layer.render(in: UIGraphicsGetCurrentContext()!) 
    let image = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 

    return image! 
} 
Powiązane problemy