gpt4 book ai didi

cocoa - 来自一维像素阵列的 NSImage?

转载 作者:行者123 更新时间:2023-12-03 16:29:43 27 4
gpt4 key购买 nike

我的程序中有一个大型一维动态数组,它表示磁盘上的 FITS 图像,即它保存图像的所有像素值。数组的类型是double。目前,我只关心单色图像。

由于 Cocoa 不直接支持 FITS 格式,因此我使用 CFITSIO 库读取图像。这是可行的 - 我可以根据需要操作数组并使用库将结果保存到磁盘。

但是,我现在想要显示图像。我认为这是 NSImage 或 NSView 可以做的事情。但类引用似乎没有列出可以采用 C 数组并最终返回 NSImage 对象的方法。我发现的最接近的是-initWithData:(NSData*)。但我不能 100% 确定这是否是我所需要的。

我是不是找错树了?任何指向可以处理此问题的类或方法的指针都将是

编辑:

这是更新后的代码。请注意,我将每个像素设置为 0xFFFF。这只会产生灰色图像。这当然只是一个测试。加载实际的 FITS 文件时,我将 0xFFFF 替换为 imageArray[i * width + j] 。这在 8 位中完美运行(当然,我将每个像素值除以 256 以用 8 位表示)。

 NSBitmapImageRep *greyRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
pixelsWide:width
pixelsHigh:height
bitsPerSample:16
samplesPerPixel:1
hasAlpha:NO
isPlanar:NO
colorSpaceName:NSCalibratedWhiteColorSpace
bytesPerRow:0
bitsPerPixel:16];

NSInteger rowBytes = [greyRep bytesPerRow];
unsigned short*pix = (unsigned short*)[greyRep bitmapData];
NSLog(@"Row Bytes: %d",rowBytes);

if(temp.bitPix == 16) // 16 bit image
{
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
pix[i * rowBytes + j] = 0xFFFF;
}
}
}

我也尝试过直接使用Quartz2D。即使是 16 位,这也确实会产生正确的图像。但奇怪的是,数据数组将 0xFF 作为白色,而不是 0xFFFF。所以我仍然必须将所有内容除以 0xFF - 在此过程中丢失数据。 Quartz2D代码:

    short* grey = (short*)malloc(width*height*sizeof(short));
for(int i=0;i<width*height; i++)
{
grey[i] = imageArray[i];
}

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef bitmapContext = CGBitmapContextCreate(grey, width, height, 16, width*2, colorSpace, kCGImageAlphaNone);
CFRelease(colorSpace);

CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);

NSImage *greyImage = [[NSImage alloc] initWithCGImage:cgImage size:NSMakeSize(width, height)];

有什么建议吗?

最佳答案

initWithData 仅适用于系统已知的图像类型。对于未知类型和原始像素数据,您需要自己构建图像表示。您可以按照 Kirby 链接到的答案中的建议通过 Core Graphics 执行此操作。或者,您可以通过创建并添加 NSBitmapImageRep 来使用 NSImage

确切的细节取决于像素数据的格式,但以下是灰度图像的处理示例,其中源数据(samples 数组)在范围内表示为 double [0,1]:

/* generate a greyscale image representation */
NSBitmapImageRep *greyRep =
[[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: nil // allocate the pixel buffer for us
pixelsWide: xDim
pixelsHigh: yDim
bitsPerSample: 8
samplesPerPixel: 1
hasAlpha: NO
isPlanar: NO
colorSpaceName: NSCalibratedWhiteColorSpace // 0 = black, 1 = white in this color space
bytesPerRow: 0 // passing 0 means "you figure it out"
bitsPerPixel: 8]; // this must agree with bitsPerSample and samplesPerPixel

NSInteger rowBytes = [greyRep bytesPerRow];

unsigned char* pix = [greyRep bitmapData];
for ( i = 0; i < yDim; ++i )
{
for ( j = 0; j < xDim; ++j )
{
pix[i * rowBytes + j] = (unsigned char)(255 * (samples[i * xDim + j]));
}
}

NSImage* greyscale = [[NSImage alloc] initWithSize:NSMakeSize(xDim,yDim)];
[greyscale addRepresentation:greyRep];
[greyRep release];
<小时/>

编辑(回应评论)

我不确定是否支持 16 位样本,但您似乎已经确认它们是支持的。

您所看到的源于仍然将像素视为 unsigned char,即 8 位。因此,您只需设置每行的一半,并且一次一个字节地将每个像素设置为两个字节值 0xFF00 - 不完全是真正的白色,但非常接近。图像的另一半没有被触摸,但会被初始化为 0,因此它保持黑色。

您需要在 16 位中工作,首先转换从代表返回的值:

unsigned short * pix = (unsigned short*) [greyRep bitmapData];

然后将 16 位值分配给像素:

if ( j % 2 )
{
pix[i * rowBytes + j] = 0xFFFF;
}
else
{
pix[i * rowBytes + j] = 0;
}

从头开始,rowBytes 以字节为单位,因此我们需要坚持使用 unsigned char 来表示 pix 并在分配时进行强制转换,这有点更丑:

if ( j % 2 )
{
*((unsigned short*) (pix + i * rowBytes + j * 2)) = 0xFFFF;
}
else
{
*((unsigned short*) (pix + i * rowBytes + j * 2)) = 0;
}

(我已经改变了子句的顺序,因为 == 0 似乎是多余的。实际上,对于这样的事情,使用 ?: 语法会更简洁,但 C 语言已经够多了。)

关于cocoa - 来自一维像素阵列的 NSImage?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5458770/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com