C ++ читает 16-битные двоичные данные из raw img и сохраняет их в векторе - PullRequest
0 голосов
/ 31 марта 2020

В эти дни я борюсь с малло c памятью. Я пытаюсь прочитать 16-битные двоичные данные из raw img и сохранить их в буфере или в векторе. Общий размер этих двоичных данных составляет около 15 млн. Для такого размера какой путь лучше между 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)

Кстати, если я использую вектор для хранения 16-битного значения, которое копируется из 8-битного вектора. Должен ли я сделать преобразование типа данных? Я просто использовал copy () fun c, чтобы скопировать данные, которые хранятся в 8-битном векторе в 16-битный вектор.

1 Ответ

0 голосов
/ 31 марта 2020

Следующий код должен быть заключен в {}

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]);
        }
    }
}

Это приводит к тому, что WritingDataHandlerNumeri c до go выходит из области действия и обновляется буфер изображения.

Отказ от ответственности: я автор Imebra.

...