3 votes

Comment obtenir une image transparente à partir du contexte OpenGL ES sur l'iPhone

J'ai un problème avec OpenGL ES sur l'iPhone.

Je travaille sur un projet qui dessine quelque chose sur la vue, puis enregistre l'image. Il a aussi une image de fond. J'ai combiné l'image obtenue de la vue et l'image de fond.

J'ai défini la propriété opaque de la vue comme NON, mais l'image obtenue de la vue reste opaque. Je n'ai donc pas pu combiner les deux images ensemble. Je ne pouvais voir que l'image de devant, l'image de fond était introuvable.

CAEAGLLayer *EAGLLayer = (CAEAGLLayer *)self.layer;
        EAGLLayer.opaque = NO;

Obtenez le code de l'image comme ceci :

- (UIImage *)GetImage
{
    CGFloat Width = self.frame.size.width;
    CGFloat Height = self.frame.size.height;
    GLubyte *TmpBuffer = (GLubyte *)malloc(Width * Height * 4);
    glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, TmpBuffer);
    GLubyte *Buffer = (GLubyte *)malloc(Width * Height * 4);

    for(int y=0; y<Height; y++) {
        for(int x=0; x<Width * 4; x++) {
            Buffer[((NSInteger)Height - 1 - y) * (NSInteger)Width * 4 + x] = TmpBuffer[y * 4 * (NSInteger)Width + x];
        }
    }
    CGDataProviderRef Provider = CGDataProviderCreateWithData(NULL, Buffer, Width * Height * 4, NULL);

    int BitsPerComponent = 8;
    int BitsPerPixel = 32;
    int BytesPerRow = 4 * 480;
    CGColorSpaceRef ColorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo BitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent RenderingIntent = kCGRenderingIntentDefault;

    // Make the cgimage.
    CGImageRef ImageRef = CGImageCreate(480, 320, 
                                        BitsPerComponent, 
                                        BitsPerPixel, 
                                        BytesPerRow, 
                                        ColorSpaceRef, 
                                        BitmapInfo, 
                                        Provider, 
                                        NULL, NO, 
                                        RenderingIntent);

    return [UIImage imageWithCGImage:ImageRef];
}

Combinez le code comme ceci :

- (void)Combine:(UIImage *)Back
{
    UIGraphicsBeginImageContext(self.frame.size);

    CGContextRef aContext = UIGraphicsGetCurrentContext();

    CGContextSaveGState(aContext);

    CGContextScaleCTM(aContext, 1.0, -1.0);
    CGContextTranslateCTM(aContext, 0, -self.frame.size.height);

    UIImage *Front = [self GetImage];

    CGContextDrawImage(aContext, 
                       CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), 
                       Back.CGImage);

    CGContextDrawImage(aContext, 
                       CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), 
                       Front.CGImage);

    CGContextRestoreGState(aContext);

    UIImageWriteToSavedPhotosAlbum(UIGraphicsGetImageFromCurrentImageContext(), nil, nil, nil);

    UIGraphicsEndImageContext();
}

Que dois-je faire ? Toute suggestion sera la bienvenue. Merci d'avance.

1voto

Gary McGowan Points 76

C'est exactement ce que j'ai fait.

J'ai utilisé les propriétés suivantes de CAEAGLLayer :

eaglLayer.opaque = NO;      
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kEAGLDrawablePropertyRetainedBacking,kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];

et dans votre -(UIImage *)GetImage plutôt utiliser la méthode :

CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;

si nécessaire, votre Combinez : peut être ajustée pour sauvegarder les deux images combinées dans une UIImage en utilisant :

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

J'espère que cela vous aidera :)

0voto

Perrako Points 513

Comment créez-vous votre tampon OpenGL ? Plus précisément, dans votre EAGLView, quand ou vous définissez la propriété drawableProperties de votre couche CAEAGLL, il devrait ressembler à quelque chose comme ça :

eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];

Si vous utilisez kEAGLColorFormatRGB565 au lieu de kEAGLColorFormatRGBA8, votre framebuffer ne stockera pas de valeur alpha, il sera donc toujours opaque.

Si vous ne définissez pas déjà cette propriété, essayez de la définir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X