-
使用CALayer的renderInContext恭朗,然后從context中獲取圖片
- (UIImage *)snapshotCALayer { UIGraphicsBeginImageContextWithOptions(imageSize, NO, [UIScreen mainScreen].scale); [window.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; }
這種方法對view對應的layer是CALayer實例是可以的,如果view的layer是CAEAGLLayer的實例就會有問題预侯,比如對GPUImageView使用上面的方法,截出來的圖就是黑的。
查看這個方法的注釋
/** Rendering properties and methods. **/ /* Renders the receiver and its sublayers into 'ctx'. This method * renders directly from the layer tree. Renders in the coordinate space * of the layer. * * WARNING: currently this method does not implement the full * CoreAnimation composition model, use with caution. */ - (void)renderInContext:(CGContextRef)ctx;
不知道是不是* WARNING: currently this method does not implement the full
包含的一種情況
-
對于CAEAGLLayer獲取截圖,網上找了一段代碼
+ (UIImage *)glToUIImage:(CGSize)size { CGSize viewSize = size; NSInteger myDataLength = viewSize.width * viewSize.height * 4; // allocate array and read pixels into it. GLubyte *buffer = (GLubyte *) malloc(myDataLength); glReadPixels(0, 0, viewSize.width, viewSize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); // gl renders "upside down" so swap top to bottom into new array. // there's gotta be a better way, but this works. GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); for(int y = 0; y < viewSize.height; y++) { for(int x = 0; x < viewSize.width* 4; x++) { buffer2[(int)((viewSize.height-1 - y) * viewSize.width * 4 + x)] = buffer[(int)(y * 4 * viewSize.width + x)]; } } // make data provider with data. CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL); // prep the ingredients int bitsPerComponent = 8; int bitsPerPixel = 32; int bytesPerRow = 4 * viewSize.width; CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; // make the cgimage CGImageRef imageRef = CGImageCreate(viewSize.width , viewSize.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); // then make the uiimage from that UIImage *myImage = [UIImage imageWithCGImage:imageRef]; return myImage; }
對opengl了解不多,但是可以看出數(shù)據獲取是通過
GLubyte *buffer = (GLubyte *) malloc(myDataLength); glReadPixels(0, 0, viewSize.width, viewSize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
實現(xiàn)的驼修,僅僅使用了layer的大小,也就是說layer沒作為數(shù)據源,那數(shù)據源從哪里來呢乙各?還是繼續(xù)搜索墨礁,有人說到了這個問題。
“注意:glReadPixels實際上是從緩沖區(qū)中讀取數(shù)據耳峦,如果使用了雙緩沖區(qū)恩静,則默認是從正在顯示的緩沖(即前緩沖)中讀取,而繪制工作是默認繪制到后緩沖區(qū)的妇萄。因此蜕企,如果需要讀取已經繪制好的像素,往往需要先交換前后緩沖”
從緩沖區(qū)獲取數(shù)據會存在一些問題冠句,因為這個緩沖區(qū)誰都可以去操作轻掩,所以這個方法很難直接使用。
-
使用 UIView (UISnapshotting) 這個分類中的方法
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
經過實踐懦底,這個方法對于layer是CAEAGLLayer實例的view也生效唇牧。iOS 7.0 開始生效。
截圖可以使用這個 https://github.com/shinydevelopment/SDScreenshotCapture
使用 drawViewHierarchyInRect 可能會出現(xiàn)閃退聚唐,原因是在遍歷layers的時候丐重,layers數(shù)組已經發(fā)生了改變。如果你要截取的內容包含collectionView這類杆查,很可能會發(fā)生閃退扮惦,可以使用try-catch來避免閃退。