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