Рисуем стандартный NSImage перевернутый (белый вместо черного) - PullRequest
3 голосов
/ 26 января 2010

Я пытаюсь нарисовать стандартный NSImage белым, а не черным.Следующее прекрасно работает для рисования изображения в черном цвете в текущем NSGraphicsContext:

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

Я ожидал, что NSCompositeXOR добьется цели, но нет.Нужно ли идти по сложному пути [CIFilter filterWithName: @ "CIColorInvert"]?Я чувствую, что, должно быть, мне не хватает чего-то простого.

Андерс

Ответы [ 2 ]

6 голосов
/ 27 января 2010

Маршрут Core Image будет наиболее надежным. Это на самом деле не очень сложно, я разместил образец ниже. Если вы знаете, что ни одно из ваших изображений не будет перевернуто, вы можете удалить код преобразования. Главное, на что следует обратить внимание, это то, что преобразование NSImage в CIImage может быть дорогостоящим с точки зрения производительности, поэтому вы должны убедиться, что вы кэшируете CIImage, если это возможно, и не создавайте его заново при каждой операции рисования. .

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];

Примечание: управление освобождением / сохранением памяти оставлено в качестве упражнения, код выше предполагает сборку мусора.

Если вы хотите визуализировать изображение произвольного размера, вы можете сделать следующее:

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 голосов
/ 07 апреля 2013

Только одно замечание: я обнаружил, что фильтр CIColorInvert не всегда надежен. Например, если вы хотите инвертировать изображение, перевернутое в Photoshop, фильтр CIFilter сделает изображение более светлым. Насколько я понял, это происходит из-за различий в гамма-значении CIFilter (гамма 1) и изображений, полученных из других источников.

Пока я искал способы изменить значение гаммы для CIFilter, я обнаружил, что в CIContext есть ошибка: изменение его значения гаммы со значения по умолчанию 1 приведет к непредсказуемым результатам.

Несмотря на это, существует другое решение для инвертирования NSImage, которое всегда дает правильные результаты - путем инвертирования пикселей NSBitmapImageRep.

Я пересылаю код с 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];
...