#include "gdcmImageChangeTransferSyntax.h"
#include "gdcmSequenceOfFragments.h"
#include "gdcmSequenceOfItems.h"
#include "gdcmFragment.h"
#include "gdcmPixmap.h"
#include "gdcmBitmap.h"
#include "gdcmRAWCodec.h"
#include "gdcmJPEGCodec.h"
#include "gdcmJPEGLSCodec.h"
#include "gdcmJPEG2000Codec.h"
#include "gdcmRLECodec.h"
namespace gdcm
{
void UpdatePhotometricInterpretation( Bitmap const &input, Bitmap &output )
{
if( input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT
|| input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT )
{
output.SetPhotometricInterpretation( PhotometricInterpretation::RGB );
}
if( input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422
|| input.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_PARTIAL_422 )
{
output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_FULL );
}
gdcm_assert( output.GetPhotometricInterpretation() == PhotometricInterpretation::RGB
|| output.GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL
|| output.GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME1
|| output.GetPhotometricInterpretation() == PhotometricInterpretation::MONOCHROME2
|| output.GetPhotometricInterpretation() == PhotometricInterpretation::ARGB
|| output.GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ); }
bool ImageChangeTransferSyntax::TryRAWCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output)
{
unsigned long len = input.GetBufferLength(); (void)len;
const TransferSyntax &ts = GetTransferSyntax();
RAWCodec codec;
if( codec.CanCode( ts ) )
{
codec.SetDimensions( input.GetDimensions() );
codec.SetPlanarConfiguration( input.GetPlanarConfiguration() );
codec.SetPhotometricInterpretation( input.GetPhotometricInterpretation() );
codec.SetPixelFormat( input.GetPixelFormat() );
codec.SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() );
DataElement out;
bool r = codec.Code(pixelde, out);
if( !r )
{
return false;
}
DataElement &de = output.GetDataElement();
de.SetValue( out.GetValue() );
UpdatePhotometricInterpretation( input, output );
return true;
}
return false;
}
bool ImageChangeTransferSyntax::TryRLECodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output)
{
unsigned long len = input.GetBufferLength(); (void)len;
const TransferSyntax &ts = GetTransferSyntax();
RLECodec codec;
if( codec.CanCode( ts ) )
{
codec.SetDimensions( input.GetDimensions() );
codec.SetPlanarConfiguration( input.GetPlanarConfiguration() );
codec.SetPhotometricInterpretation( input.GetPhotometricInterpretation() );
codec.SetPixelFormat( input.GetPixelFormat() );
codec.SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() );
DataElement out;
bool r = codec.Code(pixelde, out);
if( !r )
{
return false;
}
DataElement &de = output.GetDataElement();
de.SetValue( out.GetValue() );
UpdatePhotometricInterpretation( input, output );
if( input.GetPixelFormat().GetSamplesPerPixel() == 3 )
{
if( input.GetPlanarConfiguration() == 0 )
{
output.SetPlanarConfiguration(1);
}
}
return true;
}
return false;
}
bool ImageChangeTransferSyntax::TryJPEGCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output)
{
unsigned long len = input.GetBufferLength(); (void)len;
const TransferSyntax &ts = GetTransferSyntax();
JPEGCodec jpgcodec;
if( ts.IsLossy() )
{
jpgcodec.SetLossless( false );
}
ImageCodec *codec = &jpgcodec;
JPEGCodec *usercodec = dynamic_cast<JPEGCodec*>(UserCodec);
if( usercodec && usercodec->CanCode( ts ) )
{
codec = usercodec;
}
if( codec->CanCode( ts ) )
{
codec->SetDimensions( input.GetDimensions() );
codec->SetPlanarConfiguration( input.GetPlanarConfiguration() );
codec->SetPhotometricInterpretation( input.GetPhotometricInterpretation() );
codec->SetPixelFormat( input.GetPixelFormat() );
codec->SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() );
if( !input.GetPixelFormat().IsCompatible( ts ) )
{
gdcmErrorMacro("Pixel Format incompatible with TS" );
return false;
}
DataElement out;
bool r = codec->Code(pixelde, out);
output.SetPlanarConfiguration( 0 );
if( output.GetPhotometricInterpretation() == PhotometricInterpretation::RGB )
{
gdcmWarningMacro( "Technically this is not defined in the standard. \n"
"Some validator may complains this image is invalid, but would be wrong.");
}
if( !r )
{
return false;
}
DataElement &de = output.GetDataElement();
de.SetValue( out.GetValue() );
UpdatePhotometricInterpretation( input, output );
if ( !output.GetPhotometricInterpretation().IsSameColorSpace( codec->GetPhotometricInterpretation() ) )
{
gdcm_assert(0);
}
return true;
}
return false;
}
bool ImageChangeTransferSyntax::TryJPEGLSCodec(const DataElement &pixelde, Bitmap const &input, Bitmap &output)
{
unsigned long len = input.GetBufferLength(); (void)len;
const TransferSyntax &ts = GetTransferSyntax();
JPEGLSCodec jlscodec;
ImageCodec *codec = &jlscodec;
JPEGLSCodec *usercodec = dynamic_cast<JPEGLSCodec*>(UserCodec);
if( usercodec && usercodec->CanCode( ts ) )
{
codec = usercodec;
}
if( codec->CanCode( ts ) )
{
codec->SetDimensions( input.GetDimensions() );
codec->SetPixelFormat( input.GetPixelFormat() );
codec->SetPlanarConfiguration( input.GetPlanarConfiguration() );
codec->SetPhotometricInterpretation( input.GetPhotometricInterpretation() );
codec->SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() );
DataElement out;
bool r;
if( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() )
{
ByteValue *bv = const_cast<ByteValue*>(pixelde.GetByteValue());
gdcm_assert( bv );
gdcm::DataElement tmp;
tmp.SetByteValue( bv->GetPointer(), bv->GetLength());
bv = const_cast<ByteValue*>(tmp.GetByteValue());
r = codec->CleanupUnusedBits((char*)bv->GetVoidPointer(), bv->GetLength());
if(!r) return false;
r = codec->Code(tmp, out);
}
else
{
r = codec->Code(pixelde, out);
}
if(!r) return false;
DataElement &de = output.GetDataElement();
de.SetValue( out.GetValue() );
UpdatePhotometricInterpretation( input, output );
if( input.GetPixelFormat().GetSamplesPerPixel() == 3 )
{
if( input.GetPlanarConfiguration() == 1 )
{
output.SetPlanarConfiguration(0);
}
}
return r;
}
return false;
}
bool ImageChangeTransferSyntax::TryJPEG2000Codec(const DataElement &pixelde, Bitmap const &input, Bitmap &output)
{
unsigned long len = input.GetBufferLength(); (void)len;
const TransferSyntax &ts = GetTransferSyntax();
JPEG2000Codec j2kcodec;
ImageCodec *codec = &j2kcodec;
JPEG2000Codec *usercodec = dynamic_cast<JPEG2000Codec*>(UserCodec);
if( usercodec && usercodec->CanCode( ts ) )
{
codec = usercodec;
}
if( codec->CanCode( ts ) )
{
codec->SetDimensions( input.GetDimensions() );
codec->SetPixelFormat( input.GetPixelFormat() );
codec->SetNumberOfDimensions( input.GetNumberOfDimensions() );
codec->SetPlanarConfiguration( input.GetPlanarConfiguration() );
codec->SetPhotometricInterpretation( input.GetPhotometricInterpretation() );
codec->SetNeedOverlayCleanup( input.AreOverlaysInPixelData() || input.UnusedBitsPresentInPixelData() );
DataElement out;
bool r = codec->Code(pixelde, out);
output.SetPlanarConfiguration( 0 );
if( input.GetPixelFormat().GetSamplesPerPixel() == 3 )
{
if( input.GetPhotometricInterpretation().IsSameColorSpace( PhotometricInterpretation::RGB ) )
{
if( ts == TransferSyntax::JPEG2000Lossless )
{
output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_RCT );
}
else
{
gdcm_assert( ts == TransferSyntax::JPEG2000 );
output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_ICT );
}
}
else
{
gdcm_assert( input.GetPhotometricInterpretation().IsSameColorSpace( PhotometricInterpretation::YBR_FULL ) );
if( ts == TransferSyntax::JPEG2000Lossless )
{
output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_FULL );
gdcmWarningMacro( "Technically this is not defined in the standard. \n"
"Some validator may complains this image is invalid, but would be wrong.");
}
else
{
gdcm_assert( ts == TransferSyntax::JPEG2000 );
output.SetPhotometricInterpretation( PhotometricInterpretation::YBR_FULL );
}
}
}
else
{
gdcm_assert( input.GetPixelFormat().GetSamplesPerPixel() == 1 );
}
if( !r ) return false;
DataElement &de = output.GetDataElement();
de.SetValue( out.GetValue() );
UpdatePhotometricInterpretation( input, output );
return r;
}
return false;
}
bool ImageChangeTransferSyntax::Change()
{
if( TS == TransferSyntax::TS_END )
{
if( !Force ) return false;
if( Input->GetTransferSyntax().IsEncapsulated() && Input->GetTransferSyntax() != TransferSyntax::RLELossless )
{
Output = Input;
return true;
}
return false;
}
if( Input->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR &&
TS.IsLossy() )
{
gdcmErrorMacro( "PALETTE_COLOR and Lossy compression are impossible. Convert to RGB first." );
return false;
}
Output = Input;
if( Input->GetTransferSyntax() == TS && !Force ) return true;
if( (Input->GetTransferSyntax() != TransferSyntax::ImplicitVRLittleEndian
&& Input->GetTransferSyntax() != TransferSyntax::ExplicitVRLittleEndian
&& Input->GetTransferSyntax() != TransferSyntax::ExplicitVRBigEndian)
|| ( (Input->GetTransferSyntax() == TransferSyntax::ImplicitVRLittleEndian
|| Input->GetTransferSyntax() == TransferSyntax::ExplicitVRLittleEndian
|| Input->GetTransferSyntax() == TransferSyntax::ExplicitVRBigEndian)
&& Input->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 )
|| Force )
{
DataElement pixeldata( Tag(0x7fe0,0x0010) );
ByteValue *bv0 = new ByteValue();
uint32_t len0 = (uint32_t)Input->GetBufferLength();
bv0->SetLength( len0 );
bool b = Input->GetBuffer( (char*)bv0->GetVoidPointer() );
if( !b )
{
gdcmErrorMacro( "Error in getting buffer from input image." );
delete bv0;
return false;
}
pixeldata.SetValue( *bv0 );
bool success = false;
if( !success ) success = TryRAWCodec(pixeldata, *Input, *Output);
if( !success ) success = TryJPEGCodec(pixeldata, *Input, *Output);
if( !success ) success = TryJPEGLSCodec(pixeldata, *Input, *Output);
if( !success ) success = TryJPEG2000Codec(pixeldata, *Input, *Output);
if( !success ) success = TryRLECodec(pixeldata, *Input, *Output);
Output->SetTransferSyntax( TS );
if( !success )
{
return false;
}
DataElement iconpixeldata( Tag(0x7fe0,0x0010) );
Bitmap &bitmap = *Input;
if( Pixmap *pixmap = dynamic_cast<Pixmap*>( &bitmap ) )
{
Bitmap &outbitmap = *Output;
Pixmap *outpixmap = dynamic_cast<Pixmap*>( &outbitmap );
gdcm_assert( outpixmap != nullptr );
if( !pixmap->GetIconImage().IsEmpty() )
{
ByteValue *bv = new ByteValue();
uint32_t len = (uint32_t)pixmap->GetIconImage().GetBufferLength();
bv->SetLength( len );
bool bb = pixmap->GetIconImage().GetBuffer( (char*)bv->GetVoidPointer() );
if( !bb )
{
return false;
}
iconpixeldata.SetValue( *bv );
success = false;
if( !success ) success = TryRAWCodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryJPEGCodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryJPEGLSCodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryJPEG2000Codec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryRLECodec(iconpixeldata, pixmap->GetIconImage(), outpixmap->GetIconImage());
outpixmap->GetIconImage().SetTransferSyntax( TS );
if( !success )
{
return false;
}
gdcm_assert( outpixmap->GetIconImage().GetTransferSyntax() == TS );
}
}
gdcm_assert( Output->GetTransferSyntax() == TS );
return success;
}
bool success = false;
if( !success ) success = TryRAWCodec(Input->GetDataElement(), *Input, *Output);
if( !success ) success = TryJPEGCodec(Input->GetDataElement(), *Input, *Output);
if( !success ) success = TryJPEG2000Codec(Input->GetDataElement(), *Input, *Output);
if( !success ) success = TryJPEGLSCodec(Input->GetDataElement(), *Input, *Output);
if( !success ) success = TryRLECodec(Input->GetDataElement(), *Input, *Output);
Output->SetTransferSyntax( TS );
if( !success )
{
return false;
}
Bitmap &bitmap = *Input;
if( Pixmap *pixmap = dynamic_cast<Pixmap*>( &bitmap ) )
{
if( !pixmap->GetIconImage().IsEmpty() && CompressIconImage )
{
Bitmap &outbitmap = *Output;
Pixmap *outpixmap = dynamic_cast<Pixmap*>( &outbitmap );
success = false;
if( !success ) success = TryRAWCodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryJPEGCodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryJPEGLSCodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryJPEG2000Codec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage());
if( !success ) success = TryRLECodec(pixmap->GetIconImage().GetDataElement(), pixmap->GetIconImage(), outpixmap->GetIconImage());
outpixmap->GetIconImage().SetTransferSyntax( TS );
if( !success )
{
return false;
}
gdcm_assert( outpixmap->GetIconImage().GetTransferSyntax() == TS );
}
}
gdcm_assert( Output->GetTransferSyntax() == TS );
return success;
}
}