【问题标题】:How can I display an array of pixels on a NSWindow?如何在 NSWindow 上显示像素数组?
【发布时间】:2012-06-08 20:53:22
【问题描述】:

非常简单的问题...我有一个像素数组,如何在屏幕上显示它们?

#define WIDTH 10
#define HEIGHT 10
#define SIZE WIDTH*HEIGHT

unsigned short pixels[SIZE];

for (int i = 0; i < WIDTH; i++) {
    for (int j = 0; j < HEIGHT; j++) {
        pixels[j*HEIGHT + i] = 0xFFFF;
    }
}

就是这样......现在我怎样才能在屏幕上显示它们?

【问题讨论】:

  • 我尝试过使用 CGImage,但我无法让它工作。要创建一个 CGImage 我必须传递一个 CGDataProvider 作为参数,我不知道它是如何工作的......这似乎是一个非常简单的任务,所以我认为我走错了路......

标签: objective-c cocoa xcode4 pixel cgimage


【解决方案1】:
  1. 创建一个新的“Cocoa 应用程序”(如果您不知道如何创建一个可可应用程序,请转到Cocoa Dev Center
  2. 子类 NSView(如果您不知道如何子类化视图 read section "Create the NSView Subclass"
  3. 在界面生成器上将您的 NSWindow 设置为 400x400 大小
  4. 在您的 NSView 中使用此代码

    #import "MyView.h"
    
    @implementation MyView
    
    #define WIDTH 400
    #define HEIGHT 400
    #define SIZE (WIDTH*HEIGHT)
    #define BYTES_PER_PIXEL 2
    #define BITS_PER_COMPONENT 5
    #define BITS_PER_PIXEL 16
    
    - (id)initWithFrame:(NSRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code here.
        }
        return self;
    }
    
    - (void)drawRect:(NSRect)dirtyRect
    {
        // Get current context
        CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
    
        // Colorspace RGB
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
        // Pixel Matrix allocation
        unsigned short *pixels = calloc(SIZE, sizeof(unsigned short));
    
        // Random pixels will give you a non-organized RAINBOW 
        for (int i = 0; i < WIDTH; i++) {
            for (int j = 0; j < HEIGHT; j++) {
                pixels[i+ j*HEIGHT] = arc4random() % USHRT_MAX;
            }
        }
    
        // Provider
        CGDataProviderRef provider = CGDataProviderCreateWithData(nil, pixels, SIZE, nil);
    
        // CGImage
        CGImageRef image = CGImageCreate(WIDTH,
                                         HEIGHT,
                                         BITS_PER_COMPONENT,
                                         BITS_PER_PIXEL,
                                         BYTES_PER_PIXEL*WIDTH,
                                         colorSpace,
                                         kCGImageAlphaNoneSkipFirst,
                                         // xRRRRRGGGGGBBBBB - 16-bits, first bit is ignored!
                                         provider,
                                         nil, //No decode
                                         NO,  //No interpolation
                                         kCGRenderingIntentDefault); // Default rendering
    
    // Draw
    CGContextDrawImage(context, self.bounds, image);
    
    // Once everything is written on screen we can release everything
    CGImageRelease(image);
    CGColorSpaceRelease(colorSpace);
    CGDataProviderRelease(provider);
    
    }
    @end
    

【讨论】:

  • 很好的答案。我收到了关于 kCGImageAlphaNoneSkipFirst 错误枚举类型的警告,尽管事情似乎有效。也不应该释放实际像素吗?毕竟这就是大部分记忆的去向。
【解决方案2】:

有很多方法可以做到这一点。一种更直接的方法是使用CGContextDrawImage。在drawRect中:

CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
CGDataProviderRef provider = CGDataProviderCreateWithData(nil, bitmap, bitmap_bytes, nil);
CGImageRef img = CGImageCreate(..., provider, ...);
CGDataProviderRelease(provider);    
CGContextDrawImage(ctx, dstRect, img);
CGImageRelease(img);

CGImageCreate 有一堆我在这里省略的参数,因为正确的值将取决于您的位图格式。 See the CGImage reference for details.

请注意,如果您的位图是静态的,则保留CGImageRef 而不是立即处理它可能是有意义的。您最清楚自己的应用程序是如何工作的,因此您决定这是否有意义。

【讨论】:

  • 不...仍然不行...让我们从头开始...我有一个带有 NSWindow 的新项目,在里面我添加了一个扩展 NSView 的类(myView.m )。我应该在 myView.m 的 drawRect 中添加你的代码。是这样吗?
【解决方案3】:

我通过使用 NSImageView 和 NSBitmapImageRep 从像素值创建图像来解决了这个问题。如何创建像素值有很多选择。在我的例子中,我使用了 32 位像素 (RGBA)。在这段代码中,pixels 是像素值的巨大数组。 display 是 NSImageView 的出口。

    NSBitmapImageRep *myBitmap;
    NSImage *myImage;
    unsigned char *buff[4];
    unsigned char *pixels;
    int width, height, rectSize;
    NSRect myBounds;

    myBounds = [display bounds];
    width = myBounds.size.width;
    height = myBounds.size.height;

    rectSize = width * height;


    memset(buff, 0, sizeof(buff));
    pixels = malloc(rectSize * 4);

    (fill in pixels array)

    buff[0] = pixels;

    myBitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:buff
            pixelsWide:width
            pixelsHigh:height 
            bitsPerSample:8
            samplesPerPixel:4 
            hasAlpha:YES
            isPlanar:NO
            colorSpaceName:NSCalibratedRGBColorSpace
            bitmapFormat:0
            bytesPerRow:(4 * width)
            bitsPerPixel:32];

    myImage = [[NSImage alloc] init];
    [myImage addRepresentation:myBitmap];
    [display setImage: myImage];
    [myImage release];
    [myBitmap release];

    free(pixels);

【讨论】:

  • 感谢您的回答,但是如何从 NSImageView 中创建一个出口?
猜你喜欢
  • 1970-01-01
  • 2012-11-13
  • 2015-10-30
  • 1970-01-01
  • 2022-08-03
  • 2011-09-03
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
相关资源
最近更新 更多