@@ -53,28 +53,60 @@ def _setup_htj2k_decode_params(color_spec=None):
5353 return decode_params
5454
5555
56- def _setup_htj2k_encode_params (num_resolutions : int = 6 , code_block_size : tuple = (64 , 64 )):
56+ def _setup_htj2k_encode_params (
57+ num_resolutions : int = 6 ,
58+ code_block_size : tuple = (64 , 64 ),
59+ progression_order : str = "RPCL"
60+ ):
5761 """
5862 Create nvimgcodec encoding parameters for HTJ2K lossless compression.
5963
6064 Args:
6165 num_resolutions: Number of wavelet decomposition levels
6266 code_block_size: Code block size as (height, width) tuple
67+ progression_order: Progression order for encoding. Must be one of:
68+ - "LRCP": Layer-Resolution-Component-Position (quality scalability)
69+ - "RLCP": Resolution-Layer-Component-Position (resolution scalability)
70+ - "RPCL": Resolution-Position-Component-Layer (progressive by resolution)
71+ - "PCRL": Position-Component-Resolution-Layer (progressive by spatial area)
72+ - "CPRL": Component-Position-Resolution-Layer (component scalability)
6373
6474 Returns:
6575 tuple: (encode_params, target_transfer_syntax)
76+
77+ Raises:
78+ ValueError: If progression_order is not one of the valid values
6679 """
6780 from nvidia import nvimgcodec
6881
69- target_transfer_syntax = "1.2.840.10008.1.2.4.202" # HTJ2K with RPCL Options (Lossless)
82+ # Valid progression orders and their mappings
83+ VALID_PROG_ORDERS = {
84+ "LRCP" : (nvimgcodec .Jpeg2kProgOrder .LRCP , "1.2.840.10008.1.2.4.201" ), # HTJ2K (Lossless Only)
85+ "RLCP" : (nvimgcodec .Jpeg2kProgOrder .RLCP , "1.2.840.10008.1.2.4.201" ), # HTJ2K (Lossless Only)
86+ "RPCL" : (nvimgcodec .Jpeg2kProgOrder .RPCL , "1.2.840.10008.1.2.4.202" ), # HTJ2K with RPCL Options
87+ "PCRL" : (nvimgcodec .Jpeg2kProgOrder .PCRL , "1.2.840.10008.1.2.4.201" ), # HTJ2K (Lossless Only)
88+ "CPRL" : (nvimgcodec .Jpeg2kProgOrder .CPRL , "1.2.840.10008.1.2.4.201" ), # HTJ2K (Lossless Only)
89+ }
90+
91+ # Validate progression order
92+ if progression_order not in VALID_PROG_ORDERS :
93+ valid_orders = ", " .join (f"'{ o } '" for o in VALID_PROG_ORDERS .keys ())
94+ raise ValueError (
95+ f"Invalid progression_order '{ progression_order } '. "
96+ f"Must be one of: { valid_orders } "
97+ )
98+
99+ # Get progression order enum and transfer syntax
100+ prog_order_enum , target_transfer_syntax = VALID_PROG_ORDERS [progression_order ]
101+
70102 quality_type = nvimgcodec .QualityType .LOSSLESS
71103
72104 # Configure JPEG2K encoding parameters
73105 jpeg2k_encode_params = nvimgcodec .Jpeg2kEncodeParams ()
74106 jpeg2k_encode_params .num_resolutions = num_resolutions
75107 jpeg2k_encode_params .code_block_size = code_block_size
76- jpeg2k_encode_params .bitstream_type = nvimgcodec .Jpeg2kBitstreamType .JP2
77- jpeg2k_encode_params .prog_order = nvimgcodec . Jpeg2kProgOrder . LRCP
108+ jpeg2k_encode_params .bitstream_type = nvimgcodec .Jpeg2kBitstreamType .J2K
109+ jpeg2k_encode_params .prog_order = prog_order_enum
78110 jpeg2k_encode_params .ht = True # Enable High Throughput mode
79111
80112 encode_params = nvimgcodec .EncodeParams (
@@ -223,6 +255,7 @@ def transcode_dicom_to_htj2k(
223255 output_dir : str = None ,
224256 num_resolutions : int = 6 ,
225257 code_block_size : tuple = (64 , 64 ),
258+ progression_order : str = "RPCL" ,
226259 max_batch_size : int = 256 ,
227260 add_basic_offset_table : bool = True ,
228261) -> str :
@@ -262,6 +295,13 @@ def transcode_dicom_to_htj2k(
262295 Higher values = better compression but slower encoding
263296 code_block_size: Code block size as (height, width) tuple (default: (64, 64))
264297 Must be powers of 2. Common values: (32,32), (64,64), (128,128)
298+ progression_order: Progression order for HTJ2K encoding (default: "RPCL")
299+ Must be one of: "LRCP", "RLCP", "RPCL", "PCRL", "CPRL"
300+ - "LRCP": Layer-Resolution-Component-Position (quality scalability)
301+ - "RLCP": Resolution-Layer-Component-Position (resolution scalability)
302+ - "RPCL": Resolution-Position-Component-Layer (progressive by resolution)
303+ - "PCRL": Position-Component-Resolution-Layer (progressive by spatial area)
304+ - "CPRL": Component-Position-Resolution-Layer (component scalability)
265305 max_batch_size: Maximum number of DICOM files to process in each batch (default: 256)
266306 Lower values reduce memory usage, higher values may improve speed
267307 add_basic_offset_table: If True, creates Basic Offset Table for multi-frame DICOMs (default: True)
@@ -275,6 +315,7 @@ def transcode_dicom_to_htj2k(
275315 ImportError: If nvidia-nvimgcodec is not available
276316 ValueError: If input directory doesn't exist or contains no valid DICOM files
277317 ValueError: If DICOM files are missing required attributes (TransferSyntaxUID, PixelData)
318+ ValueError: If progression_order is not one of: "LRCP", "RLCP", "RPCL", "PCRL", "CPRL"
278319
279320 Example:
280321 >>> # Basic usage with default settings
@@ -345,7 +386,8 @@ def transcode_dicom_to_htj2k(
345386 # Setup HTJ2K encoding parameters
346387 encode_params , target_transfer_syntax = _setup_htj2k_encode_params (
347388 num_resolutions = num_resolutions ,
348- code_block_size = code_block_size
389+ code_block_size = code_block_size ,
390+ progression_order = progression_order
349391 )
350392 # Note: decode_params is created per-PhotometricInterpretation group in the batch processing
351393 logger .info ("Using lossless HTJ2K compression" )
@@ -542,6 +584,7 @@ def convert_single_frame_dicom_series_to_multiframe(
542584 convert_to_htj2k : bool = False ,
543585 num_resolutions : int = 6 ,
544586 code_block_size : tuple = (64 , 64 ),
587+ progression_order : str = "RPCL" ,
545588 add_basic_offset_table : bool = True ,
546589) -> str :
547590 """
@@ -567,6 +610,13 @@ def convert_single_frame_dicom_series_to_multiframe(
567610 convert_to_htj2k: If True, convert frames to HTJ2K compression; if False, use uncompressed format (default: False)
568611 num_resolutions: Number of wavelet decomposition levels (default: 6, only used if convert_to_htj2k=True)
569612 code_block_size: Code block size as (height, width) tuple (default: (64, 64), only used if convert_to_htj2k=True)
613+ progression_order: Progression order for HTJ2K encoding (default: "RPCL", only used if convert_to_htj2k=True)
614+ Must be one of: "LRCP", "RLCP", "RPCL", "PCRL", "CPRL"
615+ - "LRCP": Layer-Resolution-Component-Position (quality scalability)
616+ - "RLCP": Resolution-Layer-Component-Position (resolution scalability)
617+ - "RPCL": Resolution-Position-Component-Layer (progressive by resolution)
618+ - "PCRL": Position-Component-Resolution-Layer (progressive by spatial area)
619+ - "CPRL": Component-Position-Resolution-Layer (component scalability)
570620 add_basic_offset_table: If True, creates Basic Offset Table for multi-frame DICOMs (default: True)
571621 BOT enables O(1) frame access without parsing entire pixel data stream
572622 Per DICOM Part 5 Section A.4. Only affects multi-frame files.
@@ -577,6 +627,7 @@ def convert_single_frame_dicom_series_to_multiframe(
577627 Raises:
578628 ImportError: If nvidia-nvimgcodec is not available and convert_to_htj2k=True
579629 ValueError: If input directory doesn't exist or contains no valid DICOM files
630+ ValueError: If progression_order is not one of: "LRCP", "RLCP", "RPCL", "PCRL", "CPRL"
580631
581632 Example:
582633 >>> # Combine series without HTJ2K conversion (uncompressed)
@@ -693,7 +744,8 @@ def convert_single_frame_dicom_series_to_multiframe(
693744 # Setup HTJ2K encoding parameters
694745 encode_params , target_transfer_syntax = _setup_htj2k_encode_params (
695746 num_resolutions = num_resolutions ,
696- code_block_size = code_block_size
747+ code_block_size = code_block_size ,
748+ progression_order = progression_order
697749 )
698750 # Note: decode_params is created per-series based on PhotometricInterpretation
699751 logger .info ("HTJ2K conversion enabled" )
0 commit comments