2009-12-30 17 views
10

Tôi đang sử dụng NSView để lưu trữ một số đối tượng Hoạt ảnh chính CALayer. Những gì tôi muốn có thể làm là lấy một bản chụp trạng thái hiện tại của khung nhìn dưới dạng hình ảnh bitmap.Làm cách nào để hiển thị chế độ xem có chứa các lớp Hoạt ảnh chính thành bitmap?

này là tương đối đơn giản với một bình thường NSView sử dụng một cái gì đó như thế này:

void ClearBitmapImageRep(NSBitmapImageRep* bitmap) { 
    unsigned char* bitmapData = [bitmap bitmapData]; 
    if (bitmapData != NULL) 
     bzero(bitmapData, [bitmap bytesPerRow] * [bitmap pixelsHigh]); 
} 

@implementation NSView (Additions) 
- (NSBitmapImageRep*)bitmapImageRepInRect:(NSRect)rect 
{ 
    NSBitmapImageRep* imageRep = [self bitmapImageRepForCachingDisplayInRect:rect]; 
    ClearBitmapImageRep(imageRep); 
    [self cacheDisplayInRect:rect toBitmapImageRep:imageRep]; 
    return imageRep; 
} 
@end 

Tuy nhiên, khi tôi sử dụng mã này, các lớp Core Animation không trả lại.

Tôi đã điều tra CARenderer, vì nó dường như làm những gì tôi cần, tuy nhiên tôi không thể làm cho nó hiển thị cây lớp hiện tại của tôi. Tôi thử như sau:

NSOpenGLPixelFormatAttribute att[] = 
{ 
    NSOpenGLPFAWindow, 
    NSOpenGLPFADoubleBuffer, 
    NSOpenGLPFAColorSize, 24, 
    NSOpenGLPFAAlphaSize, 8, 
    NSOpenGLPFADepthSize, 24, 
    NSOpenGLPFANoRecovery, 
    NSOpenGLPFAAccelerated, 
    0 
}; 

NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:att]; 
NSOpenGLView* openGLView = [[NSOpenGLView alloc] initWithFrame:[self frame] pixelFormat:pixelFormat]; 
NSOpenGLContext* oglctx = [openGLView openGLContext]; 

CARenderer* renderer = [CARenderer rendererWithCGLContext:[oglctx CGLContextObj] options:nil]; 
renderer.layer = myContentLayer; 
[renderer render]; 
NSBitmapImageRep* bitmap = [oglView bitmapImageRepInRect:[oglView bounds]]; 

Tuy nhiên, khi tôi làm điều này tôi nhận được một ngoại lệ:

CAContextInvalidLayer -- layer <CALayer: 0x1092ea0> is already attached to a context

Tôi đoán rằng đây phải là vì cây lớp được lưu trữ trong NSView tôi và do đó gắn liền với bối cảnh của nó. Tôi không hiểu làm thế nào tôi có thể tách cây layer từ NSView để render nó vào một bitmap, và nó không tầm thường trong trường hợp này để tạo ra một cây layer trùng lặp.

Có cách nào khác để có được các CALayer giây để hiển thị bitmap không? Tôi không thể tìm thấy bất kỳ mã mẫu bất cứ nơi nào để làm điều này, trên thực tế tôi không thể tìm thấy bất kỳ mã mẫu cho CARenderer cả.

Trả lời

15

Có một bài đăng tuyệt vời về "Ca cao là bạn gái của tôi" về việc ghi Hoạt ảnh lõi. Tác giả chụp toàn bộ hoạt ảnh vào một bộ phim, nhưng bạn có thể sử dụng phần mà anh ta lấy một khung hình duy nhất.
Nhảy tới "Lấy Current Frame" phần trong bài viết này:
http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/

Ý tưởng cơ bản là:

  • Tạo một CGContext
  • Sử dụng CALayer'srenderInContext:
  • Tạo một NSBitmapImageRep từ ngữ cảnh (sử dụng CGBitmapContextCreateImage và initWithCGImage của NSBitmapImageRep)

Cập nhật:
Tôi chỉ đọc, rằng phương pháp renderInContext: không hỗ trợ tất cả các loại của các lớp trong Mac OS X 10.5. Nó không làm việc cho các lớp lớp sau:

  • QCCompositionLayer
  • CAOpenGLLayer
  • QTMovieLayer
+0

Rất cám ơn, đây chính xác là những gì tôi cần và hoạt động hoàn hảo. Tôi ước rằng tôi đã nhận thấy phương thức '-renderInContext:' trước đó, 'CARenderer' dẫn tôi đến con đường trong vườn. –

+0

Tính năng này có hoạt động cho các thành phần không có màn hình không? Ví dụ. CALayer của tôi có chứa một số yếu tố không có trong khung nhìn, nhưng tôi cần phải cuộn để xem chúng. – Tudorizer

+0

Có ai nhận được điều này để làm việc với một hình ảnh động bắt đầu với [UIView animateWithDuration: ...]? Nó không làm việc cho tôi. – Isak

4

Nếu bạn muốn mẫu mã cho làm thế nào để làm cho một hệ thống phân cấp CALayer một NSImage (hoặc UIImage cho iPhone), bạn có thể xem CPLayer của khung Core Plot-imageOfLayer method của khung công tác.Chúng tôi thực sự đã tạo một đường dẫn hiển thị độc lập với quy trình bình thường -renderInContext: được sử dụng bởi CALayer, bởi vì cách thông thường không bảo toàn các phần tử vectơ khi tạo các biểu diễn PDF của các lớp. Đó là lý do tại sao bạn sẽ thấy phương thức -recursivelyRenderInContext: trong mã này.

Tuy nhiên, điều này sẽ không giúp bạn nếu bạn đang cố bắt giữ từ bất kỳ loại lớp nào được đề cập bởi weichsel (QCCompositionLayer, CAOpenGLLayer hoặc QTMovieLayer).

+0

Cảm ơn vì điều này, nó toàn diện hơn nhiều so với câu trả lời từ weichsel nhưng nó còn hơn cả tôi thực sự cần trong trường hợp này. Mã '-recursivelyRenderInContext:' thực sự rất hay. –

Các vấn đề liên quan