/*========================================================================= 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. =========================================================================*/ #include "gdcmReader.h" #include "gdcmWriter.h" #include "gdcmImageReader.h" #include "gdcmSequenceOfFragments.h" #include "gdcmFile.h" // http://www.lost.in.ua/dicom/c.dcm // // -> BuggyJ2Kvvvua-fixed2-j2k.dcm /* * This program attemps to fix a broken J2K/DICOM: * It contains 2 bugs: * 1. The first 8 bytes seems to be random bytes: remove them * 2. YCC is set to 1, while image is grayscale need to set it back to 0 * * Ref: * It's a software from http://rentgenprom.ru/ , shipped with universal digital radiographic units * "ProScan-2000". The Ukrainian manufacturer developed own digital radiographic unit and it is * compatible with software from "ProScan-2000". * Information found in DICOM file is: * * (0008,0070) LO [ZAO "Renthenprom" (JSC Rentgenprom) ] # 36,1 Manufacturer * (0018,1020) LO [2.13.1.7] # 8,1-n Software Version(s) * */ int main(int argc, char *argv[]) { if( argc < 3 ) { std::cerr << argv[0] << " input.dcm output.dcm" << std::endl; return 1; } const char *filename = argv[1]; const char *outfilename = argv[2]; gdcm::Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) { return 1; } gdcm::File &file = reader.GetFile(); const gdcm::DataElement &pixeldata0 = file.GetDataSet().GetDataElement( gdcm::Tag(0x7fe0,0x0010) ); const gdcm::SequenceOfFragments *sqf = pixeldata0.GetSequenceOfFragments(); if( !sqf ) { return 1; } const gdcm::Fragment &frag0 = sqf->GetFragment(0); gdcm::ByteValue *bv = const_cast(frag0.GetByteValue()); char *ptr = (char*)bv->GetVoidPointer(); size_t len = bv->GetLength(); static const unsigned char sig[] = {0,0,0,0,0x6A,0x70,0x32,0x63}; if( memcmp(ptr, sig, sizeof(sig)) != 0 ) { std::cerr << "magic random signature not found" << std::endl; return 1; } // Apparently the flag to enable a color transform on 3 color components is set in // the COD marker. (YCC is byte[6] in the COD marker) // we need to disable this flag; char *cod_marker = ptr + 0x35; /* 0x2d + 0x8 */ // FIXME if( cod_marker[0] == (char)0xff && cod_marker[1] == 0x52 ) { // found start of COD if( cod_marker[6+2] == 1 ) { // Change in place: *((char*)cod_marker + 6+2) = 0; // Prepare a new DataElement: gdcm::DataElement pixeldata( gdcm::Tag(0x7fe0,0x0010) ); pixeldata.SetVR( gdcm::VR::OB ); gdcm::SmartPointer sq = new gdcm::SequenceOfFragments; gdcm::Fragment frag; // remove 8 first bytes: frag.SetByteValue( ptr + 8, (uint32_t)(len - 8) ); sq->AddFragment( frag ); pixeldata.SetValue( *sq ); file.GetDataSet().Replace( pixeldata ); } else { return 1; } } else { std::cerr << "COD not found" << (int)cod_marker[0] << std::endl; return 1; } gdcm::Writer writer; writer.SetFile( reader.GetFile() ); writer.SetFileName( outfilename ); writer.CheckFileMetaInformationOff(); if( !writer.Write() ) { std::cerr << "Could not write" << std::endl; } // paranoid check: gdcm::ImageReader ireader; ireader.SetFileName( outfilename ); if( !ireader.Read() ) { std::cerr << "file written is still not valid, please report" << std::endl; return 1; } return 0; }