2012-09-21 18 views
18

Quello che segue è il codice che uso per la lettura di un'immagine da una scena di OpenGL ES:Perché glReadPixels() non funziona in questo codice in iOS 6.0?

-(UIImage *)getImage{ 

    GLint width; 

    GLint height; 

    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width); 

    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height); 


    NSLog(@"%d %d",width,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 = kCGBitmapByteOrderDefault; 
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

    // 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]; 
    CGImageRelease(imageRef); 
    CGDataProviderRelease(provider); 
    CGColorSpaceRelease(colorSpaceRef); 
    free(buffer); 
    free(buffer2); 
    return myImage; 

} 

Questo è il lavoro in iOS 5.xe versioni più bassi, ma su iOS 6.0 questo torna ora un'immagine nera. Perché il problema è glReadPixels() non riuscito su iOS 6.0?

+0

hm, il mio aspetto le stesso e funziona, eccetto 'GLint viewport [4]; glGetIntegerv (GL_VIEWPORT, viewport); int width = viewport [2]; int height = viewport [3]; ' – SAKrisT

+0

funziona il tuo codice? – GameLoading

+0

@SAKrisT in ios 6? – GameLoading

risposta

25
CAEAGLLayer *eaglLayer = (CAEAGLLayer *) self.layer; 
eaglLayer.drawableProperties = @{ 
    kEAGLDrawablePropertyRetainedBacking: [NSNumber numberWithBool:YES], 
    kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGBA8 
}; 

set

kEAGLDrawablePropertyRetainedBacking = YES 

(non so il motivo per cui questo suggerimento sta andando bene ..///)

+2

anche io non so come funziona Ma funziona solo: D – GameLoading

+10

Il motivo è probabilmente che tu ' stai cercando di leggere dallo schermo dopo che il contenuto è stato presentato usando '[context presentRenderbuffer: GL_RENDERBUFFER];'. A meno che non imposti il ​​livello per utilizzare il supporto trattenuto, come fai sopra, non ti è garantito che questo contenuto rimanga incollato dopo che è stato presentato. Sembra che iOS 6.0 sia più aggressivo nella rimozione di questo contenuto dopo che non è più necessario. Quanto sopra provocherà un impatto sulle prestazioni, quindi potrebbe essere meglio eseguire un'operazione 'glFinish()' e catturare lo schermo dopo di ciò, quindi presentare il buffer di rendering. –

+1

Ho avuto eaglLayer.opaque = TRUE; nel mio codice che impedisce anche il funzionamento del codice dello screenshot, ho cancellato eaglLayer.opaque = TRUE; e imposta kEAGLDrawablePropertyRetainedBacking = YES. Ora funziona. –

-4

bro prova questo metodo per ottenere l'immagine dello screenshot. L'immagine di output è MailImage

- (UIImage*)screenshot 
{ 
    // Create a graphics context with the target size 
    // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration 
    // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext 
    CGSize imageSize = [[UIScreen mainScreen] bounds].size; 
    if (NULL != UIGraphicsBeginImageContextWithOptions) 
     UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 
    else 
     UIGraphicsBeginImageContext(imageSize); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    // Iterate over every window from back to front 
    for (UIWindow *window in [[UIApplication sharedApplication] windows]) 
    { 
     if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen]) 
     { 
      // -renderInContext: renders in the coordinate space of the layer, 
      // so we must first apply the layer's geometry to the graphics context 
      CGContextSaveGState(context); 
      // Center the context around the window's anchor point 
      CGContextTranslateCTM(context, [window center].x, [window center].y); 
      // Apply the window's transform about the anchor point 
      CGContextConcatCTM(context, [window transform]); 
      // Offset by the portion of the bounds left of and above the anchor point 
      CGContextTranslateCTM(context, 
            -[window bounds].size.width * [[window layer] anchorPoint].x, 
            -[window bounds].size.height * [[window layer] anchorPoint].y); 

      // Render the layer hierarchy to the current context 
      [[window layer] renderInContext:context]; 

      // Restore the context 
      CGContextRestoreGState(context); 
     } 
    } 

    // Retrieve the screenshot image 
    Mailimage = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return Mailimage; 


} 
+0

mi dà l'intera immagine dello schermo escludendo l'immagine che è nel buffer – GameLoading

+1

Questa risposta fondamentalmente fa tutto eccetto quello che OP chiede ... –

Problemi correlati