رسم nsimage القياسي مقلوب (أبيض بدلاً من الأسود)
-
22-09-2019 - |
سؤال
أحاول رسم nsimage قياسي باللون الأبيض بدلاً من الأسود. ما يلي يعمل بشكل جيد لرسم الصورة باللون الأسود في NSGraphicsContext الحالي:
NSImage* image = [NSImage imageNamed:NSImageNameEnterFullScreenTemplate];
[image drawInRect:r fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
كنت أتوقع أن يقوم nscompositexor بالخدعة ، لكن لا. هل أحتاج إلى النزول في مسار [cifilter filterwithName:@"cicolorinvert"]؟ أشعر أنني يجب أن أفتقد شيئًا بسيطًا.
أندرس
المحلول
سيكون مسار الصورة الأساسية هو الأكثر موثوقية. في الواقع ليس معقدًا للغاية ، لقد نشرت عينة أدناه. إذا كنت تعرف أي من صورك لن يتم قلبها ، فيمكنك إزالة رمز التحويل. الشيء الرئيسي الذي يجب توخي الحذر هو أن التحويل من 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]];
نصائح أخرى
ملاحظة واحدة فقط: لقد وجدت أن مرشح Cicolorinvert لا يمكن الاعتماد عليه دائمًا. على سبيل المثال ، إذا كنت ترغب في عكس صورة مقلوبة في Photoshop ، فإن Cifilter ستنتج صورة أخف بكثير. بقدر ما فهمت ، يحدث ذلك بسبب الاختلافات في قيمة جاما من cifilter (غاما هو 1) والصور التي جاءت من مصادر أخرى.
بينما كنت أبحث عن طرق لتغيير قيمة gamma لـ cifilter ، وجدت ملاحظة أن هناك خطأ في cicontext: تغيير قيمة gamma من الافتراضي 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];