FixBrokenJ2K.cxx
/*=========================================================================
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 attempts 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<gdcm::ByteValue*>(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<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;
}
gdcm::ByteValue
Class to represent binary value (array of bytes).
Definition gdcmByteValue.h:35
gdcm::ByteValue::GetVoidPointer
const void * GetVoidPointer() const
Definition gdcmByteValue.h:115
gdcm::ByteValue::GetLength
VL GetLength() const override
Definition gdcmByteValue.h:77
gdcm::DataElement
Class to represent a Data Element either Implicit or Explicit.
Definition gdcmDataElement.h:59
gdcm::DataElement::GetByteValue
const ByteValue * GetByteValue() const
Definition gdcmDataElement.h:133
gdcm::DataElement::GetSequenceOfFragments
const SequenceOfFragments * GetSequenceOfFragments() const
gdcm::DataElement::SetValue
void SetValue(Value const &vl)
Definition gdcmDataElement.h:100
gdcm::DataElement::SetByteValue
void SetByteValue(const char *array, VL length)
Definition gdcmDataElement.h:126
gdcm::DataElement::SetVR
void SetVR(VR const &vr)
Definition gdcmDataElement.h:88
gdcm::DataSet::GetDataElement
const DataElement & GetDataElement(const Tag &t) const
Definition gdcmDataSet.h:188
gdcm::DataSet::Replace
void Replace(const DataElement &de)
Replace a dataelement with another one.
Definition gdcmDataSet.h:150
gdcm::File
a DICOM File
Definition gdcmFile.h:34
gdcm::File::GetDataSet
const DataSet & GetDataSet() const
Get Data Set.
Definition gdcmFile.h:57
gdcm::Fragment
Class to represent a Fragment.
Definition gdcmFragment.h:44
gdcm::ImageReader
ImageReader.
Definition gdcmImageReader.h:34
gdcm::ImageReader::Read
bool Read() override
gdcm::Reader
Reader ala DOM (Document Object Model).
Definition gdcmReader.h:54
gdcm::Reader::GetFile
const File & GetFile() const
Set/Get File.
Definition gdcmReader.h:72
gdcm::Reader::Read
virtual bool Read()
Main function to read a file.
gdcm::Reader::SetFileName
void SetFileName(const char *filename_native)
gdcm::SequenceOfFragments
Class to represent a Sequence Of Fragments.
Definition gdcmSequenceOfFragments.h:32
gdcm::SequenceOfFragments::GetFragment
const Fragment & GetFragment(SizeType num) const
gdcm::SmartPointer
Class for Smart Pointer.
Definition gdcmSmartPointer.h:40
gdcm::Tag
Class to represent a DICOM Data Element (Attribute) Tag (Group, Element).
Definition gdcmTag.h:39
gdcm::VR::OB
@ OB
Definition gdcmVR.h:72
gdcm::Writer
Writer ala DOM (Document Object Model).
Definition gdcmWriter.h:49
gdcm::Writer::CheckFileMetaInformationOff
void CheckFileMetaInformationOff()
Definition gdcmWriter.h:71
gdcm::Writer::Write
virtual bool Write()
Main function to tell the writer to write.
gdcm::Writer::SetFile
void SetFile(const File &f)
Set/Get the DICOM file (DataSet + Header).
Definition gdcmWriter.h:66
gdcm::Writer::SetFileName
void SetFileName(const char *filename_native)
Set the filename of DICOM file to write:
gdcmFile.h
gdcmImageReader.h
gdcmReader.h
gdcmSequenceOfFragments.h
gdcmWriter.h