1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
/*=========================================================================
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".
*/
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);
const gdcm::ByteValue *bv = frag0.GetByteValue();
const char *ptr = bv->GetPointer();
size_t len = bv->GetLength();
const char sig[] = "\x00\x00\x00\x00\x6A\x70\x32\x63";
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;
const 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<gdcm::SequenceOfFragments> 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;
}
|