美文网首页iOS多媒体
iOS CAEAGLLayer生成UIImage

iOS CAEAGLLayer生成UIImage

作者: 观星 | 来源:发表于2018-04-24 17:22 被阅读288次
    1. 使用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使用上面的方法,获取的内容就不是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可能包含的一种情况

    1. 对于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了解不多,但是可以看出数据获取是通过

       GLubyte *buffer = (GLubyte *) malloc(myDataLength);
       glReadPixels(0, 0, viewSize.width, viewSize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
      

      实现的,仅仅使用了layer的大小,也就是说layer没作为数据源,那数据源从哪里来呢?还是继续搜索,有人说到了这个问题。

      “注意:glReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓冲区的。因此,如果需要读取已经绘制好的像素,往往需要先交换前后缓冲”

      从缓冲区获取数据会存在一些问题,因为这个缓冲区谁都可以去操作,所以这个方法很难直接使用。

    2. 使用 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 可能会出现闪退,原因是在遍历layers的时候,layers数组已经发生了改变。如果你要截取的内容包含collectionView这类,很可能会发生闪退,可以使用try-catch来避免闪退。

    相关文章

      网友评论

        本文标题:iOS CAEAGLLayer生成UIImage

        本文链接:https://www.haomeiwen.com/subject/nnvjlftx.html