32位大端浮点数据转换为CGImage。

3
我正在尝试编写一个读取FITS图像的应用程序。FITS代表灵活的图像传输格式,主要用于存储与天体物理学相关的科学数据,其次是由大多数使用CCD相机拍摄天空照片的业余天文学家使用。因此,FITS文件包含图像,但它们也可能包含表格和其他类型的数据。由于我对Objective-C和Cocoa编程还很新(我一年前开始这个项目,但由于太忙了,我几乎一年都没有碰它!),所以我开始尝试创建一个库,使我能够将文件的图像内容转换为NSImageRep。FITS图像二进制数据可以是8位/像素、16位/像素、32位/像素无符号整数或32位/像素、64位/像素浮点数,全部采用大端字节序。
我已经成功地实现了16位/像素、32位/像素无符号整数的灰度FITS图像的图像表示,但当我尝试寻找32位/像素浮点数时(RGB 32位/像素浮点数同样存在问题),我得到了非常奇怪的行为。到目前为止,我还没有针对8位/像素整数数据和基于16位/像素和32位/像素整数数据的RGB图像进行测试,因为我还没有在网上找到示例文件。
下面是我创建灰度图像的代码:
-(void) ConstructImgGreyScale
{
CGBitmapInfo     bitmapInfo;
int bytesPerRow;

switch ([self BITPIX])   // BITPIX : Number bits/pixel. Information extracted from the FITS header
{
    case 8:
        bytesPerRow=sizeof(int8_t);
        bitmapInfo = kCGImageAlphaNone ;
        break;
    case 16:
        bytesPerRow=sizeof(int16_t);
        bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrder16Big;
        break;
    case 32:
        bytesPerRow=sizeof(int32_t);
        bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrder32Big;
        break;
    case 64:
        bytesPerRow=sizeof(int64_t);
        bitmapInfo = kCGImageAlphaNone;
        break;
    case -32:
        bytesPerRow=sizeof(Float32);
        bitmapInfo = kCGImageAlphaNone | kCGBitmapByteOrder32Big  | kCGBitmapFloatComponents;
    case -64:
        bytesPerRow=sizeof(Float64);
        bitmapInfo = kCGImageAlphaNone  | kCGBitmapFloatComponents;
        break;
    default:
        NSLog(@"Unknown pixel bit size");
        return;
}
[self setBitsPerSample:abs([self BITPIX])];

[self setColorSpaceName:NSCalibratedWhiteColorSpace];

[self setPixelsWide:[self NAXESofAxis:0]]; // <- Size of the X axis. Extracted from FITS header
[self setPixelsHigh:[self NAXESofAxis:1]]; // <- Size of the Y axis. Extracted from FITS header

[self setSize:  NSMakeSize( 2*[self pixelsWide], 2*[self pixelsHigh])];

[self setAlpha: NO];
[self setOpaque:NO];

CGDataProviderRef provider=CGDataProviderCreateWithCFData ((CFDataRef) Img);

CGFloat Scale[2]={0,28};
image = CGImageCreate ([self pixelsWide],
                       [self pixelsHigh],
                       [self bitsPerSample],
                       [self bitsPerSample],
                       [self pixelsWide]*bytesPerRow,
                       [[NSColorSpace deviceGrayColorSpace] CGColorSpace],
                       bitmapInfo,
                       provider,
                       NULL,
                       NO,
                       kCGRenderingIntentDefault
                       );

CGDataProviderRelease(provider);
return;
}  

以下是32位/像素浮点数据的结果快照:NASA HST图片

图像似乎向左移动,但更令人恼火的是,我在同一帧中得到了同一图像的两个表示(帧的上部和下部)。

对于其他文件,行为更加奇怪: Star Field 1。(关于其他链接,请查看评论,作为新用户,我不能在此文本中使用超过两个链接。我也无法直接放置图像。)

所有三个星场图像都是相同fits文件内容的表示。我在框架的底部获得了正确的图像表示(星星太饱和了,但我还没有尝试编码)。但是,在上半部分,每次打开相同的文件时,我都会得到图像的不同表示。看起来每次打开此文件时,它都不会采用相同的字节序列来生成图像表示(至少对于上部分是这样)。

此外,我不知道底部重复的图像是否包含了一半的数据,而上面则是另外一半,或者它只是数据的副本。

当我将数据内容转换为基本格式(人类可读数字)时,数字与像素应该在正确的位置兼容。这让我认为问题不是来自数据而是来自CGImage解释数据的方式,即我在向CGImageCreate函数传递参数时出错了。

对于RGB fits图像数据,最终在我的帧中获得了18个图像。每个R、G和B图像都有6个副本。所有图像都是灰度的。请注意,在RGB图像的情况下,我的代码不同。

我做错了什么?


两个其它图片的正确链接为:星空2星空3 - William GILLARD
1个回答

1

好的,我终于找到了解决我的一个问题的方法,这个问题涉及到图像的重复。这是一个非常愚蠢的错误,我并不为自己没有早点发现它而感到骄傲。

在代码中,我忘记了case -32中的break。但问题仍然存在于图片的移位上。当我打开32位整数图像时,我看不到移位,但在32位浮点数据上出现了。

有人知道这个移位可能来自我的代码的哪里吗?是由于我构建图像的方式吗?还是由于我绘制图像的方式造成的呢?

下面是我用来绘制图像的代码片段。由于图像最初是倒置的,所以我对坐标进行了一些小的更改。

- (bool)draw {
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
if (!context || !image) {
    return NO;
}
NSSize size = [self size];

CGContextTranslateCTM(context, 0, size.height);
CGContextScaleCTM(context, 1, -1);

CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), image);
return YES;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接