2010-12-04 174 views
9

我希望我能爲此找到答案。我已經搜索和搜索,無法得到正確的答案。這是我的情況:Mac OS Cocoa:在畫布上畫一個簡單的像素

在Mac OS可可應用程序中,我想繪製一個像素(實際上是幾個像素)到我的應用程序窗口的專用區域。我想,如果將NSImageView放置在那裏(我在IB中這樣做並將插座連接到我的應用程序代理),並使用該插件而不是我的NSWindow會更好。

我在世界上怎麼可以做到這一點? Mac OS似乎提供NSBezierPath作爲最基本的繪圖工具—是真的嗎?這對我來說是完全令人震驚的。我來自Windows編程的悠久歷史,並將畫素繪製到畫布上是最簡單的事情,通常是這樣。

我不想使用OpenGL,我不確定Quartz涉及到什麼程度。

所有我想要的是我怎麼能拉斷這個僞現實的Objective-C /可可一些幫助:

imageObj.drawPixel(10,10,blackColor); 

我很樂意聽到這個答案,我相信這將有助於很多人從可可開始。

謝謝!

回答

9

可可的低級別的繪圖API是核心圖形(石英)。您可以獲取繪圖上下文併發出命令來繪製該上下文。 API被設計爲獨立於設備(在打印時,您可以使用相同的命令在屏幕上繪圖,就像在紙上繪圖一樣)。因此,沒有用於填充單個像素的命令,因爲紙張上沒有像素。即使在屏幕上,您的視圖也可能以某種方式進行了轉換,以便單個點不映射到單個設備像素。

如果你想繪製一個像素,你需要指定一個矩形作爲單個像素的大小,然後填充它。對於像素(x,y),你需要一個帶有原點的矩形(x-0.5,y-0.5)和(1,1)的大小。

您可以使用NSBezierPath來做到這一點,或者您可以從[[NSGraphicsContext currentContext] graphicsPort]獲得Core Graphics上下文(CGContextRef)並使用CGContextFillRect()之類的函數。

如果你繪製了很多像素,這顯然不會很快;這不是API的設計目的。如果這是你需要做的,考慮用malloc創建一個緩衝區,然後將你的像素數據寫入該緩衝區,然後使用Core Graphics將它轉換爲CGImageRef,然後將其繪製到屏幕上。

1

也許我誤解的問題,但石英具有填充矩形的能力:

void CGContextFillRect (CGContextRef c, CGRect rect); 
+0

或者從drawRect:或lockFocus塊中,您可以直接使用NSFillRect而不需要獲取CGContextRef – 2010-12-05 01:01:14

3

對於你描述繪製像素,沒有必要創建一個路徑或訴諸石英2D或OpenGL API 。

請參閱NSRectFill()和相關功能,如NSRectFillList()NSRectFillUsingOperation()

如果你正在繪製大量的單個像素,那麼NSRectFillList()的速度就像你可以做的一樣快,而不需要使用自己的圖像緩衝區。

11

你所要求的這兩種方法是:

NSBitmapRep setColor:atX:y:在指定座標的變化像素的顏色。

NSBitmapRep setPixel:atX:y:將接收器在指定座標處的像素設置爲指定的原始像素值。

請注意,這些在iOS上不可用。在iOS上,看起來這樣做的方法是爲給定的色彩空間(可能爲RGB)創建像素數據的原始緩衝區,用顏色數據填充該區域(編寫一個小的setPixel方法來完成此操作),然後調用CGImageCreate()像這樣:

//Create a raw buffer to hold pixel data which we will fill algorithmically 
    NSInteger width = theWidthYouWant; 
    NSInteger height = theHeightYouWant; 
    NSInteger dataLength = width * height * 4; 
    UInt8 *data = (UInt8*)malloc(dataLength * sizeof(UInt8)); 

    //Fill pixel buffer with color data 
    for (int j=0; j<height; j++) { 
     for (int i=0; i<width; i++) { 

      //Here I'm just filling every pixel with red 
      float red = 1.0f; 
      float green = 0.0f; 
      float blue = 0.0f; 
      float alpha = 1.0f; 

      int index = 4*(i+j*width); 
      data[index] =255*red; 
      data[++index]=255*green; 
      data[++index]=255*blue; 
      data[++index]=255*alpha; 

     } 
    } 

    // Create a CGImage with the pixel data 
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, dataLength, NULL); 
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 
    CGImageRef image = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, 

          provider, NULL, true, kCGRenderingIntentDefault); 

    //Clean up 
    CGColorSpaceRelease(colorspace); 
    CGDataProviderRelease(provider); 
    // Don't forget to free(data) when you are done with the CGImage 

最後,您可能想要操縱已加載到CGImage中的圖像中的像素。在Apple Technical Q & A中有一個示例代碼,名爲QA1509 Getting the pixel data from a CGImage object

0

這裏的借鑑OS X的像素的快捷方式:

- (void)drawRect:(NSRect)dirtyRect { 
    [super drawRect:dirtyRect]; 

    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] 
          initWithFocusedViewRect:dirtyRect]; 

    for (int x = 0; x < [rep pixelsWide]; x++) { 
     for (int y = 0; y < [rep pixelsHigh]; y++) { 
      NSUInteger pixel[4] = { 0, 255, 0, 255 }; 
      [rep setPixel:pixel atX:x y:y]; 
     } 
    } 

    [rep drawInRect:dirtyRect]; 
}