Question

Je suis nouveau programmeur Obj-C et cacao . Im un essaie d'écrire un cadre qui sera utilisé pour lire un fichier binaire ( Flexible Image Transport System ou FITS les fichiers binaires, généralement utilisés par les astronomes). Les données binaires, que je suis intéressé à extraire, peuvent avoir différents formats et je reçois ses propriétés en lisant l'en-tête des FITS fichier.

Jusqu'à présent, je parviens à créer une classe pour stocker le contenu du fichier FITS et d'isoler l'en-tête dans un objet NSString et les données binaires dans un objet NSData. Je gère également la méthode d'écriture qui me permettent d'extraire les valeurs clés de l'en-tête qui sont très précieux pour interpréter les données binaires.

J'essaie maintenant de convertir l'objet NSData dans un tableau primitif (tableau de double, int, short ...). Mais, ici, je suis bloqué et apprécierait toute aide.

D'après la documentation que j'ai sur les FITS fichier, j'ai 5 possibilités d'interpréter les données binaires en fonction de la valeur de la clé de BITPIX:

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

Je l'ai déjà écrit la paix de code, illustré ci-dessous, pour essayer de convertir le NSData dans un tableau primitif.

// 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);

}

Cependant, la valeur imprimer dans la boucle sont très différentes des valeurs attendues (par rapport à l'aide des logiciels FITS officiels). Par conséquent, je pense que le Obj-C double ne pas utiliser le IEEE-754 convention ainsi que la Obj-C int ne sont pas < em> complément à deux . Je ne suis vraiment pas au courant de cette convention deux ( IEEE et complément à deux ) et je voudrais savoir comment je peux faire cette conversion avec Obj-C .

En avance merci beaucoup pour toute aide ou information.

Était-ce utile?

La solution 4

Merci beaucoup. Le problème était vraiment lié à la endian et je n'étais pas au courant de cela. Honnêtement, je n'ai jamais vraiment au courant du type endian parce que, jusqu'à présent, on ne m'a jamais confronté au problème.

Par ailleurs, je trouve la solution, merci à tous pour vos remarques. Parce qu'il peut être utile pour les autres développeurs, je proposerai une paix de code qui permet de convertir NSData Primitive, ce que jamais le type endian. Ceci est la solution que je trouve (travail avec la Fondation et le cadre de cacao sur Os X 10.5 et 10.6) et il ne peut pas être le meilleur, donc, utilisez à vos propres risques et périls;)

// 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;

}

Espérons que cela peut être utile.

Autres conseils

utilise Objective-C flotteurs IEEE-754 (comme pratiquement tous les systèmes ne) ainsi que des entiers en complément à deux. Je pense que votre conjecture est fausse. Peut-être que vous avez des problèmes de endianness?

Pratiquement tous les systèmes utilisent complément à deux et IEEE 754, tout simplement parce qu'il est rarement la peine de venir avec une nouvelle représentation de ces choses - vous ne faites pas seulement que si vous avez des circonstances très spécialisées qui en ont besoin <. / p>

Je vous suggère d'afficher le nombre en hexadécimal - il est beaucoup plus susceptible d'être un problème avec boutisme que les types de données d'un format spécial, et l'impression des valeurs en hexadécimal, il est plus facile de dire si tel est le problème .

Êtes-vous sûr que

double (*array)[NElements];

est ce que vous voulez? Ce programme simple:

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

Crashes lamentablement sur ma machine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top