2013-03-08 4 views
1

J'utilise [uiImage drawAtPoint] pour dessiner une nouvelle image. Mais il s'avère que la couleur est changée. Mon image originale uiImage est rouge alors que l'image générée newImage est bleue. Voici mon code:L'ordre des octets UIImage a été modifié

UIImage* uiImage = [UIHelper loadImage:fileName]; 
NSString *text = [ApplicationSettings instance].user.name; 
UIGraphicsBeginImageContext(uiImage.size); 
[uiImage drawAtPoint: CGPointZero]; 
[text drawAtPoint: CGPointMake(10, 10) withFont: [UIFont systemFontOfSize: 12]]; 
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
return [Texture createTexture: newImage]; 

Et [Texture createTexture]:

+ (Texture*) createTextureWithImage:(UIImage*)image { 
    Texture* tex = [[[Texture alloc] init] autorelease]; 
    if ([tex loadImage:image]) 
     return tex; 
    else { 
     NSLog(@"Failed to load image %@", image); 
     return nil; 
    } 
} 

- (BOOL)loadImage:(UIImage *)image { 
    BOOL ret = NO; 

    if (image) { 
     // Get the inner CGImage from the UIImage wrapper 
     CGImageRef cgImage = image.CGImage; 

     // Get the image size 
     width = CGImageGetWidth(cgImage); 
     height = CGImageGetHeight(cgImage); 

     // Record the number of channels 
     channels = CGImageGetBitsPerPixel(cgImage)/CGImageGetBitsPerComponent(cgImage); 

     // Generate a CFData object from the CGImage object (a CFData object represents an area of memory) 
     CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(cgImage)); 

     // Copy the image data for use by Open GL 
     ret = [self copyImageDataForOpenGL: imageData]; 
     CFRelease(imageData); 
    } 

    return ret; 
} 

Et [texture copyImageDataForOpenGL]

- (BOOL)copyImageDataForOpenGL:(CFDataRef)imageData { 
    if (pngData) { 
     free(pngData); 
    } 

    pngData = (unsigned char*)malloc(width * height * channels); 
    const int rowSize = width * channels; 
    const unsigned char* pixels = (unsigned char*)CFDataGetBytePtr(imageData); 

    // Copy the row data from bottom to top 
    for (int i = 0; i < height; ++i) { 
     memcpy(pngData + rowSize * i, pixels + rowSize * (height - 1 - i), width * channels); 
    } 

    return YES; 
} 

Je suppose que l'image générée utilise pour RVB tandis que l'original utilise l'ordre inverse . C'est parce que la couleur blanche et noire reste la même.

EDIT

J'utilise OpenGL ES pour rendre cette texture. Au lieu de return [Texture createTexture: newImage] fonctionne parfaitement, mais je veux dessiner le texte uiImage.

J'ai testé UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil); et l'image enregistrée est correcte. J'ai imprimé CGImageGetBitmapInfo(uiImage.CGImage)) et CGImageGetBitmapInfo(newImage.CGImage), et ils ne sont pas identiques!

+0

Je vous recommande d'utiliser UIGraphicsBeginImageContextWithOptions (uiImage.size, NO, 0,0); au lieu de UIGraphicsBeginImageContext (uiImage.size); afin de soutenir le rendu de l'écran rétine. Toutefois, cela ne devrait pas être la raison pour laquelle votre rendu d'image inverse les couleurs. J'aimerais regarder plus en profondeur plus tard - en vous écrivant dès que possible (tant que cela n'a pas été résolu déjà;)). – Markus

+0

@Markus Cela ne fonctionne pas avec 'UIGraphicsBeginImageContextWithOptions'. –

+0

Vous ne voyez aucune image? S'il vous plaît essayez d'utiliser OUI opaque au lieu de NON (2ème paramètre) et si cela ne vous dérange pas s'il vous plaît partager le résultat. – Markus

Répondre

1

Cette ma version actuelle et correcte de copyImageDataForOpenGL

- (BOOL)copyImageDataForOpenGL:(CGImageRef)image { 
    if (pngData) { 
     free(pngData); 
    } 

    pngData = (GLubyte*)malloc(width * height * channels); 
    const int rowSize = width * channels; 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    NSUInteger bytesPerPixel = channels; 
    NSUInteger bytesPerRow = bytesPerPixel * width; 
    NSUInteger bitsPerComponent = 8; 
    CGContextRef context = CGBitmapContextCreate(pngData, width, height, 
               bitsPerComponent, bytesPerRow, colorSpace, 
               kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
    CGColorSpaceRelease(colorSpace); 
    CGContextClearRect(context, CGRectMake(0, 0, width, height)); 
    CGContextTranslateCTM(context, 0,0); 
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); 

    [ARRenderer flipRGBData: pngData bytesPerRow:bytesPerRow height:height]; 
    return YES; 
} 

[ARRenderer flipRGBData] est défini comme

+ (void)flipRGBData:(GLubyte*)data bytesPerRow:(int)bytesPerRow height:(int)height { 
    GLubyte* swp = (GLubyte*)malloc(bytesPerRow); 
    for (int h = 0; h < height/2; h++) { 
     memcpy(swp, data + (height - 1 - h) * bytesPerRow, bytesPerRow); 
     memcpy(data + (height - 1 - h) * bytesPerRow, data + h * bytesPerRow, bytesPerRow); 
     memcpy(data + h * bytesPerRow, swp, bytesPerRow); 
    } 
    free(swp); 
} 
Questions connexes