0

私はObj-Ccocoaの新しいプログラマーです。バイナリ ファイル (通常、天文学者が使用するFlexible Image Transport SystemまたはFITSバイナリ ファイル)を読み取るために使用されるフレームワークを作成しようとしています。抽出したいバイナリ データにはさまざまな形式があり、FITSファイルのヘッダーを読み取ってそのプロパティを取得します。

これまでのところ、FITSファイルのコンテンツを格納するクラスを作成し、ヘッダーをNSStringオブジェクトに分離し、バイナリ データをオブジェクトに分離することができましたNSData。また、バイナリ データを解釈するのに非常に価値のあるキー値をヘッダーから抽出できるメソッドを作成することもできました。

私は今、NSDataオブジェクトをプリミティブ配列 (、、double...の配列)intに変換しようとしています。shortしかし、ここで行き詰まり、助けていただければ幸いです。

FITSファイルに関するドキュメントによると、BITPIXキーの値に応じてバイナリ データを解釈する 5 つの可能性があります。

BITPIX value | Data represented
  8          | Char or unsigned binary int
 16          | 16-bit two's complement binary integer
 32          | 32-bit two's complement binary integer
 64          | 64-bit two's complement binary integer
-32          | IEEE single precision floating-point
-64          | IEEE double precision floating-point

NSDataをプリミティブ配列に変換するために、以下に示す平和なコードを既に作成しています。

// self reefer to my FITS class which contain a NSString object  
// with the content of the header and a NSData object with the binary data. 

-(void*) GetArray
{
switch (BITPIX)
{
    case 8:
        return [self GetArrayOfUInt];
        break;
    case 16:
        return [self GetArrayOfInt];
        break;
    case 32:
        return [self GetArrayOfLongInt];
        break;
    case 64:
        return [self GetArrayOfLongLong];
        break;
    case -32:
        return [self GetArrayOfFloat];
        break;
    case -64:
        return [self GetArrayOfDouble];
        break;
    default:
        return NULL;
}
}

// then I show you the method to convert the NSData into a primitive array.
// I restrict my example to the case of 'double'. Code is similar for other methods
// just change double by 'unsigned int' (BITPIX 8), 'short' (BITPIX 16)
// 'int' (BITPIX 32) 'long lon' (BITPIX 64), 'float' (BITPIX -32). 

-(double*) GetArrayOfDouble
{
int Nelements=[self NPIXEL]; // Metod to extract, from the header 
                             // the number of element into the array
NSLog(@"TOTAL NUMBER OF ELEMENTS [%i]\n",Nelements);

//CREATE THE ARRAY
double (*array)[Nelements];

// Get the total number of bits in the binary data
int Nbit = abs(BITPIX)*GCOUNT*(PCOUNT + Nelements); // GCOUNT and PCOUNT are defined
                                                        // into the header
NSLog(@"TOTAL NUMBER OF BIT [%i]\n",Nbit);
int i=0;

    //FILL THE ARRAY
double Value;

for(int bit=0; bit < Nbit; bit+=sizeof(double))
{
    [Img getBytes:&Value range:NSMakeRange(bit,sizeof(double))];
    NSLog(@"[%i]:(%u)%.8G\n",i,bit,Value);
        (*array)[i]=Value;
    i++;

}

return (*array);

}

ただし、ループで出力する値は、期待される値とは大きく異なります (公式の FITS ソフトウェアを使用した場合と比較して)。したがって、 Obj-Cは IEEE-754規則をdouble使用しておらず、 Obj-C2 の補数ではないと思います。私はこの 2 つの規則 ( IEEEtwos-complement ) に精通していないため、 Obj-Cでこの変換を行う方法を知りたいと考えています。 int

ヘルプや情報をお寄せいただきありがとうございます。

4

4 に答える 4

3

Objective-C は、2 の補数の整数だけでなく、IEEE-754 浮動小数点数 (実際にはすべてのシステムがそうであるように) も使用します。あなたの推測は間違っていると思います。たぶん、エンディアンに問題がありますか?

于 2010-06-11T21:09:58.613 に答える
1

事実上すべてのシステムが 2 の補数と IEEE 754 を使用しています。これは単に、これらのものの新しい表現を考え出す価値はめったにないためです。

数値を 16 進数で表示することをお勧めします。特殊な形式のデータ型よりもエンディアンの問題である可能性が高く、値を 16 進数で出力すると、それが問題であるかどうかを簡単に判断できます。

于 2010-06-11T21:11:20.750 に答える
0

どうもありがとう。問題は実際にはエンディアンに関連していて、私はこれに気づいていませんでした。正直なところ、私はエンディアン タイプについてあまり意識したことがありませんでした。これまで、この問題に直面したことがなかったからです。

ところで、解決策を見つけました。ご指摘ありがとうございます。他の開発者にも役立つ可能性があるため、エンディアンの種類に関係なく、NSData をプリミティブに変換できる平和なコードを提案します。これは私が見つけた解決策です (Os X 10.5 および 10.6 で Foundation および cocoa フレームワークを使用します)。これは最善ではない可能性があるため、自己責任で使用してください ;)

// 1- CREATE AN ARRAY OF SIZE Nelements;
int Nelements = XXX;
double (*array)[Nelements];

// 2- Create the swapped double -> a double with the wrong bit order
NSSwappedDouble swappedValue;

// 3- The correct value
double Value;

// 4- Fill your array
int i=0, bit=0;
int BitStep=sizeof(double);

while(i<Nelements)
{
    [MyNSData getBytes:&swappedValue range:NSMakeRange(bit,step)];
    Value = NSSwapBigDoubleToHost(swappedValue);   // or NSSwapLittleDoubleToHost depending of your endian type.
    (*array)[i]=Value;
    i++; bit+=BitStep;

}

これが役立つことを願っています。

于 2010-06-12T21:01:23.347 に答える
0

よろしいですか

double (*array)[NElements];

あなたが欲しいものですか?この簡単なプログラム:

int main( int argc, char** argv)
{
    double (*array)[5];
    (*array)[4] = 0;
    return 0;
}

私のマシンで惨めにクラッシュします。

于 2010-06-12T17:31:17.080 に答える