这些天我在malloc内存上很吃力。我尝试从原始img中读取16位二进制数据,并将它们存储在缓冲区或向量中。这些二进制数据的总大小约为15M。对于这种大小,buf和vector之间的哪种方式更好?下面是我的代码:
#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
代码底部的两个注释是编译cmd。现在的结论是,无论我使用哪种方式1或2,代码都会停止(见上面的代码(,它说分段故障(核心转储(。
下面是gdb调试:
(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)
顺便说一下,如果我使用向量来存储从8位向量复制的16位值。我应该进行数据类型转换吗?我只是用copy((函数将存储在8位向量中的数据复制到16位向量中。
以下代码必须用{}括起来
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]);
}
}
像这样:
{
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]);
}
}
}
这会导致WritingDataHandlerNumeric超出范围并更新图像的缓冲区。
免责声明:我是Imebra的作者。