Problema esportazione dei dati dei pixel NSOpenGLView per alcuni formati di file immagine utilizzando ImageKit & CGImageDestination
-
04-10-2019 - |
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.
(fonte: walkytalky.net )
(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.
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:
(fonte: walkytalky.net )
(fonte: walkytalky.net )
(fonte: walkytalky.net ) |
(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.