/*========================================================================= Program: GDCM (Grassroots DICOM). A DICOM library Copyright (c) 2006-2011 Mathieu Malaterre All rights reserved. See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // This work was realised during the GSOC 2011 by Manoj Alwani #include #include #include #include #include #include #include #include #include #include #include #include #include "gdcmImageReader.h" #include "gdcmSequenceOfItems.h" #include "gdcmSystem.h" #include #include "gdcm_openjpeg.h" #include "gdcmMediaStorage.h" #include "gdcmWriter.h" #include "gdcmItem.h" #include "gdcmImageReader.h" #include "gdcmAttribute.h" #include "gdcmFile.h" #include "gdcmTag.h" #include "gdcmTransferSyntax.h" #include "gdcmUIDGenerator.h" #include "gdcmAnonymizer.h" #include "gdcmStreamImageWriter.h" #include "gdcmImageHelper.h" #include "gdcmTrace.h" void error_callback(const char *msg, void *) { (void)msg; } void warning_callback(const char *msg, void *) { (void)msg; } void info_callback(const char *msg, void *) { (void)msg; } bool Write_Resolution(gdcm::StreamImageWriter & theStreamWriter, const char *filename, int res, std::ostream& of, int flag, gdcm::SequenceOfItems *sq, int No_Of_Resolutions) { std::ifstream is; is.open( filename, std::ios::binary ); opj_dparameters_t parameters; /* decompression parameters */ opj_event_mgr_t event_mgr; /* event manager */ opj_dinfo_t* dinfo; /* handle to a decompressor */ opj_cio_t *cio; opj_image_t *image = NULL; // FIXME: Do some stupid work: is.seekg( 0, std::ios::end); std::streampos buf_size = is.tellg(); char *dummy_buffer = new char[(unsigned int)buf_size]; is.seekg(0, std::ios::beg); is.read( dummy_buffer, buf_size); unsigned char *src = (unsigned char*)dummy_buffer; uint32_t file_length = (uint32_t)buf_size; // 32bits truncation should be ok since DICOM cannot have larger than 2Gb image /* configure the event callbacks (not required) */ memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); event_mgr.error_handler = error_callback; event_mgr.warning_handler = warning_callback; event_mgr.info_handler = info_callback; /* set decoding parameters to default values */ opj_set_default_decoder_parameters(¶meters); // default blindly copied parameters.cp_layer=0; parameters.cp_reduce= res; // parameters.decod_format=-1; // parameters.cod_format=-1; const char jp2magic[] = "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A"; if( memcmp( src, jp2magic, sizeof(jp2magic) ) == 0 ) { /* JPEG-2000 compressed image data ... sigh */ // gdcmData/ELSCINT1_JP2vsJ2K.dcm // gdcmData/MAROTECH_CT_JP2Lossy.dcm //gdcmWarningMacro( "J2K start like JPEG-2000 compressed image data instead of codestream" ); parameters.decod_format = 1; //JP2_CFMT; //assert(parameters.decod_format == JP2_CFMT); } else { /* JPEG-2000 codestream */ //parameters.decod_format = J2K_CFMT; //assert(parameters.decod_format == J2K_CFMT); assert( 0 ); } parameters.cod_format = 11; // PGX_DFMT; //assert(parameters.cod_format == PGX_DFMT); /* get a decoder handle */ dinfo = opj_create_decompress(CODEC_JP2); /* catch events using our callbacks and give a local context */ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL); /* setup the decoder decoding parameters using user parameters */ opj_setup_decoder(dinfo, ¶meters); /* open a byte stream */ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length); /* decode the stream and fill the image structure */ image = opj_decode(dinfo, cio); if(!image) { opj_destroy_decompress(dinfo); opj_cio_close(cio); //gdcmErrorMacro( "opj_decode failed" ); return 1; } opj_cp_t * cp = ((opj_jp2_t*)dinfo->jp2_handle)->j2k->cp; opj_tcp_t *tcp = &cp->tcps[0]; opj_tccp_t *tccp = &tcp->tccps[0]; /* std::cout << "\n No of Cols In Image" << image->x1; std::cout << "\n No of Rows In Image" << image->y1; std::cout << "\n No of Components in Image" << image->numcomps; std::cout << "\n No of Resolutions"<< tccp->numresolutions << "\n"; */ opj_j2k_t* j2k = NULL; opj_jp2_t* jp2 = NULL; jp2 = (opj_jp2_t*)dinfo->jp2_handle; int reversible = jp2->j2k->cp->tcps->tccps->qmfbid; //std:: cout << reversible; int compno = 0; opj_image_comp_t *comp = &image->comps[compno]; int Dimensions[2]; Dimensions[0]= comp->w; Dimensions[1] = comp->h; opj_cio_close(cio); unsigned long len = Dimensions[0]*Dimensions[1] * image->numcomps; //std::cout << "\nTest" <comps[0].factor; char *raw = new char[len]; for (unsigned int compno = 0; compno < (unsigned int)image->numcomps; compno++) { opj_image_comp_t *comp = &image->comps[compno]; int w = image->comps[compno].w; int h = image->comps[compno].h; uint8_t *data8 = (uint8_t*)raw + compno; for (int i = 0; i < w * h ; i++) { int v = image->comps[compno].data[i]; *data8 = (uint8_t)v; data8 += image->numcomps; } } gdcm::Writer w; gdcm::File &file = w.GetFile(); gdcm::DataSet &ds = file.GetDataSet(); file.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::UIDGenerator uid; gdcm::DataElement de( gdcm::Tag(0x8,0x18) ); // SOP Instance UID de.SetVR( gdcm::VR::UI ); const char *u = uid.Generate(); de.SetByteValue( u, strlen(u) ); ds.Insert( de ); gdcm::DataElement de1( gdcm::Tag(0x8,0x16) ); de1.SetVR( gdcm::VR::UI ); gdcm::MediaStorage ms( gdcm::MediaStorage::CTImageStorage ); de1.SetByteValue( ms.GetString(), strlen(ms.GetString())); ds.Insert( de1 ); const char mystr[] = "MONOCHROME2 "; gdcm::DataElement de2( gdcm::Tag(0x28,0x04) ); //de.SetTag(gdcm::Tag(0x28,0x04)); de2.SetVR( gdcm::VR::CS ); de2.SetByteValue(mystr, strlen(mystr)); ds.Insert( de2 ); gdcm::Attribute<0x0028,0x0010> row = {image->comps[0].w}; //row.SetValue(512); ds.Insert( row.GetAsDataElement() ); // w.SetCheckFileMetaInformation( true ); gdcm::Attribute<0x0028,0x0011> col = {image->comps[0].h}; ds.Insert( col.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames = {1}; ds.Insert( Number_Of_Frames.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0100> at = {8}; ds.Insert( at.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> at1 = {image->numcomps}; ds.Insert( at1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> at2 = {8}; ds.Insert( at2.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> at3 = {7}; ds.Insert( at3.GetAsDataElement() ); if (flag == 1) { for (int i=0; i < No_Of_Resolutions; i++) { int a = 1; int b =1; while(a!=((No_Of_Resolutions)-i)) { b = b*2; a = a+1; } uint16_t row = (image->y1)/b; uint16_t col = (image->x1)/b; //std::cout << row; gdcm::Element el2; el2.SetValue(i+1); gdcm::DataElement rfn = el2.GetAsDataElement(); //ulr --> upper left row rfn.SetTag( gdcm::Tag(0x0008,0x1160) ); gdcm::Element el; el.SetValue(1,0); el.SetValue(1,1); gdcm::DataElement ulr = el.GetAsDataElement(); //ulr --> upper left col/row ulr.SetTag( gdcm::Tag(0x0048,0x0201) ); gdcm::Element el1; el1.SetValue(col,0); el1.SetValue(row,1); gdcm::DataElement brr = el1.GetAsDataElement(); brr.SetTag( gdcm::Tag(0x0048,0x0202) ); //brr --> bottom right col/row gdcm::Item it; gdcm::DataSet &nds = it.GetNestedDataSet(); nds.Insert( rfn ); nds.Insert(ulr); nds.Insert(brr); sq->AddItem(it); } gdcm::Writer w1; gdcm::File &file1 = w1.GetFile(); gdcm::DataSet &ds1 = file1.GetDataSet(); file1.GetHeader().SetDataSetTransferSyntax( gdcm::TransferSyntax::ExplicitVRLittleEndian ); gdcm::UIDGenerator uid1; gdcm::DataElement dea( gdcm::Tag(0x8,0x18) ); // SOP Instance UID dea.SetVR( gdcm::VR::UI ); const char *u1 = uid1.Generate(); dea.SetByteValue( u1, strlen(u1) ); ds1.Insert( dea ); gdcm::DataElement deb( gdcm::Tag(0x8,0x16) ); deb.SetVR( gdcm::VR::UI ); gdcm::MediaStorage ms1( gdcm::MediaStorage::VLWholeSlideMicroscopyImageStorage ); deb.SetByteValue( ms1.GetString(), strlen(ms1.GetString())); ds1.Insert( deb ); const char mystr1[] = "MONOCHROME2 "; gdcm::DataElement dec( gdcm::Tag(0x28,0x04) ); //de.SetTag(gdcm::Tag(0x28,0x04)); dec.SetVR( gdcm::VR::CS ); dec.SetByteValue(mystr, strlen(mystr1)); ds1.Insert( dec ); gdcm::Attribute<0x0028,0x0010> row1 = {image->y1}; //row.SetValue(512); ds1.Insert( row1.GetAsDataElement() ); // w.SetCheckFileMetaInformation( true ); gdcm::Attribute<0x0028,0x0011> col1 = {image->x1}; ds1.Insert( col1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0008> Number_Of_Frames1 = {tccp->numresolutions}; ds1.Insert( Number_Of_Frames1.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0100> ata = {8}; ds1.Insert( ata.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0002> atb = {image->numcomps}; ds1.Insert( atb.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0101> atc = {8}; ds1.Insert( atc.GetAsDataElement() ); gdcm::Attribute<0x0028,0x0102> atd = {7}; ds1.Insert( atd.GetAsDataElement() ); theStreamWriter.SetFile(file1); gdcm::DataElement des( gdcm::Tag(0x0048,0x0200) ); des.SetVR(gdcm::VR::SQ); //des.SetVR(gdcm::VM::VM1); des.SetValue(*sq); des.SetVLToUndefined(); ds1.Insert(des); if (!theStreamWriter.WriteImageInformation()){ std::cerr << "unable to write image information" << std::endl; return 1; //the CanWrite function should prevent getting here, else, //that's a test failure } } theStreamWriter.SetFile(file); if (!theStreamWriter.CanWriteFile()){ delete [] raw; std::cout << "Not able to write"; return 0;//this means that the file was unwritable, period. //very similar to a ReadImageInformation failure } else std::cout<<"\nabletoread"; // Important to write here std::vector extent = gdcm::ImageHelper::GetDimensionsValue(file); unsigned short xmax = extent[0]; unsigned short ymax = extent[1]; unsigned short theChunkSize = 4; unsigned short ychunk = extent[1]/theChunkSize; //go in chunk sizes of theChunkSize unsigned short zmax = extent[2]; std::cout << "\n"<numcomps<<"\n"; if (xmax == 0 || ymax == 0) { std::cerr << "Image has no size, unable to write zero-sized image." << std::endl; return 0; } int z, y, nexty; unsigned long prevLen = 0; //when going through the char buffer, make sure to grab //the bytes sequentially. So, store how far you got in the buffer with each iteration. for (z = 0; z < zmax; ++z){ for (y = 0; y < ymax; y += ychunk){ nexty = y + ychunk; if (nexty > ymax) nexty = ymax; theStreamWriter.DefinePixelExtent(0, xmax, y, nexty, z, z+1); unsigned long len = theStreamWriter.DefineProperBufferLength(); std::cout << "\n" <