Cách chụp ảnh màn hình theo chương trình trên iOS


157

Tôi muốn một ảnh chụp màn hình của hình ảnh trên màn hình được lưu vào thư viện ảnh đã lưu.

Câu trả lời:


233

Xem xét kiểm tra màn hình võng mạc sử dụng đoạn mã sau:

#import <QuartzCore/QuartzCore.h> 

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(self.window.bounds.size);
}

[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image);
if (imageData) {
    [imageData writeToFile:@"screenshot.png" atomically:YES];
} else {
    NSLog(@"error while taking screenshot");
}

13
Lưu ý rằng điều này sẽ không nắm bắt được một số loại nội dung màn hình nhất định, như các lớp OpenGL ES. UIGetScreenImage (), mà Hua-Ying chỉ đến, không.
Brad Larson

12
Các bạn thân mến, đừng quên làm #import <QuartzCore / QuartzCore.h>
Enrico Susatyo

ảnh này sẽ chụp ảnh màn hình nếu bạn đang xem ảnh mà ứng dụng của bạn vừa chụp?
John Riselvato

5
Hình ảnh này được lưu trữ ở đâu?
Burhanuddin Sunelwala

3
@ wladimir -
g212ss

46

Phương thức bên dưới cũng hoạt động cho các đối tượng OPENGL

//iOS7 or above
- (UIImage *) screenshot {

    CGSize size = CGSizeMake(your_width, your_height);

    UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);

    CGRect rec = CGRectMake(0, 0, your_width, your_height);
    [_viewController.view drawViewHierarchyInRect:rec afterScreenUpdates:YES];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

5
UIGetScreenImagelà một API riêng
jonahb

Cảm ơn rất nhiều vì chuyện này! Bạn chắc chắn nhận được phiếu bầu của tôi. Sau khi thử nhiều cách khác, có vẻ như drawViewHVELy ​​là cách duy nhất để chụp màn hình trong robovm với javafx ui.
Christo Smal

Đây là những gì đang làm việc mọi lúc !!!! Tôi có rất nhiều biến đổi 3d trên màn hình và các giải pháp khác đã gây rối trong ảnh chụp màn hình của tôi. Điều này hoạt động như nó nên. Cảm ơn rất nhiều!
AndrewK

1
nếu bộ điều khiển xem nằm trong bộ điều khiển điều hướng, thanh điều hướng sẽ không được chụp
Radu Simionescu

Vâng, drawViewHierarchyInRect nhanh hơn renderInContext :-)
Alones

20
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.myView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData *imageData = UIImageJPEGRepresentation(image, 1.0 ); //you can use PNG too
[imageData writeToFile:@"image1.jpeg" atomically:YES];

1
+1 Đối với lưu ý về việc sử dụng PNG. Nó không mất dữ liệu và sẽ nhỏ hơn jpeg với quality = 1.0.
Cướp

1
thay vào đó, nó không sử dụng NavigationBar trong iOS 7.
Ali Sufyan

14
- (UIImage*) getGLScreenshot {
    NSInteger myDataLength = 320 * 480 * 4;

    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, 320, 480, 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 <480; y++)
    {
        for(int x = 0; x <320 * 4; x++)
        {
            buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + 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 * 320;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    // make the cgimage
    CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    // then make the uiimage from that
    UIImage *myImage = [UIImage imageWithCGImage:imageRef];
    return myImage;
}

- (void)saveGLScreenshotToPhotosAlbum {
    UIImageWriteToSavedPhotosAlbum([self getGLScreenshot], nil, nil, nil);  
}

Nguồn .


1
Tại sao myDataLpm được nhân với 4 ontop của 320 * 480?
Jab

2
Điều này cũng thực sự có vẻ rất ngu ngốc khi họ không cung cấp cho chúng ta một cách dễ dàng hơn để làm điều này.
Jab

320 * 480 là số pixel. Lần bốn để bạn có RGBA cho mỗi pixel.
Aistina

nhớ bội số theo hệ số tỷ lệ khi chạy trên iPhone 4 :-)
MrDatabase

1
@Aistina, sử dụng UIImage *myImage = [[UIImage alloc] initWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationDownMirrored];và bạn không cần 'buffer2' nữa. BTW có vẻ như tôi quên mất việc quản lý bộ nhớ, không có cuộc gọi miễn phí () hoặc phát hành () ...
Oleg Trakhman

10

Ở SWift

func captureScreen() -> UIImage
{

    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);

    self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)

    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return image
}

9

Xem bài đăng này có vẻ như bạn có thể sử dụng UIGetScreenImage () ngay bây giờ.


9
Điều này không được phép một lần nữa trong iOS 4.
sudo rm -rf

9

Kể từ iOS10, điều này trở nên đơn giản hơn một chút. UIKit đi kèm UIGraphicsImageRendercho phép bạn

... Hoàn thành các tác vụ vẽ mà không phải xử lý cấu hình như độ sâu màu và tỷ lệ hình ảnh hoặc quản lý bối cảnh Đồ họa lõi

Apple Docs - UIGraphicsImageRenderer

Vì vậy, bây giờ bạn có thể làm một cái gì đó như thế này:

let renderer = UIGraphicsImageRenderer(size: someView.bounds.size)

let image = renderer.image(actions: { context in
    someView.drawHierarchy(in: someView.bounds, afterScreenUpdates: true)
})

Nhiều câu trả lời ở đây đã làm việc cho tôi trong hầu hết các trường hợp. Nhưng khi cố gắng chụp ảnh nhanh ARSCNView, tôi chỉ có thể làm điều đó bằng phương pháp được mô tả ở trên. Mặc dù có thể đáng chú ý là tại thời điểm này, ARKit vẫn đang trong giai đoạn thử nghiệm và Xcode đang ở giai đoạn beta 4


7

Điều này sẽ lưu một ảnh chụp màn hình và cũng trả lại ảnh chụp màn hình.

-(UIImage *)capture{
    UIGraphicsBeginImageContext(self.view.bounds.size);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *imageView = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageWriteToSavedPhotosAlbum(imageView, nil, nil, nil); //if you need to save
    return imageView;
}

5

Tôi nghĩ đoạn trích sau sẽ hữu ích nếu bạn muốn chụp toàn màn hình ( ngoại trừ thanh trạng thái ), chỉ cần thay thế AppDelegate bằng tên đại biểu ứng dụng của bạn nếu cần.

- (UIImage *)captureFullScreen {

    AppDelegate *_appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        // for retina-display
        UIGraphicsBeginImageContextWithOptions(_appDelegate.window.bounds.size, NO, [UIScreen mainScreen].scale);
        [_appDelegate.window drawViewHierarchyInRect:_appDelegate.window.bounds afterScreenUpdates:NO];
    } else {
        // non-retina-display
        UIGraphicsBeginImageContext(_bodyView.bounds.size);
        [_appDelegate.window drawViewHierarchyInRect:_appDelegate.window.bounds afterScreenUpdates:NO];
    }

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

Trong một cái mà thêm thanh điều hướng! Sẽ bỏ phiếu hai lần nếu tôi có thể! Chúc mừng người bạn đời
marcelosarquis

4

Tôi không thể tìm thấy câu trả lời với việc triển khai Swift 3. Vì vậy, ở đây nó đi.

static func screenshotOf(window: UIWindow) -> UIImage? {

    UIGraphicsBeginImageContextWithOptions(window.bounds.size, true, UIScreen.main.scale)

    guard let currentContext = UIGraphicsGetCurrentContext() else {
        return nil
    }

    window.layer.render(in: currentContext)
    guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
        UIGraphicsEndImageContext()
        return nil
    }

    UIGraphicsEndImageContext()
    return image
}

3

Dành cho iOS 7.0 trở lên ..

Nếu bạn muốn chụp ảnh màn hình của chế độ xem (myView), bạn có thể thực hiện việc này với một dòng duy nhất:

[myView snapshotViewAfterScreenUpdates:NO];

3

Điều này sẽ hoạt động với swift 4.2 , ảnh chụp màn hình sẽ được lưu trong thư viện, nhưng đừng quên chỉnh sửa info.plist @ NSPhotoLibraryAddUsageDescription:

  @IBAction func takeScreenshot(_ sender: UIButton) {

    //Start full Screenshot
    print("full Screenshot")
    UIGraphicsBeginImageContext(card.frame.size)
    view.layer.render(in: UIGraphicsGetCurrentContext()!)
    var sourceImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    UIImageWriteToSavedPhotosAlbum(sourceImage!, nil, nil, nil)

    //Start partial Screenshot
    print("partial Screenshot")
    UIGraphicsBeginImageContext(card.frame.size)
    sourceImage?.draw(at: CGPoint(x:-25,y:-100)) //the screenshot starts at -25, -100
    var croppedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    UIImageWriteToSavedPhotosAlbum(croppedImage!, nil, nil, nil)

}

2

Nhận ảnh chụp màn hình từ chế độ xem

-(UIImage *)getScreenshotImage {
    if ([[UIScreen mainScreen] scale] == 2.0) {
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, FALSE, 2.0);
    } else {
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, FALSE, 1.0);
    }

    [self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

Lưu hình ảnh vào hình ảnh

UIImageWriteToSavedPhotosAlbum(YOUR_IMAGE, nil, nil, nil);

Làm thế nào để

UIImageWriteToSavedPhotosAlbum([self getScreenshotImage], nil, nil, nil);

2

Nhận ảnh chụp màn hình từ chế độ xem:

- (UIImage *)takeSnapshotView {
    CGRect rect = [myView bounds];//Here you can change your view with myView
    UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [myView.layer renderInContext:context];
    UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return capturedScreen;//capturedScreen is the image of your view
}

Hy vọng, đây là những gì bạn đang tìm kiếm. Bất kỳ mối quan tâm trở lại với tôi. :)


2

Tôi đang trả lời câu hỏi này vì đây là một câu hỏi được đánh giá cao và có rất nhiều câu trả lời ngoài đó cộng với Swift và Obj-C.

Tuyên bố miễn trừ trách nhiệm Đây không phải là mã của tôi, cũng không phải câu trả lời của tôi, đây chỉ là để giúp những người ở đây tìm được câu trả lời nhanh chóng. Có liên kết đến các câu trả lời ban đầu để cung cấp tín dụng khi tín dụng đáo hạn !! Vui lòng tôn trọng các câu trả lời ban đầu với +1 nếu bạn sử dụng câu trả lời của họ!


Sử dụng QuartzCore

#import <QuartzCore/QuartzCore.h> 

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(self.window.bounds.size);
}

[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image);
if (imageData) {
    [imageData writeToFile:@"screenshot.png" atomically:YES];
} else {
    NSLog(@"error while taking screenshot");
}

Trong Swift

func captureScreen() -> UIImage
{

    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);

    self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)

    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return image
}

Lưu ý: Vì bản chất với lập trình, các cập nhật có thể cần được thực hiện vì vậy vui lòng chỉnh sửa hoặc cho tôi biết! * Ngoài ra nếu tôi không bao gồm một câu trả lời / phương pháp có giá trị bao gồm cả hãy thoải mái cho tôi biết!


1
Câu trả lời này dường như không thêm bất cứ điều gì. Bạn chỉ cần sao chép hai câu trả lời đã có trên trang và đăng kết quả là của riêng bạn.
user2357112 hỗ trợ Monica 23/11/18

Ý định của tôi là không lấy tín dụng cho câu trả lời của họ, nó bao gồm cả swift và Obj-C trong một câu trả lời để mọi người tìm thấy nhanh hơn. Tôi đề cập đến các câu trả lời tương ứng là tốt. nếu điều này không được thực hiện, tôi sẽ xóa câu trả lời của mình và quay lại chỉ một trong số chúng.
Jab

Tôi đang sử dụng giải pháp ObjC. Đối với tôi, tôi đã phải thêm ".view" sau "tự", nhưng kết quả là 100%. Đây là VÀNG
samouray

Nó cũng hoạt động cho Capturing Presentation Stream. Cảm ơn
fan YSR

1

Một tùy chọn khác là sử dụng công cụ Tự động hóa trên các công cụ. Bạn viết một kịch bản để đặt màn hình vào bất cứ điều gì bạn muốn, sau đó chụp. Đây là kịch bản tôi đã sử dụng cho một trong những ứng dụng của mình. Rõ ràng, các chi tiết của tập lệnh sẽ khác nhau cho ứng dụng của bạn.

var target = UIATarget.localTarget();
var app = target.frontMostApp();
var window = app.mainWindow();
var picker = window.pickers()[0];
var wheel = picker.wheels()[2];
var buttons = window.buttons();
var button1 = buttons.firstWithPredicate("name == 'dateButton1'");
var button2 = buttons.firstWithPredicate("name == 'dateButton2'");

function setYear(picker, year) {
    var yearName = year.toString();
    var yearWheel = picker.wheels()[2];
    yearWheel.selectValue(yearName);
}

function setMonth(picker, monthName) {
    var wheel = picker.wheels()[0];
    wheel.selectValue(monthName);
}

function setDay(picker, day) {
    var wheel = picker.wheels()[1];
    var name = day.toString();
    wheel.selectValue(name);
}

target.delay(1);
setYear(picker, 2015);
setMonth(picker, "July");
setDay(picker, 4);
button1.tap();
setYear(picker, 2015);
setMonth(picker, "December");
setDay(picker, 25);

target.captureScreenWithName("daysShot1");

var nButtons = buttons.length;
UIALogger.logMessage(nButtons + " buttons");
for (var i=0; i<nButtons; i++) {
    UIALogger.logMessage("button " + buttons[i].name());
}

var tabBar = window.tabBars()[0];
var barButtons = tabBar.buttons();

var nBarButtons = barButtons.length;
UIALogger.logMessage(nBarButtons + " buttons on tab bar");

for (var i=0; i<nBarButtons; i++) {
    UIALogger.logMessage("button " + barButtons[i].name());
}

var weeksButton = barButtons[1];
var monthsButton = barButtons[2];
var yearsButton = barButtons[3];

target.delay(2);
weeksButton.tap();
target.captureScreenWithName("daysShot2");
target.delay(2);
monthsButton.tap();
target.captureScreenWithName("daysShot3");
target.delay(2);
yearsButton.tap();
target.delay(2);
button2.tap();
target.delay(2);
setYear(picker, 2018);
target.delay(2);
target.captureScreenWithName("daysShot4");

1

Hai tùy chọn có sẵn tại trang web dưới đây:

TÙY CHỌN 1: sử dụng UIWindow (đã thử và hoạt động hoàn hảo)

// create graphics context with screen size
CGRect screenRect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);

// grab reference to our window
UIWindow *window = [UIApplication sharedApplication].keyWindow;

// transfer content into our context
[window.layer renderInContext:ctx];
UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

TÙY CHỌN 2: sử dụng UIView

// grab reference to the view you'd like to capture
UIView *wholeScreen = self.splitViewController.view;

// define the size and grab a UIImage from it
UIGraphicsBeginImageContextWithOptions(wholeScreen.bounds.size, wholeScreen.opaque, 0.0);
[wholeScreen.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Đối với màn hình võng mạc (như câu trả lời của DenNukem)

// grab reference to our window
    UIWindow *window = [UIApplication sharedApplication].keyWindow;

    // create graphics context with screen size
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(screenRect.size, NO, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(screenRect.size);
        [window.layer renderInContext:UIGraphicsGetCurrentContext()];
    }

để biết thêm chi tiết: http://pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/


1

Chỉ cần một đóng góp nhỏ, tôi đã thực hiện điều này bằng một nút nhưng nhấn cũng có nghĩa là nút được chụp. Vì vậy, đầu tiên tôi làm sáng tỏ.

- (IBAction)screenShot:(id)sender {
    // Unpress screen shot button
    screenShotButton.highlighted = NO;

    // create graphics context with screen size
    CGRect screenRect = [[UIScreen mainScreen] bounds];

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(self.view.bounds.size);
    }

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);

    // grab reference to our window
    UIWindow *window = [UIApplication sharedApplication].keyWindow;

    // transfer content into our context
    [window.layer renderInContext:ctx];
    UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // save screengrab to Camera Roll
    UIImageWriteToSavedPhotosAlbum(screengrab, nil, nil, nil);
}

Tôi đã nhận phần chính của mã từ: http://pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/ nơi tôi đã sử dụng tùy chọn 1, tùy chọn 2 dường như không hoạt động cho tôi. Đã thêm các điều chỉnh cho kích thước màn hình của Rentina từ chuỗi này và làm nổi bật màn hình chụp ảnh. Chế độ xem tôi đang sử dụng là màn hình các nút và nhãn StoryBoarded và với một số UIView được thêm sau thông qua chương trình.


Cảm ơn the_UB đã chỉnh sửa. Tôi nhận ra rằng tôi đã để lại mã nhận xét, nhưng sau đó nghĩ rằng "đó là mã được dán chính hãng". Mã làm việc trực tiếp hiện có trong App Store.
Symanski

1

Trong Swift bạn có thể sử dụng mã sau đây.

if UIScreen.mainScreen().respondsToSelector(Selector("scale")) {
    UIGraphicsBeginImageContextWithOptions(self.window!.bounds.size, false, UIScreen.mainScreen().scale)
}
else{
    UIGraphicsBeginImageContext(self.window!.bounds.size)
}
self.window?.layer.renderInContext(UIGraphicsGetCurrentContext())
var image : UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)

0

Swift 4:

func makeImage(withView view: UIView) -> UIImage? {

    let rect = view.bounds

    UIGraphicsBeginImageContextWithOptions(rect.size, true, 0)

    guard let context = UIGraphicsGetCurrentContext() else {
      assertionFailure()
      return nil
    }

    view.layer.render(in: context)

    guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
      assertionFailure()
      return nil
    }

    UIGraphicsEndImageContext()

    return image
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.