2015-10-27 2 views
0

Мне нужно сделать снимок экрана всего экрана, включая строку состояния, я использую CARenderServerRenderDisplay, чтобы добиться этого, он работает прямо на iPad, но неправильно на iPhone 6 Plus. В качестве * отмеченной части кода, если я установил width=screenSize.width*scale и height=screenSize.height*scale, это приведет к сбою, если я их просто изменил как:и height=screenSize.width*scale, он будет работать, но создаст такое изображение: enter image description here, я пробовал много, но нет причин, кто-нибудь знает это? Надеюсь, я описал это достаточно ясно.Как сделать снимок экрана всего экрана на устройстве Jailbroken iOS?

- (void)snapshot 
{ 
    CGFloat scale = [UIScreen mainScreen].scale; 
    CGSize screenSize = [UIScreen mainScreen].bounds.size; 

    //*********** the place where problem appears   
    size_t width = screenSize.height * scale; 
    size_t height = screenSize.width * scale; 
    //*********** 

    size_t bytesPerElement = 4; 
    OSType pixelFormat = 'ARGB'; 
    size_t bytesPerRow = bytesPerElement * width; 
    size_t surfaceAllocSize = bytesPerRow * height; 

    NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys: 
           [NSNumber numberWithBool:YES], kIOSurfaceIsGlobal, 
           [NSNumber numberWithUnsignedLong:bytesPerElement], kIOSurfaceBytesPerElement, 
           [NSNumber numberWithUnsignedLong:bytesPerRow], kIOSurfaceBytesPerRow, 
           [NSNumber numberWithUnsignedLong:width], kIOSurfaceWidth, 
           [NSNumber numberWithUnsignedLong:height], kIOSurfaceHeight, 
           [NSNumber numberWithUnsignedInt:pixelFormat], kIOSurfacePixelFormat, 
           [NSNumber numberWithUnsignedLong:surfaceAllocSize], kIOSurfaceAllocSize, 
           nil]; 

    IOSurfaceRef destSurf = IOSurfaceCreate((__bridge CFDictionaryRef)(properties)); 

    IOSurfaceLock(destSurf, 0, NULL); 
    CARenderServerRenderDisplay(0, CFSTR("LCD"), destSurf, 0, 0); 
    IOSurfaceUnlock(destSurf, 0, NULL); 

    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, IOSurfaceGetBaseAddress(destSurf), (width * height * 4), NULL); 
    CGImageRef cgImage = CGImageCreate(width, height, 8, 
             8*4, IOSurfaceGetBytesPerRow(destSurf), 
             CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipFirst |kCGBitmapByteOrder32Little, 
             provider, NULL, YES, kCGRenderingIntentDefault); 
    UIImage *image = [UIImage imageWithCGImage:cgImage]; 
    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); 
} 
+0

My environment is jailbroken iPhone 6 Plus с iOS 9.0.2. – Suge

+0

Ваш провайдер может предоставить только 'width * height * 4' байты, но' CGImageCreate' запросит его для 'IOSurfaceGetBytesPerRow (destSurf) * height * 4' байт. Возможно, поэтому он падает? –

+0

@robmayoff, я взял тест только сейчас, он разбился на 'CARenderServerRenderDisplay'. – Suge

ответ

2

Если вы находитесь на Jailbroken среде, вы можете использовать частный UIImage метод _UICreateScreenUIImage:

OBJC_EXTERN UIImage *_UICreateScreenUIImage(void); 

// ... 

- (void)takeScreenshot { 
    UIImage *screenImage = _UICreateScreenUIImage(); 
    // do something with your screenshot 
} 

Этот метод использует CARenderServerRenderDisplay для более быстрого рендеринга на весь экран устройства. Он заменяет методы UICreateScreenImage и UIGetScreenImage, которые были удалены в версии 64-го уровня iOS 7 SDK.

+0

Большое вам спасибо! – Suge

+0

Вы знаете, как объявить/назвать этот метод в Xamarin (C#)? – Benj

+0

@Benj Эй, я не уверен, как это будет работать в Xamarin. Есть ли способ загрузить или запустить функцию C? Это действительно все. – JAL