GDCM 2.2.1

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Examples

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 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;
}