программный вывод экрана из UIView glview

#iphone #opengl-es

#iPhone #opengl-es

Вопрос:

у меня есть glview в моем uiview, теперь я должен сделать предварительный снимок комбинированного просмотра uiview и glview. я много гуглил, но не нашел ничего полезного, я знаю, как сделать снимок экрана glview

nt width = glView.frame.size.width; int height = glView.frame.size.height;

 NSInteger myDataLength = width * height * 4;
// allocate array and read pixels into it.
GLubyte *buffer = (GLubyte *) malloc(myDataLength);
glReadPixels(0, 0, width, 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 < height; y  )
{
    for(int x = 0; x < width * 4; x  )
    {
        buffer2[((height - 1) - y) * width * 4   x] = buffer[y * 4 * 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 * width;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefau<
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefau<
// make the cgimage
CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
// then make the uiimage from that
UIImage *myImage = [UIImage imageWithCGImage:imageRef];
return myImage;
  

Ответ №1:

Кажется, что в наши дни довольно сложно получить скриншот, особенно когда вы смешиваете UIKit и OpenGL ES: раньше было, UIGetScreenImage() но Apple снова сделала его приватным и отклоняет приложения, которые его используют.

Вместо этого есть два «решения» для его замены: захват экрана в приложениях UIKit и моментальный снимок OpenGL ES View. Первый не захватывает OpenGL ES или видеоконтент, в то время как более поздний — только для OpenGL ES.

Есть еще одно техническое примечание, как мне сделать снимок экрана моего приложения, которое содержит как элементы UIKit, так и камеры?, и здесь они по сути говорят: вам нужно сначала сделать снимок с камеры, а затем при рендеринге иерархии представлений нарисовать это изображение в контексте.

То же самое применимо и к OpenGL ES: сначала вам нужно будет сделать снимок для вашего представления OpenGL ES, затем отобразить иерархию представлений UIKit в контексте изображения и нарисовать поверх нее изображение вашего представления OpenGL ES. Очень некрасиво, и в зависимости от вашей иерархии представлений на самом деле это может быть не то, что вы видите на экране (например, если перед вашим представлением OpenGL есть представления).

Комментарии:

1. @ DarkDust: — очень полезный ответ ….. привет, у меня проблема с захватом OpenGL es с использованием glReadPixels ….вызов glReadPixels () снижает частоту кадров в секунду примерно с 30 до 2-3 …. почему?

2. @Tornado: Понятия не имею, но в целом Apple заявляет, что ее реализация OpenGL ES настроена на операции записи, а чтение любого состояния происходит медленно, и этого следует избегать. Лучше запоминать состояния, о которых вы заботитесь сами, а не запрашивать их. Конечно, это невозможно сделать для glReadPixels , но я думаю, вам следует попытаться уменьшить количество обращений к нему, если это возможно.

3. @ DarkDust k привет, я пытаюсь записать игровой процесс моей игры, чтобы я мог загружать видео на YouTube с самого устройства … пытаюсь сделать то же самое, что приложение Talking tomcat для iphone .. записывать видео, затем воспроизводить его и т.д. … я думаю, что это приложение также создано с помощью Opengl ES, В нем также есть функция записи видео, но оно не замедляется при чтении каждого кадра есть идеи?

4. @Tornado: Нет, пожалуйста, задайте новый вопрос по этому поводу.

Ответ №2:

Вдохновленный DarkDust, я успешно реализовал захват экрана в сочетании uiview и openglview (просмотр cocos2d 2.0). Я немного переработал код и вставил ниже, надеюсь, это полезно для других.

Чтобы помочь объяснить настройку, экран моего приложения имеет 4 слоя просмотра: задняя часть — фоновый UIView с фоновыми изображениями «backgroundLayer», средняя — 2 слоя Cocos2d glview «glLayer1 и glLayer2»; и передняя часть — еще один слой UIView с несколькими элементами управления пользовательского интерфейса (например, UIButtons) «frontView».

Вот код:

   (UIImage *) grabScreenshot
{
    // Get the 2 layers in the middle of cocos2d glview and store it as UIImage
    [CCDirector sharedDirector].nextDeltaTimeZero = YES;

    CGSize winSize = [CCDirector sharedDirector].winSize;
    CCRenderTexture* rtx =
        [CCRenderTexture renderTextureWithWidth:winSize.width
                                         height:winSize.height];
    [rtx begin];
    [glLayer1 visit];
    [glLayer2 visit];
    [rtx end];

    UIImage *openglImage = [rtx getUIImage];

    UIGraphicsBeginImageContext(winSize);

    // Capture the bottom layer
    [backgroundView.layer renderInContext:UIGraphicsGetCurrentContext()];
    // Save the captured glLayers image to the image context
    [openglImage drawInRect:CGRectMake(0, 0, openglImage.size.width, openglImage.size.height)];
    [frontView.layer renderInContext:UIGraphicsGetCurrentContext()];

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

    return viewImage;
}