Problema esportazione dei dati dei pixel NSOpenGLView per alcuni formati di file immagine utilizzando ImageKit & CGImageDestination

StackOverflow https://stackoverflow.com/questions/2878488

Domanda

Riepilogo: l'esportazione dei dati di pixel da NSOpenGLView per alcuni formati di file dà colori non corretti

Sto sviluppando un'applicazione per visualizzare alcuni dati sperimentali. Una delle sue funzioni è quello di rendere i dati in una sottoclasse NSOpenGLView, e consentire l'immagine risultante da esportare in un file o copiato negli appunti.

Le esportazioni visualizzare i dati come un NSImage, generate in questo modo:

- (NSImage*) image
{
    NSBitmapImageRep* imageRep;
    NSImage* image;
    NSSize viewSize = [self bounds].size;
    int width = viewSize.width;
    int height = viewSize.height;

    [self lockFocus];
    [self drawRect:[self bounds]];
    [self unlockFocus];

    imageRep=[[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                      pixelsWide:width
                                                      pixelsHigh:height
                                                   bitsPerSample:8
                                                 samplesPerPixel:4
                                                        hasAlpha:YES
                                                        isPlanar:NO
                                                  colorSpaceName:NSDeviceRGBColorSpace
                                                     bytesPerRow:width*4
                                                    bitsPerPixel:32] autorelease];
    [[self openGLContext] makeCurrentContext];
    glReadPixels(0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,[imageRep bitmapData]);
    image=[[[NSImage alloc] initWithSize:NSMakeSize(width,height)] autorelease];
    [image addRepresentation:imageRep];
    [image setFlipped:YES]; // this is deprecated in 10.6
    [image lockFocusOnRepresentation:imageRep]; // this will flip the rep
    [image unlockFocus];
    return image;
}

Copia usi questa immagine molto semplicemente, in questo modo:

- (IBAction) copy:(id) sender
{
    NSImage* img = [self image];
    NSPasteboard* pb = [NSPasteboard generalPasteboard];
    [pb clearContents];
    NSArray* copied = [NSArray arrayWithObject:img];
    [pb writeObjects:copied];
}

Per la scrittura di file, io uso il pannello ImageKit IKSaveOptions accessorio per impostare il tipo di file di output e le opzioni associate, quindi utilizzare il seguente codice per fare la scrittura:

NSImage* glImage = [glView image];
NSRect rect = [glView bounds];
rect.origin.x = rect.origin.y = 0;
img = [glImage CGImageForProposedRect:&rect
                              context:[NSGraphicsContext currentContext]
                                hints:nil];

if (img)
{
    NSURL* url = [NSURL fileURLWithPath: path];
    CGImageDestinationRef dest = CGImageDestinationCreateWithURL((CFURLRef)url,
                                                                 (CFStringRef)newUTType,
                                                                 1,
                                                                 NULL);
    if (dest)
    {
        CGImageDestinationAddImage(dest,
                                   img,
                                   (CFDictionaryRef)[imgSaveOptions imageProperties]);
        CGImageDestinationFinalize(dest);
        CFRelease(dest);
    }
}

(ho rifilato un po 'di codice estraneo qui, ma nulla che possa influenzare il risultato, per quanto posso vedere. Il newUTType proviene dal pannello IKSaveOptions.)

Questo funziona bene quando il file viene esportato come GIF, JPEG, PNG, PSD o TIFF, ma l'esportazione in PDF, BMP, TGA, ICNS e JPEG-2000 produce un colore rosso manufatto sulla parte dell'immagine. Immagini di esempio sono al di sotto, la prima esportata in formato JPG, il secondo come PDF.

immagine esportata in formato JPEG, con i colori corretti
(fonte: walkytalky.net )

immagine esportata in formato PDF, con striature rosso sulla pipetta
(fonte: walkytalky.net )

Copia nella clipboard non presenta questo striscia rossa con l'attuale implementazione di image, ma ha con l'implementazione originale, che ha generato il imageRep utilizzando NSCalibratedRGBColorSpace piuttosto che NSDeviceRGBColorSpace. Quindi immagino ci sia qualche problema con la rappresentazione dei colori nei pixel che ricevo da OpenGL che non ottiene attraverso le conversioni successive correttamente, ma io sono in perdita quanto a che cosa fare al riguardo.

Quindi, qualcuno mi può (i) dica che cosa sta causando questo, e (ii) come posso farlo andare via? Non mi interessa tanto di tutti dei formati ma mi piacerebbe davvero come almeno PDF al lavoro.

È stato utile?

Soluzione

OK. Come dimostra il silenzio assordante che ha incontrato questa domanda, il problema risulta essere un po 'oscura. Ma la soluzione è bello e semplice, in modo che sto descrivendo qui solo nel caso in cui nessuno mai vuole sapere.

Riepilogo:. Alcuni formati di esportazione di file non affrontare bene con traslucenza nei pixel resi

Non capire le ragioni esatte per questo, anche se potrebbe eventualmente avere a che fare con la presenza o l'assenza di alfa pre-moltiplicazione. Tutti i formati sembrano andare bene con i pixel completamente trasparenti, rendendoli trasparenti o come bianca se il formato non supporta la trasparenza. Ma pixel che hanno un alpha parziale, oltre a qualcosa nei canali di colore, possono ottenere alterati.

Si dà il caso, non ho nemmeno voglio eventuali parti dell'immagine per essere trasparente, e in effetti set glDisable(GL_BLEND) prima che il codice di rendering in questione. Tuttavia, gli oggetti sono stati resi con i materiali da questa collezione apparentemente canonica presso il sito principale OpenGL , alcuni dei quali includono alfa valori diversi da 1.0 nella loro speculare, diffusa e colori ambientali. Avevo pedissequamente copiato questo senza prestare attenzione a questo fatto che potrebbe portare a qualche traslucenza indesiderati.

Per i miei scopi, quindi, la soluzione è semplice:. modificare le definizioni di materiale in modo che la componente alfa è sempre 1.0

Si noti che alcuni formati di immagine, come PNG e TIFF, do sostenere pienamente la traslucenza, quindi se avete bisogno che poi questi sono quelli di andare per.

Questa è stata, di fatto ciò che mi soffiata per la risposta. Tuttavia non è stato evidente in un primo momento perché ero utilizzando OS X Preview per visualizzare i file, e la traslucenza non è evidente con le impostazioni di visualizzazione di default:

traslucido pipetta come esportati in BMP
(fonte: walkytalky.net )

traslucido pipetta come esportato in PNG e quindi JPG in Anteprima
(fonte: walkytalky.net )

traslucido pipetta, come esportare in PNG, visualizzati in anteprima
(fonte: walkytalky.net ) |

traslucido pipetta, come esportare in PNG, vista in Photoshop
(fonte: walkytalky.net ) |

Quindi, una seconda lezione da tutto questo episodio è: abilitare Visualizza | Mostra immagine di sfondo in Anteprima per ottenere la scacchiera e mostrare alcuna trasparenza randagi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top