Convert NSData to primitive variable with ieee-754 or twos-complement?

I am a new programmer in Obj-C and cocoa . I am trying to write a framework that will be used to read binary files (Flexible Image Transport System or FITS binaries commonly used by astronomers). The binary data that interests me can have various formats, and I get its properties by reading the header of the FITS file.

So far, I have managed to create a class to hold the contents of the FITS file and extract the header into the NSString object and the binary data into the NSData object. I also manage to write a method that allows me to extract the key values ​​from the header, which are very valuable for interpreting binary data.

Now I am trying to convert an NSData object to a primitive array (array double , int , short ...). But here I am stuck and would appreciate any help.

According to the documentation available with the FITS file, I have 5 options to interpret binary data depending on the value of the BITPIX key:

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

I am already writing the world of code shown below to try to convert NSData to a primitive array.

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

However, the value that I print in the loop is very different from the expected values ​​(compared using official FITS software). Therefore, I believe that Obj-C double does not use the IEEE-754 convention, and Obj-C int are not two additions. I am really not familiar with these two conventions ( IEEE and two additions) and would like to know how I can do this conversion using Obj-C .

Thanks in advance for any help or information.

0
source share
4 answers

Many thanks. The problem was really connected with the end, and I did not know about it. Honestly, I never knew about the terminal type, because so far I have never encountered a problem.

By the way, I find a solution, thank you all for your comments. Since it may be useful for another developer, I propose a world of code that allows you to convert NSData to a primitive, whatever the endian type is. This is the solution that I find (working with Foundation and cocoa framework on Os X 10.5 and 10.6), and it may not be the best, so use it at your own risk;)

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

Hope this can be helpful.

0
source

Objective-C uses IEEE-754 floats (like almost every system), as well as integers with two additions. I think your hypothesis is wrong. Perhaps you have problems with the content?

+3
source

Almost all systems use two add-ons and IEEE 754, simply because it is rarely worthwhile to come up with a completely new idea of ​​these things - you simply do not do this if you do not have special specialized circumstances requiring this.

I would suggest that you display the number in hexadecimal - it is much more likely to have a problem with the content than data types related to the special format, and printing the values ​​in hexadecimal makes it easier to determine if this is a problem.

+1
source

You are sure that

 double (*array)[NElements]; 

- Is this what you want? This simple program:

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

Crash on my car.

0
source

Source: https://habr.com/ru/post/1394470/


All Articles