2010-01-26 4 views
3

J'essaye de dessiner un NSImage standard en blanc au lieu du noir. Les travaux suivants fins pour dessiner l'image en noir dans le NSGraphicsContext actuel:Dessine le NSImage standard inversé (blanc au lieu du noir)

NSImage* image = [NSImage imageNamed:NSImageNameEnterFullScreenTemplate]; 
[image drawInRect:r fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0]; 

I expected NSCompositeXOR faire l'affaire, mais non. Dois-je descendre le chemin compliqué [CIFilter filterWithName: @ "CIColorInvert"]? J'ai l'impression qu'il me manque quelque chose de simple.

Anders

Répondre

6

La route Core Image serait le plus fiable. En fait, ce n'est pas très compliqué, j'ai posté un exemple ci-dessous. Si vous savez qu'aucune de vos images ne sera retournée, vous pouvez supprimer le code de transformation. La principale chose à faire est que la conversion de NSImage à CIImage peut être coûteuse en termes de performances, vous devez donc veiller à mettre en cache le CIImage si possible et ne pas le recréer lors de chaque opération de dessin.

CIImage* ciImage = [[CIImage alloc] initWithData:[yourImage TIFFRepresentation]]; 
if ([yourImage isFlipped]) 
{ 
    CGRect cgRect = [ciImage extent]; 
    CGAffineTransform transform; 
    transform = CGAffineTransformMakeTranslation(0.0,cgRect.size.height); 
    transform = CGAffineTransformScale(transform, 1.0, -1.0); 
    ciImage = [ciImage imageByApplyingTransform:transform]; 
} 
CIFilter* filter = [CIFilter filterWithName:@"CIColorInvert"]; 
[filter setDefaults]; 
[filter setValue:ciImage forKey:@"inputImage"]; 
CIImage* output = [filter valueForKey:@"outputImage"]; 
[output drawAtPoint:NSZeroPoint fromRect:NSRectFromCGRect([output extent]) operation:NSCompositeSourceOver fraction:1.0]; 

Remarque: libérer/conserver la gestion de la mémoire est laissé à titre d'exercice, le code ci-dessus suppose la récupération de place.

Si vous voulez rendre l'image à une taille arbitraire, vous pouvez effectuer les opérations suivantes:

NSSize imageSize = NSMakeSize(1024,768); //or whatever size you want 
[yourImage setSize:imageSize]; 
[yourImage lockFocus]; 
NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, imageSize.width, imageSize.height)]; 
[yourImage unlockFocus]; 
CIImage* image = [CIImage imageWithData:[bitmap TIFFRepresentation]]; 
+0

Merci, qui ne résout le problème d'inversion des couleurs. Malheureusement, cela ne me donne pas la pleine résolution: il semble que la TIFFRprésentation initiale est beaucoup plus petite que la taille que je veux en tirer. Comment puis-je m'assurer d'obtenir les données à haute résolution? – smartgo

+0

Vous pouvez créer un 'NSBitmapImageRep' à partir du' NSImage' en utilisant la taille que vous voulez et ensuite créer le 'CIImage' de l'image bitmap, voir ici: http://pastie.org/798088 –

+0

Parfait, merci beaucoup! – smartgo

0

Juste une remarque: je trouve que le filtre CIColorInvert est pas toujours fiable. Par exemple, si vous souhaitez inverser une image inversée dans Photoshop, le CIFilter produira une image beaucoup plus claire. Pour autant que je l'aie compris, cela se produit en raison des différences de valeur gamma de CIFilter (gamma est 1) et des images provenant d'autres sources.

Alors que je cherchais des moyens de changer la valeur gamma pour CIFilter, j'ai trouvé une note qu'il y avait un bug dans CIContext: changer sa valeur gamma par défaut 1 produirait des résultats imprévisibles. Néanmoins, il existe une autre solution pour inverser NSImage, qui produit toujours les résultats corrects - en inversant les pixels de NSBitmapImageRep.

Je reposter le code de etutorials.org (http://bit.ly/Y6GpLn):

// srcImageRep is the NSBitmapImageRep of the source image 
int n = [srcImageRep bitsPerPixel]/8;   // Bytes per pixel 
int w = [srcImageRep pixelsWide]; 
int h = [srcImageRep pixelsHigh]; 
int rowBytes = [srcImageRep bytesPerRow]; 
int i; 

NSImage *destImage = [[NSImage alloc] initWithSize:NSMakeSize(w, h)]; 
NSBitmapImageRep *destImageRep = [[[NSBitmapImageRep alloc] 
     initWithBitmapDataPlanes:NULL 
      pixelsWide:w 
      pixelsHigh:h 
      bitsPerSample:8 
      samplesPerPixel:n 
      hasAlpha:[srcImageRep hasAlpha] 
      isPlanar:NO 
      colorSpaceName:[srcImageRep colorSpaceName] 
      bytesPerRow:rowBytes 
      bitsPerPixel:NULL] autorelease]; 

unsigned char *srcData = [srcImageRep bitmapData]; 
unsigned char *destData = [destImageRep bitmapData]; 

for (i = 0; i < rowBytes * h; i++) 
    *(destData + i) = 255 - *(srcData + i); 

[destImage addRepresentation:destImageRep]; 
Questions connexes