Skip to content

Commit

Permalink
add dicom catenation support
Browse files Browse the repository at this point in the history
- new API `dcm_filehandle_get_frame_number()` to read out an element of
  the postition->frame mapping
- add `frame_offset` support for `TILED_FULL` catenations
  • Loading branch information
jcupitt committed Dec 19, 2024
1 parent 7381e3e commit 52a2626
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* better handling of implicit mode in dcm-dump [jcupitt]
* better handling of trailing spaces in string values [y-baba-isb]
* much faster read of files with an EOT but no FGS [pcram-techcyte]
* add `dcm_filehandle_frame_position()` [jcupitt]
* add DICOM catenation support [jcupitt]

## 1.1.0, 28/3/24

Expand Down
24 changes: 23 additions & 1 deletion include/dicom/dicom.h
Original file line number Diff line number Diff line change
Expand Up @@ -1767,7 +1767,7 @@ bool dcm_filehandle_prepare_read_frame(DcmError **error,
*
* :param error: Pointer to error object
* :param filehandle: File
* :param index: One-based frame number
* :param frame_number: One-based frame number
*
* :return: Frame
*/
Expand All @@ -1776,6 +1776,28 @@ DcmFrame *dcm_filehandle_read_frame(DcmError **error,
DcmFilehandle *filehandle,
uint32_t frame_number);

/**
* Get the frame number at a position.
*
* Given a tile row and column, get the number of the frame that should be
* displayed at that position, taking into account any frame-positioning
* metadata.
*
* :param error: Pointer to error object
* :param filehandle: File
* :param column: Column number, from 0
* :param row: Row number, from 0
* :param frame_number: Return one-based frame number
*
* :return: true on success, false for no frame available
*/
DCM_EXTERN
bool dcm_filehandle_get_frame_number(DcmError **error,
DcmFilehandle *filehandle,
uint32_t column,
uint32_t row,
uint32_t *frame_number);

/**
* Read the frame at a position in a File.
*
Expand Down
72 changes: 60 additions & 12 deletions src/dicom-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct _DcmFilehandle {
uint32_t frame_width;
uint32_t frame_height;
uint32_t num_frames;
uint32_t frame_offset;
struct PixelDescription desc;
DcmLayout layout;

Expand Down Expand Up @@ -312,6 +313,23 @@ static bool get_num_frames(DcmError **error,
}


static bool get_frame_offset(DcmError **error,
const DcmDataSet *metadata,
uint32_t *frame_offset)
{
// optional, defaults to 0
int64_t value;
if (!get_tag_int(error,
metadata, "ConcatenationFrameOffsetNumber", &value)) {
value = 0;
}

*frame_offset = value;

return true;
}


static bool get_frame_size(DcmError **error,
const DcmDataSet *metadata,
uint32_t *frame_width,
Expand Down Expand Up @@ -867,6 +885,7 @@ const DcmDataSet *dcm_filehandle_get_metadata_subset(DcmError **error,
&filehandle->frame_width,
&filehandle->frame_height) ||
!get_num_frames(error, meta, &filehandle->num_frames) ||
!get_frame_offset(error, meta, &filehandle->frame_offset) ||
!get_tiles(error, meta,
&filehandle->tiles_across, &filehandle->tiles_down) ||
!set_pixel_description(error, meta, &filehandle->desc)) {
Expand Down Expand Up @@ -1344,15 +1363,16 @@ DcmFrame *dcm_filehandle_read_frame(DcmError **error,
}


DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
DcmFilehandle *filehandle,
uint32_t column,
uint32_t row)
bool dcm_filehandle_get_frame_number(DcmError **error,
DcmFilehandle *filehandle,
uint32_t column,
uint32_t row,
uint32_t *frame_number)
{
dcm_log_debug("Read frame position (%u, %u)", column, row);
dcm_log_debug("Get frame number at (%u, %u)", column, row);

if (!dcm_filehandle_prepare_read_frame(error, filehandle)) {
return NULL;
return false;
}

if (column >= filehandle->tiles_across ||
Expand All @@ -1362,22 +1382,50 @@ DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
"column and Row must be less than %u, %u",
filehandle->tiles_across,
filehandle->tiles_down);
return NULL;
return false;
}

uint32_t index = column + row * filehandle->tiles_across;
int64_t index = column + row * filehandle->tiles_across;
if (filehandle->layout == DCM_LAYOUT_SPARSE) {
index = filehandle->frame_index[index];
if (index == 0xffffffff) {
if (index == -1) {
dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME,
"no frame",
"no frame at position (%u, %u)", column, row);
return NULL;
return false;
}
} else {
// subtract the start of this file, for catenation support
index -= filehandle->frame_offset;
if (index < 0 || index >= (int64_t) filehandle->num_frames) {
dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME,
"no frame",
"no frame at position (%u, %u)", column, row);
return false;
}
}

// read_frame() numbers from 1
return dcm_filehandle_read_frame(error, filehandle, index + 1);
// frame numbers are from 1
*frame_number = index + 1;

return true;
}


DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
DcmFilehandle *filehandle,
uint32_t column,
uint32_t row)
{
dcm_log_debug("Read frame position (%u, %u)", column, row);

uint32_t frame_number;
if (!dcm_filehandle_get_frame_number(error,
filehandle, column, row, &frame_number)) {
return NULL;
}

return dcm_filehandle_read_frame(error, filehandle, frame_number);
}


Expand Down

0 comments on commit 52a2626

Please sign in to comment.