
Import Cbf Byte_offset compressed images

ilavsky
see: http://www.bernstein-plus-sons.com/software/CBF/doc/CBFlib.html#3.3.3
for compression description and lots of other information. This compression is easy enough that it can be done in Igor Pro directly. Load time on 2M image on high level Macbook Pro (2013) is about 0.6 seconds. Tested on Pilatus 2M images (from PSI).
//************************************************************************************************* // This function imports Cbf file with byte_offset compression // see: http://www.bernstein-plus-sons.com/software/CBF/doc/CBFlib.html#3.3.3 // for compression description and lots of other information. // tested on Pilatus 2M images (from PSI) //************************************************************************************************* Function LoadCbfCompresedImage(PathName,FileNameToLoad, WaveNameToCreate) string PathName, FileNameToLoad, WaveNameToCreate //this function loads and uncompresses the Cbf byte_offset compressed file format with: // conversions="x-CBF_BYTE_OFFSET";Content-Transfer-Encoding=BINARY; //X-Binary-Element-Type="signed 32-bit integer";X-Binary-Element-Byte-Order=LITTLE_ENDIAN; //Searches for start of binary data, checks how much data there should be and creates 1D wave output wave (stream) // with uncompressed data in the current data folder. variable SkipBytes variable filevar variable bufSize variable sizeToExpect string testLine //locate start of the binary data open /R/P=$(PathName) filevar as FileNameToLoad testLine="" testLine=PadString (testLine, 16800, 0x20) FBinRead filevar, testLine close filevar SkipBytes=strsearch(testLine, "\014\032\004\325" , 0)+4 //this is string I found in test images if(SkipBytes<5) //string not found... SkipBytes=strsearch(testLine, "\012\026\004\213" , 0)+4 //this is per http://www.bernstein-plus-sons.com/software/CBF/doc/CBFlib.html#3.2.2 what should be there. Go figure... endif if(SkipBytes<5) Abort "Failed to find start of binary section in the Cbf file" //string still not found. This is problem. endif //Figure out now how much data are we expecting // this header is quite messy, let's clean ti up a bit testLine=ReplaceString("\r\n\r\n", testLine, ";") testLine=ReplaceString("\r\n", testLine, ";") testLine=ReplaceString("#", testLine, "") testLine=ReplaceString(";;;;", testLine, ";") testLine=ReplaceString(";;;", testLine, ";") testLine=ReplaceString(";;", testLine, ";") testLine = ReplaceString(":", testLine, "=") sizeToExpect = NumberByKey("X-Binary-Number-of-Elements", testLine, "=", ";") //read the data in binary free wave so we can use them here Open /Z/R/P=$(PathName)/T="????" filevar as FileNameToLoad if (V_flag) close filevar Abort "Cannot open file, something is wrong here" // could not open file endif FSetPos fileVar, SkipBytes //start of the image FStatus fileVar bufSize = V_logEOF-V_filePos //this is how mcuh data we have in the image starting at the binary data start make/B/O/N=(bufSize)/Free BufWv //signed 1 byte wave for the data make/O/N=(sizeToExpect)/Free ResultImage //here go teh converted singed integers. Note, they can be 8, 16, or 32 bits. 64bits not supported here. FBinRead/B=1/F=1 fileVar, BufWv //read 1 Byte each into singed integers wave close filevar //and not decompress the data here variable i, j, PixelValue, ReadValue j=0 // j is index of the signed 1 byte wave (stream of data in) PixelValue = 0 //value in current pixel in image. For(i=0;i<(sizeToExpect);i+=1) //i is index for output wave if(j>bufSize-1) break //just in case, we run our of j. Should never happen endif ReadValue = BufWv[j] //read 1 Byte integer if(ReadValue>-128) //this is useable value if +/- 127 PixelValue += ReadValue //add to prior pixel value ResultImage[i] = PixelValue //store in output stream j+=1 // move to another j point elseif(ReadValue==-128) // This is indicator that the difference did not fit in 1Byte, read 2 bytes and use those. j+=1 // move to another point to start reading the 2 bytes ReadValue = Conv2Bytes(BufWv[j],BufWv[j+1]) //read and convert 2 Bytes in integer if(ReadValue>-32768) // This is useable value, use these two bytes PixelValue += ReadValue //add to prior pixel value ResultImage[i] = PixelValue //store in output stream j+=2 //move to another j point elseif(ReadValue==-32768) // This is indicator that the difference did not fit in 2Bytes, read 4 bytes and use those. j+=2 //move to another point to start reading the 4 bytes ReadValue = Conv4Bytes(BufWv[j],BufWv[j+1], BufWv[j+2], BufWv[j+3]) //read and convert next 4 Bytes in integer if(abs(ReadValue)<2147483648) //this is correct value for 32 bits PixelValue += ReadValue //add to prior pixel value ResultImage[i] = PixelValue //store in output stream j+=4 //move to another j point else //abort, do not support 64 byte integers (no such detector exists... abort "64 bits data are not supported" endif else print "error" endif else print "error" endif endfor Duplicate/O ResultImage, $(WaveNameToCreate) //create wave user requested. Note, this is 1D wave and needs to be redimensioned to 2D wave (image). Could be done here... end //************************************************************************************************* //************************************************************************************************* //************************************************************************************************* static Function Conv2Bytes(B1,B2) variable B1, B2 //takes two signed integer bytes, and converts them to 16 bit signed integer, little-endian, two's complement signed interpretation //assume B1 is first byte for little-endian should be unsigned integer as it is the smaller part of the data //assume B2 contains the larger values and sign variable unsB1=(B1>=0) ? B1 : (256 + B1) //this should convert two's complement signed interpretation to Usigned interpretation return unsB1 + 256*B2 end //************************************************************************************************* //************************************************************************************************* static Function Conv4Bytes(B1,B2, B3, B4) variable B1, B2, B3, B4 //takes four signed integer bytes, and converts them to 32 bit signed integer, little-endian, two's complement signed interpretation //assume B1, B2, B3 are first bytes for little-endian should be unsigned integer as it is the smaller part of the data //assume B4 contains the larger values and sign variable unsB1=(B1>=0) ? B1 : (256 + B1) //this should convert two's complement signed interpretation to Usigned interpretation variable unsB2=(B2>=0) ? B2 : (256 + B2) //this should convert two's complement signed interpretation to Usigned interpretation variable unsB3=(B3>=0) ? B3 : (256 + B3) //this should convert two's complement signed interpretation to Usigned interpretation return unsB1 + 256*unsB2 + 256*256*unsB3 + 256*256*256*B4 end //************************************************************************************************* //*************************************************************************************************

Forum

Support

Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More