iOS CAEAGLLayer生成UIImage

  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使用上面的方法,截出來的圖就是黑的。

    查看這個方法的注釋

     /** 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了解不多,但是可以看出數(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ū)誰都可以去操作轻掩,所以這個方法很難直接使用。

  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 可能會出現(xiàn)閃退聚唐,原因是在遍歷layers的時候丐重,layers數(shù)組已經發(fā)生了改變。如果你要截取的內容包含collectionView這類杆查,很可能會發(fā)生閃退扮惦,可以使用try-catch來避免閃退。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末亲桦,一起剝皮案震驚了整個濱河市崖蜜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌客峭,老刑警劉巖豫领,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異舔琅,居然都是意外死亡等恐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門备蚓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來课蔬,“玉大人,你說我怎么就攤上這事郊尝《希” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵虚循,是天一觀的道長同欠。 經常有香客問我样傍,道長,這世上最難降的妖魔是什么铺遂? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任衫哥,我火速辦了婚禮,結果婚禮上襟锐,老公的妹妹穿的比我還像新娘撤逢。我一直安慰自己,他們只是感情好粮坞,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布蚊荣。 她就那樣靜靜地躺著,像睡著了一般莫杈。 火紅的嫁衣襯著肌膚如雪互例。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天筝闹,我揣著相機與錄音媳叨,去河邊找鬼。 笑死关顷,一個胖子當著我的面吹牛糊秆,可吹牛的內容都是我干的。 我是一名探鬼主播议双,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼痘番,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了平痰?” 一聲冷哼從身側響起汞舱,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎觉增,沒想到半個月后兵拢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體翻斟,經...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡逾礁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了访惜。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嘹履。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖债热,靈堂內的尸體忽然破棺而出砾嫉,到底是詐尸還是另有隱情,我是刑警寧澤窒篱,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布焕刮,位于F島的核電站舶沿,受9級特大地震影響,放射性物質發(fā)生泄漏配并。R本人自食惡果不足惜括荡,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望溉旋。 院中可真熱鬧畸冲,春花似錦、人聲如沸观腊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梧油。三九已至苫耸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間儡陨,已是汗流浹背鲸阔。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留迄委,地道東北人褐筛。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像叙身,于是被迫代替她去往敵國和親渔扎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內容