33 #ifndef __INCLUDE_MIST_DICOM_INFO__
34 #define __INCLUDE_MIST_DICOM_INFO__
37 #ifndef __INCLUDE_MIST_CONF_H__
38 #include "../config/mist_conf.h"
41 #ifndef __INCLUDE_MIST_ENDIAN__
42 #include "../config/endian.h"
45 #ifndef __INCLUDE_MIST_SINGLETON__
46 #include "../singleton.h"
49 #ifndef __INCLUDE_MIST_DICOM_TAG__
62 #ifdef __DECODE_JPEG_COMPRESSION__
64 #if defined( __MIST_WINDOWS__ ) && __MIST_WINDOWS__ > 0
67 #define HAVE_INT32 // JPEG用INT32型を持っている宣言
68 #define HAVE_BOOLEAN // JPEG用boolean型を持っている宣言
127 return( uid_table.
get_uid( uid ) );
141 return(
get_uid( std::string( reinterpret_cast< const char * >( str ), str[ numBytes - 1 ] == 0 ? numBytes - 1 : numBytes ) ) );
144 inline size_t compute_need_bytes(
const dicom_tag &tag,
size_t max_bytes,
size_t num_bytes,
bool align_max_bytes )
146 size_t rest = num_bytes % max_bytes;
148 if( rest > 0 && align_max_bytes )
150 num_bytes += max_bytes - rest;
153 if( tag.vm != -1 && num_bytes > max_bytes * tag.vm )
155 num_bytes = max_bytes * tag.vm;
161 inline size_t compute_need_bytes(
const dicom_tag &tag,
size_t num_bytes )
163 bool isEven = ( num_bytes % 2 ) == 0;
178 num_bytes = compute_need_bytes( tag, 16, num_bytes,
false );
192 num_bytes = compute_need_bytes( tag, 4, num_bytes,
true );
203 num_bytes = compute_need_bytes( tag, 4, num_bytes,
true );
218 num_bytes = compute_need_bytes( tag, 16, num_bytes,
false );
229 if( num_bytes != 8 && num_bytes != 10 )
231 num_bytes = compute_need_bytes( tag, 10, num_bytes,
true );
247 num_bytes = compute_need_bytes( tag, 16, num_bytes,
false );
262 num_bytes = compute_need_bytes( tag, 26, num_bytes,
false );
268 num_bytes = compute_need_bytes( tag, 4, num_bytes,
true );
274 num_bytes = compute_need_bytes( tag, 8, num_bytes,
true );
288 num_bytes = compute_need_bytes( tag, 16, num_bytes,
false );
302 num_bytes = compute_need_bytes( tag, 64, num_bytes,
false );
316 num_bytes = compute_need_bytes( tag, 10240, num_bytes,
false );
353 num_bytes = compute_need_bytes( tag, 64, num_bytes,
false );
367 num_bytes = compute_need_bytes( tag, 16, num_bytes,
false );
373 num_bytes = compute_need_bytes( tag, 4, num_bytes,
true );
385 num_bytes = compute_need_bytes( tag, 2, num_bytes,
true );
398 num_bytes = compute_need_bytes( tag, 1024, num_bytes,
false );
413 num_bytes = compute_need_bytes( tag, 16, num_bytes,
false );
425 num_bytes = compute_need_bytes( tag, 64, num_bytes,
false );
431 num_bytes = compute_need_bytes( tag, 4, num_bytes,
true );
441 num_bytes = compute_need_bytes( tag, 2, num_bytes,
true );
463 inline void padding_bytes(
const dicom_tag &tag,
unsigned char *from,
unsigned char *to )
509 void create(
const size_type nbytes )
511 if( num_bytes != nbytes )
518 if( num_bytes != 0 && data == NULL )
520 data =
new unsigned char[ num_bytes + 1 ];
521 data[ num_bytes ] =
'\0';
527 void copy(
const unsigned char *p,
const size_type nbytes )
533 memcpy( data, p, nbytes );
542 unsigned char *tmp = data;
546 size_type nbytes = num_bytes;
556 size_type need_bytes = compute_need_bytes( *
this, num_bytes );
558 if( num_bytes != need_bytes && need_bytes > 0 )
560 size_t nbytes = num_bytes;
561 unsigned char *tmp = data;
565 create( need_bytes );
568 if( nbytes > need_bytes )
573 memcpy( data, tmp, nbytes );
574 padding_bytes( *
this, data + nbytes, data + num_bytes );
591 bool operator <(
const dicom_element &dicm )
const {
return( base::operator <( dicm ) ); }
599 base::operator =( dicm );
601 memcpy( data, dicm.
data,
sizeof(
unsigned char ) * num_bytes );
608 void modify(
const std::string &value )
614 float val = ( float )atof( value.c_str( ) );
615 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< unsigned char * >( &val ),
sizeof(
float ) );
620 double val = atof( value.c_str( ) );
621 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< unsigned char * >( &val ),
sizeof(
double ) );
626 long val = atoi( value.c_str( ) );
627 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< unsigned char * >( &val ),
sizeof(
long ) );
632 short val = ( short )atoi( value.c_str( ) );
633 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< unsigned char * >( &val ),
sizeof(
short ) );
638 unsigned long val = atoi( value.c_str( ) );
639 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< unsigned char * >( &val ),
sizeof(
unsigned long ) );
644 unsigned short val = (
unsigned short )atoi( value.c_str( ) );
645 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< unsigned char * >( &val ),
sizeof(
unsigned short ) );
650 *
this =
dicom_element( get_group( ), get_element( ), reinterpret_cast< const unsigned char * >( value.c_str( ) ), value.size( ) );
657 double to_double( )
const {
return( ( vr ==
FD && num_bytes == 8 )?
byte_array< double >( data ).get_value( ) : static_cast< double > ( atof( to_string( ).c_str( ) ) ) ); }
660 float to_float( )
const {
return( ( vr ==
FL && num_bytes == 4 )?
byte_array< float >( data ).get_value( ) : static_cast< float > ( atof( to_string( ).c_str( ) ) ) ); }
663 signed int to_int( )
const {
return( ( vr ==
SL && num_bytes == 4 )?
byte_array< signed int >( data ).get_value( ) : static_cast< signed int > ( atoi( to_string( ).c_str( ) ) ) ); }
666 unsigned int to_uint( )
const {
return( ( vr ==
UL && num_bytes == 4 )?
byte_array< unsigned int >( data ).get_value( ) : static_cast< unsigned int > ( atoi( to_string( ).c_str( ) ) ) ); }
675 std::string to_string( )
const
677 if( data != NULL && num_bytes > 0 )
679 static char buff[ 128 ];
709 return( std::string( reinterpret_cast< char * >( data ) ) );
721 void show_tag( )
const
723 if( data == NULL || num_bytes == 0 )
725 printf(
"( %04x, %04x, %s, % 8d, %s ) = undefined!!\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str() );
730 dicom_uid uid =
get_uid( std::string( reinterpret_cast< char * >( data ), num_bytes ) );
731 printf(
"( %04x, %04x, %s, % 8d, %s ) = %s\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), uid.
name.c_str( ) );
738 printf(
"( %04x, %04x, %s, % 8d, %s ) = %f\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), to_float( ) );
741 printf(
"( %04x, %04x, %s, % 8d, %s ) = %f\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), to_double( ) );
744 printf(
"( %04x, %04x, %s, % 8d, %s ) = %d\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), to_int( ) );
747 printf(
"( %04x, %04x, %s, % 8d, %s ) = %d\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), to_short( ) );
750 printf(
"( %04x, %04x, %s, % 8d, %s ) = %d\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), to_uint( ) );
753 printf(
"( %04x, %04x, %s, % 8d, %s ) = %d\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(), to_ushort( ) );
760 printf(
"( %04x, %04x, %s, % 8d, %s ) = ...\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str() );
764 printf(
"( %04x, %04x, %s, % 8d, %s ) = %s\n", get_group( ), get_element( ),
get_dicom_vr( vr ).c_str(), static_cast< unsigned int >( num_bytes ), comment.c_str(),
reinterpret_cast< char *
>( data ) );
782 dicom_element(
unsigned short group,
unsigned short element,
const unsigned char *d = NULL, size_type nbytes = 0 )
806 typedef std::map< unsigned int, dicom_element > base;
807 typedef std::pair< unsigned int, dicom_element > element_pair;
820 const dicom_element &operator ()(
unsigned short group,
unsigned short element )
const
822 const_iterator cite = find( group, element );
823 return( cite->second );
830 std::pair< iterator, bool > ite = base::insert( element_pair( element.
tag, element ) );
831 return( ite.second );
837 std::pair< iterator, bool > ite = base::insert( element_pair( element.
tag, element ) );
844 base::erase( element.
tag );
850 base::erase( tag.
tag );
854 void erase(
unsigned short group,
unsigned short element )
862 base::erase( element.tag );
868 base::erase( tag.tag );
872 void remove(
unsigned short group,
unsigned short element )
879 iterator find(
unsigned short group,
unsigned short element )
885 const_iterator find(
unsigned short group,
unsigned short element )
const
892 bool contain(
unsigned short group,
unsigned short element )
const
894 return( find( group, element ) != base::end( ) );
900 for( iterator ite = base::begin( ) ; ite != base::end( ) ; ++ite )
902 ite->second.update( );
909 dicom_tag_container(
const dicom_tag_container &dicm ) : base( dicm )
945 compression_type(
RAW ),
946 photometric_type( UNKNOWNTYPE ),
947 samples_per_pixel( 1 ),
948 number_of_frames( 1 ),
951 pixel_spacing_x( 1.0 ),
952 pixel_spacing_y( 1.0 ),
953 image_position_x( 1.0 ),
954 image_position_y( 1.0 ),
955 image_position_z( 1.0 ),
956 rescale_intercept( 0.0 ),
957 rescale_slope( 1.0 ),
961 pixel_representation( 0 ),
962 planar_configuration( 0 ),
963 window_center( 128 ),
989 little_endian_encoding( true ),
990 study_instance_uid(
"0" ),
991 series_instance_uid(
"0" ),
995 acquisition_number( 0 ),
1003 little_endian_encoding( info.little_endian_encoding ),
1004 study_instance_uid( info.study_instance_uid ),
1005 series_instance_uid( info.series_instance_uid ),
1006 study_id( info.study_id ),
1007 patient_id( info.patient_id ),
1008 series_number( info.series_number ),
1009 acquisition_number( info.acquisition_number ),
1010 instance_number( info.instance_number )
1020 dicom_image_info::operator =( info );
1038 } __dicom_compress_type__;
1040 inline std::string trim(
const std::string &str )
1042 std::string::difference_type sindx = 0;
1043 std::string::difference_type eindx = str.length( ) - 1;
1045 for( ; sindx <= eindx ; sindx++ )
1047 if( str[ sindx ] != 0x20 )
1053 for( ; sindx <= eindx ; eindx-- )
1055 if( str[ eindx ] != 0x20 )
1061 if( sindx <= eindx )
1063 return( str.substr( sindx, eindx - sindx + 1 ) );
1074 static __dicom_compress_type__ compress_type_list[] = {
1075 {
"1.2.840.10008.1.2.4.50",
JPEG, },
1076 {
"1.2.840.10008.1.2.4.51",
JPEG, },
1077 {
"1.2.840.10008.1.2.4.52",
JPEG, },
1078 {
"1.2.840.10008.1.2.4.53",
JPEG, },
1079 {
"1.2.840.10008.1.2.4.54",
JPEG, },
1080 {
"1.2.840.10008.1.2.4.55",
JPEG, },
1081 {
"1.2.840.10008.1.2.4.56",
JPEG, },
1082 {
"1.2.840.10008.1.2.4.57",
JPEGLS, },
1083 {
"1.2.840.10008.1.2.4.58",
JPEGLS, },
1084 {
"1.2.840.10008.1.2.4.59",
JPEG, },
1085 {
"1.2.840.10008.1.2.4.60",
JPEG, },
1086 {
"1.2.840.10008.1.2.4.61",
JPEG, },
1087 {
"1.2.840.10008.1.2.4.62",
JPEG, },
1088 {
"1.2.840.10008.1.2.4.63",
JPEG, },
1089 {
"1.2.840.10008.1.2.4.64",
JPEG, },
1090 {
"1.2.840.10008.1.2.4.65",
JPEGLS, },
1091 {
"1.2.840.10008.1.2.4.66",
JPEGLS, },
1092 {
"1.2.840.10008.1.2.4.70",
JPEGLS, },
1093 {
"1.2.840.10008.1.2.4.80",
JPEGLS, },
1094 {
"1.2.840.10008.1.2.4.81",
JPEGLS, },
1095 {
"1.2.840.10008.1.2.4.90",
JPEG2000, },
1096 {
"1.2.840.10008.1.2.4.91",
JPEG2000, },
1097 {
"1.2.840.10008.1.2.5",
RLE, },
1101 __dicom_compress_type__ *list = compress_type_list;
1102 while( list->uid != NULL )
1104 if( uid == list->uid )
1106 return( list->type );
1119 return( cite == dicm.end( ) ? default_value : cite->second.to_double( ) );
1126 return( cite == dicm.end( ) ? default_value : cite->second.to_float( ) );
1133 return( cite == dicm.end( ) ? default_value : cite->second.to_int( ) );
1140 return( cite == dicm.end( ) ? default_value : cite->second.to_uint( ) );
1147 return( cite == dicm.end( ) ? default_value : cite->second.to_short( ) );
1154 return( cite == dicm.end( ) ? default_value : cite->second.to_ushort( ) );
1161 return( cite == dicm.end( ) ? default_value : cite->second.to_string( ) );
1168 return( cite == dicm.end( ) ? default_value : cite->second.to_string( ) );
1171 inline bool begin_with(
const std::string &str1,
const std::string &str2 )
1173 if( str1.size( ) < str2.size( ) )
1178 for(
size_t i = 0 ; i < str2.size( ) ; i++ )
1180 if( str1[ i ] != str2[ i ] )
1189 inline bool can_convert_to_number(
const std::string &str )
1192 for( i = 0 ; i < str.size( ) ; i++ )
1194 std::string::value_type ch = str[ i ];
1195 if( (
'0' <= ch && ch <=
'9' ) || (
'+' <= ch && ch <=
'.' ) )
1199 else if( ch !=
' ' )
1204 for( ; i < str.size( ) ; i++ )
1206 std::string::value_type ch = str[ i ];
1211 else if( !( (
'0' <= ch && ch <=
'9' ) || (
'+' <= ch && ch <=
'.' ) ) )
1216 for( ; i < str.size( ) ; i++ )
1218 std::string::value_type ch = str[ i ];
1239 std::string photometric_interpretation =
find_tag( dicm, 0x0028, 0x0004,
"" );
1240 if( begin_with( photometric_interpretation,
"MONOCHROME1" ) )
1244 else if( begin_with( photometric_interpretation,
"MONOCHROME2" ) )
1248 else if( begin_with( photometric_interpretation,
"RGB" ) )
1252 else if( begin_with( photometric_interpretation,
"PALETTE COLOR" ) )
1256 else if( begin_with( photometric_interpretation,
"YBR FULL 422" ) )
1260 else if( begin_with( photometric_interpretation,
"YBR FULL" ) )
1267 std::string pixel_spacing =
find_tag( dicm, 0x0028, 0x0030,
"" );
1268 if( pixel_spacing !=
"" )
1270 double resoX = 1.0, resoY = 1.0;
1271 sscanf( pixel_spacing.c_str( ),
"%lf\\%lf", &resoX, &resoY );
1277 std::string image_position =
find_tag( dicm, 0x0020, 0x0032,
"" );
1278 if( image_position !=
"" )
1280 double posX = 0.0, posY = 0.0, posZ = 0.0;
1281 sscanf( image_position.c_str( ),
"%lf\\%lf\\%lf", &posX, &posY, &posZ );
1292 std::string kvp =
find_tag( dicm, 0x0018, 0x0060,
"" );
1295 info.
KVP = atof( kvp.c_str( ) );
1299 std::string mA =
find_tag( dicm, 0x0018, 0x1151,
"" );
1302 info.
mA = atoi( mA.c_str( ) );
1309 std::string rescale_intercept =
find_tag( dicm, 0x0028, 0x1052,
"" );
1310 if( rescale_intercept !=
"" && can_convert_to_number( rescale_intercept ) )
1316 std::string rescale_slope =
find_tag( dicm, 0x0028, 0x1053,
"" );
1317 if( rescale_slope !=
"" && can_convert_to_number( rescale_slope ) )
1323 std::string window_center =
find_tag( dicm, 0x0028, 0x1050,
"" );
1324 if( window_center !=
"" && can_convert_to_number( window_center ) )
1330 std::string window_width =
find_tag( dicm, 0x0028, 0x1051,
"" );
1331 if( window_width !=
"" && can_convert_to_number( window_width ) )
1369 return( p[ 0 ] == 0xfe && p[ 1 ] == 0xff && p[ 2 ] == 0x00 && p[ 3 ] == 0xe0 );
1386 return( p[ 0 ] == 0xfe && p[ 1 ] == 0xff && p[ 2 ] == 0xdd && p[ 3 ] == 0xe0 && p[ 4 ] == 0x00 && p[ 5 ] == 0x00 && p[ 6 ] == 0x00 && p[ 7 ] == 0x00 );
1400 inline unsigned char *
decode_RLE(
unsigned char *psrc,
unsigned char *psrc_end,
unsigned char *pdst,
unsigned char *pdst_end,
bool from_little_endian =
true )
1402 if( psrc + 64 >= psrc_end )
1410 difference_type frame_offset[ 15 ] = {
1428 if( frame_offset[ 0 ] != 64 )
1430 frame_offset[ 0 ] = 64;
1434 while( n < number_of_segments && psrc < psrc_end && pdst < pdst_end )
1436 char *p =
reinterpret_cast< char *
>( psrc + frame_offset[ n ] );
1437 char *e =
reinterpret_cast< char *
>( n == number_of_segments - 1 ? psrc_end : psrc + frame_offset[ n + 1 ] );
1438 while( p < e && pdst < pdst_end )
1440 difference_type num = *p++;
1441 if( 0 <= num && num <= 127 )
1444 if( p + num <= e && pdst + num <= pdst_end )
1446 for( difference_type i = 0 ; i < num ; i++ )
1454 else if( -127 <= num && num <= -1 )
1457 if( p + 1 <= e && pdst + num <= pdst_end )
1459 for( difference_type i = 0 ; i < num ; i++ )
1474 #ifdef __DECODE_JPEG_COMPRESSION__
1475 static void JpegInitSource( j_decompress_ptr dinfo )
1479 static boolean JpegFillInputBuffer( j_decompress_ptr dinfo )
1484 static void JpegSkipInputData( j_decompress_ptr dinfo,
long num_bytes )
1486 jpeg_source_mgr &jpegSrcManager = *( dinfo->src );
1487 jpegSrcManager.next_input_byte += (size_t) num_bytes;
1488 jpegSrcManager.bytes_in_buffer -= (size_t) num_bytes;
1491 static void JpegTermSource( j_decompress_ptr dinfo )
1506 inline unsigned char *
decode_JPEG(
unsigned char *psrc,
unsigned char *psrc_end,
unsigned char *pdst,
unsigned char *pdst_end )
1508 #ifdef __DECODE_JPEG_COMPRESSION__
1509 difference_type compressedLen = psrc_end - psrc;
1510 if( compressedLen <= 0 )
1517 jpeg_decompress_struct dinfo;
1518 jpeg_error_mgr jerr;
1521 dinfo.err = jpeg_std_error( &jerr );
1522 jpeg_create_decompress( &dinfo );
1524 jpeg_source_mgr jpegSrcManager;
1525 jpegSrcManager.init_source = JpegInitSource;
1526 jpegSrcManager.fill_input_buffer = JpegFillInputBuffer;
1527 jpegSrcManager.skip_input_data = JpegSkipInputData;
1528 jpegSrcManager.resync_to_restart = jpeg_resync_to_restart;
1529 jpegSrcManager.term_source = JpegTermSource;
1530 jpegSrcManager.next_input_byte = psrc;
1531 jpegSrcManager.bytes_in_buffer = compressedLen;
1532 dinfo.src = &jpegSrcManager;
1534 jpeg_read_header( &dinfo, TRUE );
1537 jpeg_start_decompress( &dinfo );
1539 scanlen = dinfo.output_width * dinfo.output_components;
1541 JSAMPLE *buffer =
new JSAMPLE[ scanlen ];
1542 for( j = 0 ; j < dinfo.output_height ; j++ )
1544 bitmap[ 0 ] = &buffer[ 0 ];
1545 if( dinfo.output_scanline < dinfo.output_height ) jpeg_read_scanlines( &dinfo, bitmap, 1 );
1546 for( i = 0 ; i < dinfo.output_width ; i++ )
1548 for( c = 0 ; c < dinfo.output_components ; c++ )
1550 *pdst++ = buffer[ i * dinfo.output_components + c ];
1555 jpeg_finish_decompress(&dinfo);
1556 jpeg_destroy_decompress(&dinfo);
1600 unsigned char *pointer = element.
data;
1601 unsigned char *end_pointer = element.
data + element.
num_bytes;
1602 difference_type num_bytes = element.
num_bytes;
1603 difference_type frame_offset[ 16 ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1604 size_type number_of_fragments = 0;
1617 unsigned char *p = pointer;
1618 while( p < pointer + num_bytes && number_of_fragments < 16 )
1626 number_of_fragments = 1;
1632 pointer += num_bytes;
1633 if( pointer > end_pointer )
1639 unsigned char *buff =
new unsigned char[ dstBytes + 1 ];
1640 unsigned char *dst_pointer = buff;
1641 unsigned char *p = pointer;
1646 while( dst_pointer < buff + dstBytes && i < number_of_fragments && ret )
1648 p = pointer + frame_offset[ i ];
1661 if( dst_pointer == NULL )
1670 memcpy( dst_pointer, p, num_bytes );
1671 dst_pointer += num_bytes;
1682 element.
copy( buff, dst_pointer - buff );
1704 #endif // __INCLUDE_MIST_DICOM_INFO__