Skip to content

Commit c850ee2

Browse files
committed
Merge branch 'main' into revise-unknown
2 parents 6797374 + 95bc8db commit c850ee2

File tree

4 files changed

+90
-12
lines changed

4 files changed

+90
-12
lines changed

.github/workflows/run_unit_tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ jobs:
7878
DEBUG_DICT=1 meson compile -C builddir
7979
$sudo meson install -C builddir
8080
81+
- name: Rebuild the shared library cache
82+
if: startsWith(matrix.os, 'ubuntu')
83+
run: sudo ldconfig
84+
8185
- name: Run unit tests
8286
# Don't run tests for private copy of Check
8387
run: meson test -C builddir --suite libdicom

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* better handling of implicit mode in dcm-dump [jcupitt]
66
* better handling of trailing spaces in string values [y-baba-isb]
77
* much faster read of files with an EOT but no FGS [pcram-techcyte]
8+
* add `dcm_filehandle_get_frame_number()` [jcupitt]
9+
* add DICOM catenation support [jcupitt]
810

911
## 1.1.0, 28/3/24
1012

include/dicom/dicom.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1767,7 +1767,7 @@ bool dcm_filehandle_prepare_read_frame(DcmError **error,
17671767
*
17681768
* :param error: Pointer to error object
17691769
* :param filehandle: File
1770-
* :param index: One-based frame number
1770+
* :param frame_number: One-based frame number
17711771
*
17721772
* :return: Frame
17731773
*/
@@ -1776,6 +1776,28 @@ DcmFrame *dcm_filehandle_read_frame(DcmError **error,
17761776
DcmFilehandle *filehandle,
17771777
uint32_t frame_number);
17781778

1779+
/**
1780+
* Get the frame number at a position.
1781+
*
1782+
* Given a tile row and column, get the number of the frame that should be
1783+
* displayed at that position, taking into account any frame-positioning
1784+
* metadata.
1785+
*
1786+
* :param error: Pointer to error object
1787+
* :param filehandle: File
1788+
* :param column: Column number, from 0
1789+
* :param row: Row number, from 0
1790+
* :param frame_number: Return one-based frame number
1791+
*
1792+
* :return: true on success, false for no frame available
1793+
*/
1794+
DCM_EXTERN
1795+
bool dcm_filehandle_get_frame_number(DcmError **error,
1796+
DcmFilehandle *filehandle,
1797+
uint32_t column,
1798+
uint32_t row,
1799+
uint32_t *frame_number);
1800+
17791801
/**
17801802
* Read the frame at a position in a File.
17811803
*

src/dicom-file.c

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct _DcmFilehandle {
5252
uint32_t frame_width;
5353
uint32_t frame_height;
5454
uint32_t num_frames;
55+
uint32_t frame_offset;
5556
struct PixelDescription desc;
5657
DcmLayout layout;
5758

@@ -313,6 +314,24 @@ static bool get_num_frames(DcmError **error,
313314
}
314315

315316

317+
static bool get_frame_offset(DcmError **error,
318+
const DcmDataSet *metadata,
319+
uint32_t *frame_offset)
320+
{
321+
// optional, defaults to 0
322+
int64_t value;
323+
if (!get_tag_int(error,
324+
metadata, "ConcatenationFrameOffsetNumber", &value)) {
325+
value = 0;
326+
}
327+
328+
// it's a uint32 in the DICOM file
329+
*frame_offset = (uint32_t) value;
330+
331+
return true;
332+
}
333+
334+
316335
static bool get_frame_size(DcmError **error,
317336
const DcmDataSet *metadata,
318337
uint32_t *frame_width,
@@ -868,6 +887,7 @@ const DcmDataSet *dcm_filehandle_get_metadata_subset(DcmError **error,
868887
&filehandle->frame_width,
869888
&filehandle->frame_height) ||
870889
!get_num_frames(error, meta, &filehandle->num_frames) ||
890+
!get_frame_offset(error, meta, &filehandle->frame_offset) ||
871891
!get_tiles(error, meta,
872892
&filehandle->tiles_across, &filehandle->tiles_down) ||
873893
!set_pixel_description(error, meta, &filehandle->desc)) {
@@ -1345,15 +1365,16 @@ DcmFrame *dcm_filehandle_read_frame(DcmError **error,
13451365
}
13461366

13471367

1348-
DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
1349-
DcmFilehandle *filehandle,
1350-
uint32_t column,
1351-
uint32_t row)
1368+
bool dcm_filehandle_get_frame_number(DcmError **error,
1369+
DcmFilehandle *filehandle,
1370+
uint32_t column,
1371+
uint32_t row,
1372+
uint32_t *frame_number)
13521373
{
1353-
dcm_log_debug("Read frame position (%u, %u)", column, row);
1374+
dcm_log_debug("Get frame number at (%u, %u)", column, row);
13541375

13551376
if (!dcm_filehandle_prepare_read_frame(error, filehandle)) {
1356-
return NULL;
1377+
return false;
13571378
}
13581379

13591380
if (column >= filehandle->tiles_across ||
@@ -1363,22 +1384,51 @@ DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
13631384
"column and Row must be less than %u, %u",
13641385
filehandle->tiles_across,
13651386
filehandle->tiles_down);
1366-
return NULL;
1387+
return false;
13671388
}
13681389

1369-
uint32_t index = column + row * filehandle->tiles_across;
1390+
int64_t index = column + row * filehandle->tiles_across;
13701391
if (filehandle->layout == DCM_LAYOUT_SPARSE) {
13711392
index = filehandle->frame_index[index];
13721393
if (index == 0xffffffff) {
13731394
dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME,
13741395
"no frame",
13751396
"no frame at position (%u, %u)", column, row);
1376-
return NULL;
1397+
return false;
1398+
}
1399+
} else {
1400+
// subtract the start of this file, for catenation support
1401+
index -= filehandle->frame_offset;
1402+
if (index < 0 || index >= (int64_t) filehandle->num_frames) {
1403+
dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME,
1404+
"no frame",
1405+
"no frame at position (%u, %u)", column, row);
1406+
return false;
13771407
}
13781408
}
13791409

1380-
// read_frame() numbers from 1
1381-
return dcm_filehandle_read_frame(error, filehandle, index + 1);
1410+
// frame numbers are from 1, and are always uint32
1411+
if (frame_number)
1412+
*frame_number = (uint32_t) (index + 1);
1413+
1414+
return true;
1415+
}
1416+
1417+
1418+
DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
1419+
DcmFilehandle *filehandle,
1420+
uint32_t column,
1421+
uint32_t row)
1422+
{
1423+
dcm_log_debug("Read frame position (%u, %u)", column, row);
1424+
1425+
uint32_t frame_number;
1426+
if (!dcm_filehandle_get_frame_number(error,
1427+
filehandle, column, row, &frame_number)) {
1428+
return NULL;
1429+
}
1430+
1431+
return dcm_filehandle_read_frame(error, filehandle, frame_number);
13821432
}
13831433

13841434

0 commit comments

Comments
 (0)