pixels - DICOM Convert 16 bit to 8bit -
big trees: want find solution of follow question: want convert pixeldata of dicom file 8bit(byte[]) file bitsallocated 16bit. whatever it's grayscale or color. know color's simpleperpixel 3.
3q!!!!
you cannot take pixel data , transform 8 bit (unless sure values in range supported byte). because alter important data: dicom file may store pixel data in visual density units or hounsfield units, , modifying values may screw things.
you can apply transformation 8 bits presentation data, values resulting modality voi/lut , presentation voi/lut transformations.
this example uses imebra library uses presentation data obtain 8 bits per color channel image, saved in jpeg format. modify color space ybr_full rgb in both color transform , image allocation in order rgb image.
example (in case link changes):
/* imebra 2011 build 2013-07-16_08-42-08 imebra: c++ dicom library copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 paolo brandoli/binarno s.p. rights reserved. program free software; can redistribute and/or modify under terms of gnu general public license version 2 published free software foundation. program distributed in hope useful, without warranty; without implied warranty of merchantability or fitness particular purpose. see gnu general public license more details. should have received copy of gnu general public license along program; if not, write free software foundation, inc., 51 franklin st, fifth floor, boston, ma 02110-1301 usa ------------------- if want use imebra commercially have buy commercial support available @ http://imebra.com after buy commercial support can use imebra according terms described in imebra commercial license version 1. copy of imebra commercial license version 1 available in documentation pages. imebra available @ http://imebra.com author can contacted email @ info@binarno.com or mail @ following address: paolo brandoli rakuseva 14 1000 ljubljana slovenia */ #include <iostream> #include "../../library/imebra/include/imebra.h" #include <sstream> #ifdef puntoexe_windows #include <process.h> #else #include <spawn.h> #include <sys/wait.h> #endif #include <memory> #include <list> using namespace puntoexe; using namespace puntoexe::imebra; int findargument(const char* argument, int argc, char* argv[]) { for(int scanarg(0); scanarg != argc; ++scanarg) { if(std::string(argv[scanarg]) == argument) { return scanarg; } } return -1; } int main(int argc, char* argv[]) { std::wstring version(l"1.0.0.1"); std::wcout << l"dicom2jpeg version " << version << std::endl; try { if(argc < 3) { std::wcout << l"usage: dicom2jpeg dicomfilename jpegfilename [-ffmpeg ffmpegpath ffmpegopt]" << std::endl; std::wcout << "dicomfilename = name of dicom file" << std::endl; std::wcout << "jpegfilename = name of final jpeg file" << std::endl; std::wcout << "-ffmpeg ffmpegpath = launches ffmpeg after generating jpeg images." << std::endl; std::wcout << " ffmpegpath path ffmpeg" << std::endl; std::wcout << " ffmpegopt options ffmpeg" << std::endl; std::wcout << " input images , frame rate added automatically options" << std::endl; return 1; } // separate extension file name std::string outputfilename(argv[2]); std::string extension; size_t dotpos(outputfilename.rfind('.')); if(dotpos != outputfilename.npos) { extension = outputfilename.substr(dotpos); outputfilename.erase(dotpos); } else { extension = ".jpg"; } // check -ffmpeg flag int ffmpegflag(findargument("-ffmpeg", argc, argv)); size_t framescount(0); ptr<dataset> loadeddataset; try { // open file containing dicom dataset ptr<puntoexe::stream> inputstream(new puntoexe::stream); inputstream->openfile(argv[1], std::ios_base::in); // connect stream reader dicom stream. several stream reader // can share same stream ptr<puntoexe::streamreader> reader(new streamreader(inputstream)); // codec factory , let use right codec create dataset // input stream ptr<codecs::codecfactory> codecsfactory(codecs::codecfactory::getcodecfactory()); loadeddataset = codecsfactory->load(reader, 2048); // first image. use in case there isn't presentation voi/lut // , have calculate optimal 1 ptr<image> datasetimage(loadeddataset->getimage(0)); imbxuint32 width, height; datasetimage->getsize(&width, &height); // build transforms chain ptr<transforms::transformschain> chain(new transforms::transformschain); ptr<transforms::modalityvoilut> modalityvoilut(new transforms::modalityvoilut(loadeddataset)); chain->addtransform(modalityvoilut); ptr<transforms::colortransforms::colortransformsfactory> colorfactory(transforms::colortransforms::colortransformsfactory::getcolortransformsfactory()); if(colorfactory->ismonochrome(datasetimage->getcolorspace())) { // convert monochrome2 if modality transform not present if(modalityvoilut->isempty()) { ptr<transforms::colortransforms::colortransform> monochromecolortransform(colorfactory->gettransform(datasetimage->getcolorspace(), l"monochrome2")); if(monochromecolortransform != 0) { chain->addtransform(monochromecolortransform); } } ptr<transforms::voilut> presentationvoilut(new transforms::voilut(loadeddataset)); imbxuint32 firstvoilutid(presentationvoilut->getvoilutid(0)); if(firstvoilutid != 0) { presentationvoilut->setvoilut(firstvoilutid); } else { // run transform on first image ptr<image> temporaryimage = chain->allocateoutputimage(datasetimage, width, height); chain->runtransform(datasetimage, 0, 0, width, height, temporaryimage, 0, 0); // find optimal voilut presentationvoilut->applyoptimalvoi(temporaryimage, 0, 0, width, height); } chain->addtransform(presentationvoilut); } std::wstring initialcolorspace; if(chain->isempty()) { initialcolorspace = datasetimage->getcolorspace(); } else { ptr<image> startimage(chain->allocateoutputimage(datasetimage, 1, 1)); initialcolorspace = startimage->getcolorspace(); } // color transform ycrcb ptr<transforms::colortransforms::colortransform> colortransform(colorfactory->gettransform(initialcolorspace, l"ybr_full")); if(colortransform != 0) { chain->addtransform((colortransform)); } ptr<image> finalimage(new image); finalimage->create(width, height, image::depthu8, l"ybr_full", 7); // scan through frames for(imbxuint32 framenumber(0); ; ++framenumber) { if(framenumber != 0) { datasetimage = loadeddataset->getimage(framenumber); } if(chain->isempty() && datasetimage->getdepth() != finalimage->getdepth() && datasetimage->gethighbit() != finalimage->gethighbit()) { chain->addtransform(new transforms::transformhighbit); } if(!chain->isempty()) { chain->runtransform(datasetimage, 0, 0, width, height, finalimage, 0, 0); } else { finalimage = datasetimage; } // open stream jpeg const std::wstring jpegtransfersyntax(l"1.2.840.10008.1.2.4.50"); std::ostringstream jpegfilename; jpegfilename << outputfilename; if(framenumber != 0 || ffmpegflag >= 0) { jpegfilename << "_" << framenumber; } jpegfilename << extension; ptr<puntoexe::stream> jpegstream(new puntoexe::stream); jpegstream->openfile(jpegfilename.str(), std::ios_base::out | std::ios_base::trunc); ptr<puntoexe::streamwriter> jpegwriter(new streamwriter(jpegstream)); ptr<codecs::codec> outputcodec(codecsfactory->getcodec(jpegtransfersyntax)); // write jpeg image stream outputcodec->setimage(jpegwriter, finalimage, jpegtransfersyntax, codecs::codec::veryhigh, "ob", 8, false, false, false, false); ++framescount; } } catch(datasetimagedoesntexist&) { // ignore exception. thrown when reach // end of images list exceptionsmanager::getmessage(); } // images have been generated. // should launch ffmpeg? if(ffmpegflag >= 0 && framescount != 0) { // list of arguments passed ffmpeg typedef std::list<std::string> toptionslist; toptionslist options; // first argument application's name options.push_back(argv[ffmpegflag + 1]); // calculate frames per second available tags double framespersecond(0); double frametime(loadeddataset->getdouble(0x0018, 0, 0x1063, 0)); if(frametime > 0.1) { framespersecond = 1000 / frametime; } if(framespersecond < 0.1) { framespersecond = loadeddataset->getunsignedlong(0x0018, 0x0, 0x0040, 0x0); } if(framespersecond < 0.1) { framespersecond = loadeddataset->getunsignedlong(0x0008, 0x0, 0x2144, 0x0); } // add ffmpeg argument frames per second if(framespersecond > 0.1) { options.push_back("-r"); std::ostringstream framerate; framerate << framespersecond; options.push_back(framerate.str()); } // add ffmpeg argument input files options.push_back("-i"); options.push_back(outputfilename + "_%d" + extension); // add ffmpeg argument number of frames options.push_back("-dframes"); std::ostringstream framecount; framecount << (unsigned long)framescount; options.push_back(framecount.str()); // add arguments specified when dicom2jpeg launched for(int copyarguments(ffmpegflag + 2); copyarguments < argc; ++copyarguments) { options.push_back(argv[copyarguments]); } // build arguments array std::auto_ptr<const char*> ffargv(new const char*[options.size() + 1]); size_t insertposition(0); for(toptionslist::iterator scanoptions(options.begin()); scanoptions != options.end(); ++scanoptions, ++insertposition) { ffargv.get()[insertposition] = (*scanoptions).c_str(); } ffargv.get()[options.size()] = 0; // launch ffmpeg #ifdef puntoexe_windows return (int)_spawnvp(_p_wait , argv[ffmpegflag + 1], ffargv.get()); #else char *environment[] = {0}; pid_t process_id; posix_spawnp (&process_id, argv[ffmpegflag + 1], 0, 0, (char* const*)ffargv.get(), (char* const*)environment); wait(0); #endif } return 0; } catch(...) { std::wcout << exceptionsmanager::getmessage(); return 1; } }
Comments
Post a Comment