📄 gdcmpixelreadconvert.cxx
字号:
a16 = (uint16_t*)LutRGBA + 0 + debR;
for( i=0; i < lengthR; ++i )
{
*a16 = ((uint16_t*)LutRedData)[i];
a16 += 4;
}
a16 = (uint16_t*)LutRGBA + 1 + debG;
for( i=0; i < lengthG; ++i)
{
*a16 = ((uint16_t*)LutGreenData)[i];
a16 += 4;
}
a16 = (uint16_t*)LutRGBA + 2 + debB;
for(i=0; i < lengthB; ++i)
{
*a16 = ((uint16_t*)LutBlueData)[i];
a16 += 4;
}
a16 = (uint16_t*)LutRGBA + 3 ;
for(i=0; i < 65536; ++i)
{
*a16 = 1; // Alpha component
a16 += 4;
}
/* Just to 'see' the LUT, at debug time
// Don't remove this commented out code.
a16=(uint16_t*)LutRGBA;
for (int j=0;j<65536;j++)
{
std::cout << *a16 << " " << *(a16+1) << " "
<< *(a16+2) << " " << *(a16+3) << std::endl;
a16+=4;
}
*/
}
}
/**
* \brief Swap the bytes, according to \ref SwapCode.
*/
void PixelReadConvert::ConvertSwapZone()
{
unsigned int i;
// If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax',
// then the header is in little endian format and the pixel data is in
// big endian format. When reading the header, GDCM has already established
// a byte swapping code suitable for this machine to read the
// header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
// to be switched in order to read the pixel data. This must be
// done REGARDLESS of the processor endianess!
//
// Example: Assume we are on a little endian machine. When
// GDCM reads the header, the header will match the machine
// endianess and the swap code will be established as a no-op.
// When GDCM reaches the pixel data, it will need to switch the
// swap code to do big endian to little endian conversion.
//
// Now, assume we are on a big endian machine. When GDCM reads the
// header, the header will be recognized as a different endianess
// than the machine endianess, and a swap code will be established
// to convert from little endian to big endian. When GDCM readers
// the pixel data, the pixel data endianess will now match the
// machine endianess. But we currently have a swap code that
// converts from little endian to big endian. In this case, we
// need to switch the swap code to a no-op.
//
// Therefore, in either case, if the file is in
// 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
// the byte swapping code when entering the pixel data.
int tempSwapCode = SwapCode;
if ( IsPrivateGETransferSyntax )
{
gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode");
// PrivateGETransferSyntax only exists for 'true' Dicom images
// we assume there is no 'exotic' 32 bits endianess!
if (SwapCode == 1234)
{
tempSwapCode = 4321;
}
else if (SwapCode == 4321)
{
tempSwapCode = 1234;
}
}
if ( BitsAllocated == 16 )
{
uint16_t *im16 = (uint16_t*)Raw;
switch( tempSwapCode )
{
case 1234:
break;
case 3412:
case 2143:
case 4321:
for( i = 0; i < RawSize / 2; i++ )
{
im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
}
break;
default:
gdcmWarningMacro("SwapCode value (16 bits) not allowed."
<< tempSwapCode);
}
}
else if ( BitsAllocated == 32 )
{
uint32_t s32;
uint16_t high;
uint16_t low;
uint32_t *im32 = (uint32_t*)Raw;
switch ( tempSwapCode )
{
case 1234:
break;
case 4321:
for( i = 0; i < RawSize / 4; i++ )
{
low = im32[i] & 0x0000ffff; // 4321
high = im32[i] >> 16;
high = ( high >> 8 ) | ( high << 8 );
low = ( low >> 8 ) | ( low << 8 );
s32 = low;
im32[i] = ( s32 << 16 ) | high;
}
break;
case 2143:
for( i = 0; i < RawSize / 4; i++ )
{
low = im32[i] & 0x0000ffff; // 2143
high = im32[i] >> 16;
high = ( high >> 8 ) | ( high << 8 );
low = ( low >> 8 ) | ( low << 8 );
s32 = high;
im32[i] = ( s32 << 16 ) | low;
}
break;
case 3412:
for( i = 0; i < RawSize / 4; i++ )
{
low = im32[i] & 0x0000ffff; // 3412
high = im32[i] >> 16;
s32 = low;
im32[i] = ( s32 << 16 ) | high;
}
break;
default:
gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
}
}
}
/**
* \brief Deal with endianness i.e. re-arange bytes inside the integer
*/
void PixelReadConvert::ConvertReorderEndianity()
{
if ( BitsAllocated != 8 )
{
ConvertSwapZone();
}
// Special kludge in order to deal with xmedcon broken images:
if ( BitsAllocated == 16
&& BitsStored < BitsAllocated
&& !PixelSign )
{
int l = (int)( RawSize / ( BitsAllocated / 8 ) );
uint16_t *deb = (uint16_t *)Raw;
for(int i = 0; i<l; i++)
{
if ( *deb == 0xffff )
{
*deb = 0;
}
deb++;
}
}
}
/**
* \brief Deal with Grey levels i.e. re-arange them
* to have low values = dark, high values = bright
*/
void PixelReadConvert::ConvertFixGreyLevels()
{
if (!IsMonochrome1)
return;
uint32_t i; // to please M$VC6
int16_t j;
if (!PixelSign)
{
if ( BitsAllocated == 8 )
{
uint8_t *deb = (uint8_t *)Raw;
for (i=0; i<RawSize; i++)
{
*deb = 255 - *deb;
deb++;
}
return;
}
if ( BitsAllocated == 16 )
{
uint16_t mask =1;
for (j=0; j<BitsStored-1; j++)
{
mask = (mask << 1) +1; // will be fff when BitsStored=12
}
uint16_t *deb = (uint16_t *)Raw;
for (i=0; i<RawSize/2; i++)
{
*deb = mask - *deb;
deb++;
}
return;
}
}
else
{
if ( BitsAllocated == 8 )
{
uint8_t smask8 = 255;
uint8_t *deb = (uint8_t *)Raw;
for (i=0; i<RawSize; i++)
{
*deb = smask8 - *deb;
deb++;
}
return;
}
if ( BitsAllocated == 16 )
{
uint16_t smask16 = 65535;
uint16_t *deb = (uint16_t *)Raw;
for (i=0; i<RawSize/2; i++)
{
*deb = smask16 - *deb;
deb++;
}
return;
}
}
}
/**
* \brief Re-arrange the bits within the bytes.
* @return Boolean always true
*/
bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
{
if ( BitsStored != BitsAllocated )
{
int l = (int)( RawSize / ( BitsAllocated / 8 ) );
if ( BitsAllocated == 16 )
{
// pmask : to mask the 'unused bits' (may contain overlays)
uint16_t pmask = 0xffff;
pmask = pmask >> ( BitsAllocated - BitsStored );
uint16_t *deb = (uint16_t*)Raw;
if ( !PixelSign ) // Pixels are unsigned
{
for(int i = 0; i<l; i++)
{
*deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
deb++;
}
}
else // Pixels are signed
{
// smask : to check the 'sign' when BitsStored != BitsAllocated
uint16_t smask = 0x0001;
smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
// nmask : to propagate sign bit on negative values
int16_t nmask = (int16_t)0x8000;
nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
for(int i = 0; i<l; i++)
{
*deb = *deb >> (BitsStored - HighBitPosition - 1);
if ( *deb & smask )
{
*deb = *deb | nmask;
}
else
{
*deb = *deb & pmask;
}
deb++;
}
}
}
else if ( BitsAllocated == 32 )
{
// pmask : to mask the 'unused bits' (may contain overlays)
uint32_t pmask = 0xffffffff;
pmask = pmask >> ( BitsAllocated - BitsStored );
uint32_t *deb = (uint32_t*)Raw;
if ( !PixelSign )
{
for(int i = 0; i<l; i++)
{
*deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
deb++;
}
}
else
{
// smask : to check the 'sign' when BitsStored != BitsAllocated
uint32_t smask = 0x00000001;
smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
// nmask : to propagate sign bit on negative values
int32_t nmask = 0x80000000;
nmask = nmask >> ( BitsAllocated - BitsStored -1 );
for(int i = 0; i<l; i++)
{
*deb = *deb >> (BitsStored - HighBitPosition - 1);
if ( *deb & smask )
*deb = *deb | nmask;
else
*deb = *deb & pmask;
deb++;
}
}
}
else
{
gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
throw FormatError( "Weird image !?" );
}
}
return true;
}
/**
* \brief Convert (Red plane, Green plane, Blue plane) to RGB pixels
* \warning Works on all the frames at a time
*/
void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
{
gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
uint8_t *localRaw = Raw;
uint8_t *copyRaw = new uint8_t[ RawSize ];
memmove( copyRaw, localRaw, RawSize );
int l = XSize * YSize * ZSize;
uint8_t *a = copyRaw;
uint8_t *b = copyRaw + l;
uint8_t *c = copyRaw + l + l;
for (int j = 0; j < l; j++)
{
*(localRaw++) = *(a++);
*(localRaw++) = *(b++);
*(localRaw++) = *(c++);
}
delete[] copyRaw;
}
/**
* \brief Convert (cY plane, cB plane, cR plane) to RGB pixels
* \warning Works on all the frames at a time
*/
void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
{
// Remarks for YBR newbees :
// YBR_FULL works very much like RGB, i.e. three samples per pixel,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -