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.
The following code must be enclosed by {}
Like this:
This cause the WritingDataHandlerNumeric to go out of scope and update the image's buffer.
Disclaimer: I'm the author of Imebra.