Pregunta

Soy nuevo programador en Obj-C y cacao . Im a tratar de escribir un marco que se utiliza para leer un archivos binarios ( Sistema de Transporte Flexible imagen o FITS archivos binarios, por lo general utilizados por los astrónomos). Los datos binarios, que yo estoy interesado en el extracto, pueden tener diversos formatos y obtener sus propiedades mediante la lectura de la cabecera de los FITS archivo.

Hasta ahora, me las arreglo para crear una clase para almacenar el contenido de la FITS archivo y para aislar la cabecera en un objeto NSString y los datos binarios en un objeto NSData. También me encargo de método de escritura que me permiten extraer los valores clave de la cabecera que son muy valiosas para interpretar los datos binarios.

Ahora estoy tratando de convertir el objeto NSData en una matriz primitiva (matriz de double, int, short ...). Pero, aquí, se queda bloqueado y agradecería cualquier ayuda.

De acuerdo con la documentación que tengo sobre los FITS archivo, tengo 5 posibilidades para interpretar los datos binarios en función del valor de la clave 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

Ya escribir la paz de código, que se muestra abajo, para tratar de convertir el NSData en una matriz 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);

}

Sin embargo, el valor imprimo en el bucle son muy diferentes de los valores esperados (en comparación con el uso de software FITS oficiales). Por lo tanto, creo que el Obj-C double no utiliza el IEEE-754 convenciones, así como el Obj-C int no son < em> de complemento a dos . Estoy muy familiarizado con estos dos convenciones ( IEEE y de complemento a dos ) y le gustaría saber cómo puedo hacer esta conversión con Obj-C .

De antemano muchas gracias por cualquier ayuda o información.

¿Fue útil?

Solución 4

Muchas gracias. El problema fue realmente relacionado con la endian y yo no era consciente de ello. Honestamente, nunca era realmente consciente del tipo endian, ya que, hasta ahora, nunca vi enfrentado al problema.

Por cierto, me parece la solución, gracias a todos por sus comentarios. Debido a que puede ser útil para otro desarrollador, propondré una paz de código que permite convertir NSData a lo que cada vez el tipo primitivo, endian. Esta es la solución que encuentro (trabajo con la Fundación y el marco de cacao en OS X 10.5 y 10.6) y puede que no sea lo mejor, así, su uso bajo su propio riesgo;)

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

}

Espero que esto puede ser útil.

Otros consejos

Objetivo-C utiliza IEEE-754 flotadores (como prácticamente todos los sistemas lo hace), así como números enteros en complemento a dos. Creo que su conjetura es falsa. Tal vez usted está teniendo problemas endianness?

Prácticamente todos los sistemas de uso de complemento a dos e IEEE 754, simplemente porque es rara vez vale la pena para llegar a una nueva representación de estas cosas - sólo no lo hace a menos que tenga las circunstancias que así lo requieran muy especializado <. / p>

Yo sugeriría que aparezca el número en hexadecimal - es mucho más probable que sea un problema con el orden de bits que ser los tipos de datos de un formato especial, y la impresión de los valores en hexadecimal hace que sea más fácil de saber si ese es el problema .

¿Está seguro de que

double (*array)[NElements];

es lo que quiere? Este sencillo programa:

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

se bloquea miserablemente en mi máquina.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top