Программно сделать снимок экрана определенной области

Как вы можете видеть в моем коде, я делаю снимок экрана и сохраняю его в фотоальбом.

//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(self.view.bounds.size);
}
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);

Вначале я использовал webview.size вместо self.view.bounds.size, и это работало правильно, потому что представление располагалось в 0/0. Но теперь я центрировал WebView, но изображения начинаются с 0/0 для заданного размера.

Как я могу настроить, чтобы скриншот начинался с другого location (например, 300/150) для заданного размера?

Или есть другой способ сфотографировать UIWebView?


person Sharky    schedule 02.01.2012    source источник
comment
Это работает на настольной OSX или только на iphone?   -  person Noitidart    schedule 07.05.2015


Ответы (4)


Вам нужно внести два изменения, чтобы захватить только часть экрана:

  1. Создайте изображение меньшего размера — используйте размер прямоугольника, который вы хотите захватить.
  2. Переместите источник контекста, который вы визуализируете, на отрицательный x/y прямоугольника, который вы хотите захватить.

После этого вы просто визуализируете слой в контексте, как вы это делали, и вы должны получить то, что ищете. Что-то вроде этого должно сделать это:

CGRect grabRect = CGRectMake(40,40,300,200);

//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(grabRect.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(grabRect.size);
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -grabRect.origin.x, -grabRect.origin.y);
[self.view.layer renderInContext:ctx];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
person escrafford    schedule 08.03.2013
comment
Это приводит к сбою моего приложения. Есть идеи, почему? Я добавил фреймворк QuartzCore и поместил этот код в функцию, но все еще не работает. - person rebellion; 05.06.2013
comment
@rebellion - я заставил это работать. Хоть и не в фотоальбоме. См. мою адаптацию ниже как метод категории UIView. - person idStar; 21.06.2013
comment
Спасибо, это отлично работает для меня. Просто небольшая проблема, цвет фона изображения белый, я хочу, чтобы он был прозрачным. Как я могу это сделать. Пожалуйста помоги - person iMemon; 06.11.2013
comment
Цвет фона изображения был белым, так как я загружал изображение в формате jpeg вместо изображения png. Вышеприведенный код идеален :) - person iMemon; 06.11.2013

Я взял и протестировал ответ @escrafford выше и заставил его работать нормально. Я протестировал его в контексте создания метода категории в UIView, чтобы можно было параметризовать «grabRect». Вот этот код как категория UIView, которая возвращает вам UIImageView:

/**
 Takes a screenshot of a UIView at a specific point and size, as denoted by
 the provided croppingRect parameter. Returns a UIImageView of this cropped
 region.

 CREDIT: This is based on @escrafford's answer at http://stackoverflow.com/a/15304222/535054
*/
- (UIImageView *)rp_screenshotImageViewWithCroppingRect:(CGRect)croppingRect {
    // For dealing with Retina displays as well as non-Retina, we need to check
    // the scale factor, if it is available. Note that we use the size of teh cropping Rect
    // passed in, and not the size of the view we are taking a screenshot of.
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(croppingRect.size, YES, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(croppingRect.size);
    }

    // Create a graphics context and translate it the view we want to crop so
    // that even in grabbing (0,0), that origin point now represents the actual
    // cropping origin desired:
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -croppingRect.origin.x, -croppingRect.origin.y);
    [self.layer renderInContext:ctx];

    // Retrieve a UIImage from the current image context:
    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // Return the image in a UIImageView:
    return [[UIImageView alloc] initWithImage:snapshotImage];
}
person idStar    schedule 20.06.2013
comment
Этот код, конечно, предполагает ARC и актуален (рабочее решение), как и в iOS6.1. - person idStar; 21.06.2013

Я решил свою проблему, но не ответил на вопрос:

Я создал подкласс UIView и переместил туда свой UIWebView, чтобы он располагался 0/0 относительно подкласса. Затем используйте размер WebView:

UIGraphicsBeginImageContext(webview.frame.size);

и другой код сверху.

Теперь вы можете переместить подкласс в любое желаемое место.

Примечание. Если у вас есть метки, такие как метка даты/времени, их тоже нужно переместить, иначе вы не увидите их на картинке.

Поэтому создайте подкласс UIView и переместите туда все IBOutlet, которые вы хотите видеть на картинке.

Вопрос пока открыт: Так можно ли сделать снимок определенной области экрана?

С уважением. $h@rky

person Sharky    schedule 09.01.2012

- (void)drawRect:(CGRect)rect {
  UIGraphicsBeginImageContext(self.bounds.size);    
  [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
  UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);  
}

Вы можете назвать это своим мнением:]

person Nils Munch    schedule 02.01.2012
comment
Метод drawRect вызывается при создании веб-представления, поэтому в начале у меня есть серая картинка. Идея, которую я получил от этого, состоит в том, чтобы перетащить код и поместить его в мой пользовательский класс UIView, где мое веб-представление находится в 0/0. Это работает, но я больше не видел ярлык, потому что он является частью корневого представления. - person Sharky; 03.01.2012