C++ reading 16bit binary data from raw img and store them in vector

453 views Asked by At

These days I am struggling at malloc memory. I try to read 16-bit binary data from raw img and store them in buffer or vector. The total size of these binary data is about 15M. For this kind of size, which way is better between buf or vector? Here is my code below:

#include <imebra/imebra.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>
#include<iterator>
#include <algorithm>

#define img_height 2816
#define img_width  2816


//#define img_size img_height*img_width*img_bit //15.1MB

using namespace std;

//MONOCHROME1: indicates that the greyscale ranges from bright to dark with ascending pixel values
//MONOCHROME2: indicates that the greyscale ranges from dark to bright with ascending pixel values



/*
create an Image object
fill the image object with raw dat
create a DICOM dataset
add the image to the DICOM dataset
fill all the necessary DICOM tags (e.g. sop class, instance, patient name, etc)
save the DICOM dataset
*/
int main()
{
    ifstream mydata("/home/lixingyu/123.raw", ios::binary);
    if(!mydata.is_open())
    {
        cout<<"open file failed"<<endl;
        exit(1);
    }
    //get img size
    mydata.seekg (0, mydata.end);
    int img_size = mydata.tellg();
    mydata.seekg (0, mydata.beg);
    cout<<"img_size : "<<img_size<<endl;


/* way 1
    char *buf= new (nothrow) char[img_size];
    uint16_t *rawdata = new (nothrow) uint16_t[img_size];

    if(buf == NULL)
    {
        cout<<"memory allocation failed"<<endl;
        delete [] buf;
    }
    if(rawdata == NULL)
    {
        cout<<"memory allocation failed"<<endl;
        delete [] rawdata;
    }

    mydata.read(rawdata,img_size);
     memcpy(rawdata,buf,img_size); //forced type changed from char to uint16_t
     cout<<"rawdata[first] = "<<rawdata[0]<<endl;
     cout<<"rawdata[last]= "<<rawdata[img_size/2-1]<<endl;

*/

//way 2
    vector<char> raw_8;
    vector<uint16_t> raw_16;
    char value;
    while(! mydata.eof())
    {
        mydata>>value;
        raw_8.push_back(value);
    }
    //raw_8->pop_back();
    copy(raw_8.begin(),raw_8.end(),back_inserter(raw_16));
    copy(raw_16.begin(),raw_16.end(),ostream_iterator<uint16_t>(cout,"\n"));

/*

    imebra::MutableImage image=imebra::MutableImage(img_height,img_width,imebra::bitDepth_t::depthU16,"MONOCHROME2",15);

    // 1. Fill the image with data
    // We use a writing data handler to write into the image.
    // The data is committed into the image only when the writing   
    // data handler golses out of scope.
    imebra::WritingDataHandlerNumeric writeIntoImage(image.getWritingDataHandler());    

    //writeIntoImage.assign(buf,sizeof(buf));   
    for (size_t y(0);y!=img_width;++y)
    {
        for (size_t x(0); x!= img_height; ++x)
        {
            writeIntoImage.setUnsignedLong(y*img_height+x,rawdata[y*img_height+x]);
        }
    }

    // specify the tansfer syntax and the charset
    imebra::charsetsList_t charsets;
    charsets.push_back("ISO 2022 IR 6");    

    //Explicit VR little endian
    imebra::MutableDataSet dataSet("1.2.840.10008.1.2.1",charsets);
  /************ code stop here *************/
    // add the image to the dataSet
    dataSet.setImage(0,image,imebra::imageQuality_t::veryHigh);

    // set the patient name dataSet.setUnicodePatientName(imebra::TagId(imebra::tagId_t::PatientName_0010_0010),imebra::UnicodePatientName(L"fjx",L"",L""));

    // save to a file
    imebra::CodecFactory::save(dataSet,"GH1.dcm",imebra::codecType_t::dicom);

    mydata.close();
    delete [] buf;
    delete [] rawdata;    
}

// sudo g++ -I/home/lixingyu/imebra_5_0_1_1/library/include -o test raw2dcm.cpp -std=c++0x -l imebra -L/home/lixingyu/artifacets
// export LD_LIBRARY_PATH=/home/lixingyu/artifacets:$LD_LIBRARY_PATH  

The two comments at the buttom of the code are compiling cmd. Now the suitation is that whatever I use way 1 or 2, the code will stop there (see code above), and it said segmetation fault(core dump).

here below are gdb debug:

(gdb) bt full
#0  0x00007faecd9854bd in imebra::implementation::codecs::dicomNativeImageCodec::writeInterleavedNotSubsampled<unsigned short> (pImageSamples=0x0, 
    allocatedBits=16, pLittleEndianTagData=0x36a1d11 "", numPixels=7929856, 
    numChannels=1)
    at /home/lixingyu/imebra_5_1_0_0/library/implementation/dicomNativeImageCodecImpl.h:125
#1  0x00007faecd983887 in imebra::implementation::codecs::dicomNativeImageCodec::writeInterleavedNotSubsampled (pImageSamples=0x0, allocatedBits=16, 
    samplesDepth=imebra::bitDepth_t::depthU16, 
    pLittleEndianTagData=0x36a1d10 "", numPixels=7929856, numChannels=1)
    at /home/lixingyu/imebra_5_1_0_0/library/implementation/dicomNativeImageCodecImpl.cpp:396
#2  0x00007faecd9828b4 in imebra::implementation::codecs::dicomNativeImageCodec::setImage (this=0xf3b080, pDestStream=
    std::shared_ptr (count 2, weak 0) 0x36a0780, 
    pImage=std::shared_ptr (count 3, weak 0) 0xf3dff0, allocatedBits=16, 
    bSubSampledX=false, bSubSampledY=false, bInterleaved=false)
    at /home/lixingyu/imebra_5_1_0_0/library/implementation/dicomNativeImageCodecImpl.cpp:311
#3  0x00007faecd81a34e in imebra::implementation::dataSet::setImage (
    this=0x1e5f2a0, frameNumber=0, 
    pImage=std::shared_ptr (count 3, weak 0) 0xf3dff0, 
    quality=imebra::imageQuality_t::veryHigh)

By the way, if I use vector to store 16-bit value which copied from 8-bit vector. Should I do data type transform? I just used copy() func to copy the data which stored in 8-bit vector to 16-bit vector.

1

There are 1 answers

0
Paolo Brandoli On BEST ANSWER

The following code must be enclosed by {}

imebra::WritingDataHandlerNumeric writeIntoImage(image.getWritingDataHandler());    

//writeIntoImage.assign(buf,sizeof(buf));   
for (size_t y(0);y!=img_width;++y)
{
    for (size_t x(0); x!= img_height; ++x)
    {
        writeIntoImage.setUnsignedLong(y*img_height+x,rawdata[y*img_height+x]);
    }
}

Like this:

{
    imebra::WritingDataHandlerNumeric writeIntoImage(image.getWritingDataHandler());    

    //writeIntoImage.assign(buf,sizeof(buf));   
    for (size_t y(0);y!=img_width;++y)
    {
        for (size_t x(0); x!= img_height; ++x)
        {
            writeIntoImage.setUnsignedLong(y*img_height+x,rawdata[y*img_height+x]);
        }
    }
}

This cause the WritingDataHandlerNumeric to go out of scope and update the image's buffer.

Disclaimer: I'm the author of Imebra.