Domanda

Sono nuovo programmatore in Obj-C e cacao . Im un tentativo di scrivere un quadro che verrà utilizzata per leggere un file binari ( Flexible Image Transport Sistema o FITS i file binari, di solito utilizzati dagli astronomi). I dati binari, che mi interessa di estratto, possono avere vari formati e ottengo le sue proprietà leggendo l'intestazione delle FITS file.

Fino ad ora, riesco a creare una classe per memorizzare il contenuto della FITS file e di isolare l'intestazione in un oggetto NSString ei dati binari in un oggetto NSData. Riesco anche il metodo di scrittura che mi permetta di estrarre i valori chiave del colpo di testa che sono molto preziosi per interpretare i dati binari.

ora sto cercando di convertire l'oggetto NSData in una matrice primitiva (array di double, int, short ...). Ma, qui, mi si blocca e gradirebbe qualsiasi aiuto.

In base alla documentazione ho circa FITS di file, ho 5 possibilità per interpretare i dati binari a seconda del valore della chiave 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

I già scrivere la pace di codice, mostrato di seguito, per cercare di convertire la NSData in una matrice primitiva.

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

}

Tuttavia, il valore stampo nel loop sono molto diversi dai valori attesi (rispetto utilizzando il software FITS ufficiali). Pertanto, ritengo che il Obj-C double non utilizza il IEEE-754 di convenzione così come la Obj-C int non sono < em> complemento a due . Sono veramente non hanno familiarità con questi due congressi ( IEEE e complemento a due ) e vorrei sapere come posso fare questa conversione con Obj-C .

in anticipo molte grazie per qualsiasi aiuto o informazioni.

È stato utile?

Soluzione 4

Grazie mille. Il problema è stato veramente legato alla endian e non ero a conoscenza di questo. Onestamente, non sono mai stato veramente consapevoli del tipo di endian perché, fino ad ora, non sono mai stato confrontato al problema.

A proposito, ho trovato la soluzione, ringrazia tutti per le sue osservazioni. Perché può essere utile per altro sviluppatore, vi propongo una pace di codice che permette di convertire i NSData al primitivo, che cosa mai il tipo di endian. Questa è la soluzione che trovo (lavoro con la Fondazione e il quadro di cacao su OS X 10.5 e 10.6) e non può essere la migliore, quindi, l'uso a proprio rischio;)

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

}

Spero che questo può essere utile.

Altri suggerimenti

Objective-C utilizza IEEE-754 carri allegorici (come praticamente ogni sistema fa), così come interi in complemento a due. Credo che la vostra congettura è falsa. Forse si stanno avendo problemi di ordine?

Praticamente tutti i sistemi utilizzano complemento a due e IEEE 754, semplicemente perché è raramente vale la pena di venire con una nuova rappresentazione di queste cose - basta non fare che se non si dispone di circostanze che lo richiedono molto specializzata <. / p>

I suggerirebbe di visualizzare il numero in formato esadecimale - è molto più probabile che sia un problema con endianness rispetto ai tipi di dati di un formato speciale, e la stampa dei valori in esadecimale rende più facile capire se questo è il problema .

Sei sicuro che

double (*array)[NElements];

è quello che vuoi? Questo semplice programma:

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

si blocca miseramente sulla mia macchina.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top