iOS應用截屏

來源:互聯網
上載者:User

iOS應用截屏

iPhone自從推出後就內建了截屏功能,簡單而易用,所以應用就沒什麼截屏的需求了,不過有些時候我們還是會遇到這個需求。比如,我們開發了一個播放器,用openGL進行video render,此時直接截屏有可能有OSD疊加內容,所以希望能截完全是視頻的幀,這時就需要應用自己來實現了。

從應用角度看,雖說都是截屏,但用不用openGL是不同的,因為openGL是直接寫GPU frame buffer的,如果我們是直接用UIController來用做的介面:

- (void)snapshotScreen{    // check the retina screen    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]){        UIGraphicsBeginImageContextWithOptions(self.view.window.bounds.size, NO, [UIScreen mainScreen].scale);    } else {        UIGraphicsBeginImageContext(self.view.window.bounds.size);    }    [self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    NSData * data = UIImagePNGRepresentation(image);        NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);    NSString *filename = [[path objectAtIndex:0] stringByAppendingPathComponent:@"foo.png"];    [data writeToFile:filename atomically:YES];}

這個代碼前面部分是檢查是否是retina螢幕的,因為iPhone都是retina的螢幕,但iPod有非retina的螢幕;最後一部分是把image存到應用的document目錄下。


如果要截openGL的內容,那麼上面的代碼就不能用了,思路是用openGL的API,glReadPixels去讀出內容來。代碼如下:

- (void)getGLScreenShot {    int       w = self.bounds.size.width;    int       h = self.bounds.size.height;    NSInteger myDataLength = w * h * 4;        // allocate array and read pixels into it.    GLubyte *buffer = (GLubyte *) malloc(myDataLength);    glReadPixels(0, 0, w, h, 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 < h; y++) {        for(int x = 0; x       這段代碼是抓下了openGL渲染的一個GLView的所有內容,因為openGL讀出的內容是顛倒的,所以習慣上需要顛倒一下,中間的兩層for迴圈就是這個用途,當然,這個寫法效率不高,不過一時也沒找到什麼高效的方法,就先用一下。

這段代碼裡面釋放了buffer的記憶體,但沒有釋放buffer2的記憶體。因為圖片的儲存是非同步,所以是在存完圖片之後,調用@selector(GLImage:didFinishSavingWithError:contextInfo:)這個方法進行清理,通過這個回調,在UI上也可以做一些限制,防止使用者連續快速的截屏導致系統負載過重。

順便說一下,這裡把存下的圖片按照習慣放到了圖片庫之中。


在iOS7之後,UIView有了UISnapshotting的category,這個真是大大的方便了我們截屏的實現,因為它既可以截屏普通的UIController,也可以截屏openGL的內容,

// only support iOS7 or Above- (void)snapshotScreenWithGL{    CGSize size = videoView.bounds.size;         UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);        CGRect rec = CGRectMake(videoView.frame.origin.x, videoView.frame.origin.y, videoView.bounds.size.width, videoView.bounds.size.height);    [self.view drawViewHierarchyInRect:rec afterScreenUpdates:YES];        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();        NSData * data = UIImagePNGRepresentation(image);        NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);    NSString *filename = [[path objectAtIndex:0] stringByAppendingPathComponent:@"foo.png"];    [data writeToFile:filename atomically:YES];}

綜合起來看,iOS7之後,蘋果考慮到了使用者這方面的需求,提供了API,可以比較方便的實現功能。iOS7之前,需要自己手動實現,根據是否使用了openGL代碼有所不同。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.