Import Cbf Byte_offset compressed images

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. 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 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More