diff --git a/CHANGELOG.md b/CHANGELOG.md index fc802df..81e66af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.3.0, date tbd + +* add dcm_filehandle_find_frame_number(), deprecate + dcm_filehandle_get_frame_number() [jcupitt] +* add DCM_DEPRECATED() macro [jcupitt] +* don't format ignored errors for debug log if logging is disabled [bgilbert] + ## 1.2.1, 28/04/2026 * add support for encapsulated pixel data reading [weanti] diff --git a/include/dicom/dicom.h b/include/dicom/dicom.h index 8dedf0d..92534d8 100644 --- a/include/dicom/dicom.h +++ b/include/dicom/dicom.h @@ -20,6 +20,16 @@ #define DCM_EXTERN __attribute__((visibility("default"))) extern #endif +#ifndef BUILDING_LIBDICOM +#if defined(_MSC_VER) +#define DCM_DEPRECATED(MSG) __declspec(deprecated(MSG)) +#elif defined(__GNUC__) +#define DCM_DEPRECATED(MSG) __attribute__((deprecated(MSG))) +#endif +#else +#define DCM_DEPRECATED(MSG) +#endif + /** * Maximum number of characters in values with Value Representation AE. */ @@ -124,13 +134,7 @@ typedef struct _DcmSequence DcmSequence; * .. deprecated:: 1.1.0 * Calling this function is no longer necessary. */ -#ifndef BUILDING_LIBDICOM -#if defined(_MSC_VER) -__declspec(deprecated("dcm_init() no longer needs to be called")) -#elif defined(__GNUC__) -__attribute__((deprecated("dcm_init() no longer needs to be called"))) -#endif -#endif +DCM_DEPRECATED("dcm_init() no longer needs to be called") DCM_EXTERN void dcm_init(void); @@ -1777,21 +1781,54 @@ DcmFrame *dcm_filehandle_read_frame(DcmError **error, DcmFilehandle *filehandle, uint32_t frame_number); +/** + * Find the frame number at a position. + * + * Given a tile row and column, find the number of the frame that should be + * displayed at that position, taking into account any frame-positioning + * metadata. + * + * If no frame is available at that position, set frame_number to 0. + * + * :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, or 0 for no frame + * + * :return: true on success, false for error + */ +DCM_EXTERN +bool dcm_filehandle_find_frame_number(DcmError **error, + DcmFilehandle *filehandle, + uint32_t column, + uint32_t row, + uint32_t *frame_number); + /** * Get the frame number at a position. * + * Note: this function is deprecated, please use + * :c:func:`dcm_filehandle_find_frame_number()` instead. + * * 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. * + * If no frame is available, return false and set the error + * :c:enum:`DCM_ERROR_CODE_MISSING_FRAME`. + * + * frame_number may be NULL. + * * :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 + * :return: true on success, false for error or no frame available */ +DCM_DEPRECATED("deprecated for dcm_filehandle_find_frame_number()") DCM_EXTERN bool dcm_filehandle_get_frame_number(DcmError **error, DcmFilehandle *filehandle, diff --git a/meson.build b/meson.build index 33ec4f1..ad0bef8 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,7 @@ project( ], license : 'MIT', meson_version : '>=0.55', - version : '1.2.1', + version : '1.3.0', ) if not meson.is_subproject() meson.add_dist_script('scripts/dist.py') @@ -34,8 +34,8 @@ endif # 2. Backward-compatible ABI change: bump minor, reset patch # 3. Other, eg. bugfix: bump patch abi_version_major = 1 -abi_version_minor = 2 -abi_version_patch = 1 +abi_version_minor = 3 +abi_version_patch = 0 abi_version = '@0@.@1@.@2@'.format( abi_version_major, diff --git a/src/dicom-file.c b/src/dicom-file.c index 59d3f4f..48647f3 100644 --- a/src/dicom-file.c +++ b/src/dicom-file.c @@ -1405,13 +1405,13 @@ DcmFrame *dcm_filehandle_read_frame(DcmError **error, } -bool dcm_filehandle_get_frame_number(DcmError **error, - DcmFilehandle *filehandle, - uint32_t column, - uint32_t row, - uint32_t *frame_number) +bool dcm_filehandle_find_frame_number(DcmError **error, + DcmFilehandle *filehandle, + uint32_t column, + uint32_t row, + uint32_t *frame_number) { - dcm_log_debug("Get frame number at (%u, %u)", column, row); + dcm_log_debug("Find frame number for tile (%u, %u)", column, row); if (!dcm_filehandle_prepare_read_frame(error, filehandle)) { return false; @@ -1431,25 +1431,51 @@ bool dcm_filehandle_get_frame_number(DcmError **error, if (filehandle->layout == DCM_LAYOUT_SPARSE) { index = filehandle->frame_index[index]; if (index == 0xffffffff) { - dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME, - "no frame", - "no frame at position (%u, %u)", column, row); - return false; + // missing frame + *frame_number = 0; + } + else { + *frame_number = (uint32_t) (index + 1); } } 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; + // missing frame + *frame_number = 0; + } + else { + *frame_number = (uint32_t) (index + 1); } } - // frame numbers are from 1, and are always uint32 + return true; +} + + +/* Deprecated function, only here for compatibility with libdicom 1.2. + */ +bool dcm_filehandle_get_frame_number(DcmError **error, + DcmFilehandle *filehandle, + uint32_t column, + uint32_t row, + uint32_t *frame_number) +{ + uint32_t n; + + if (!dcm_filehandle_find_frame_number(error, filehandle, column, row, &n)) { + return false; + } + + if (n == 0) { + dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME, + "no frame", + "no frame at position (%u, %u)", column, row); + return false; + } + if (frame_number) - *frame_number = (uint32_t) (index + 1); + *frame_number = n; return true; } @@ -1463,11 +1489,18 @@ DcmFrame *dcm_filehandle_read_frame_position(DcmError **error, 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)) { + if (!dcm_filehandle_find_frame_number(error, filehandle, + column, row, &frame_number)) { return NULL; } + if (frame_number == 0) { + dcm_error_set(error, DCM_ERROR_CODE_MISSING_FRAME, + "no frame", + "no frame at position (%u, %u)", column, row); + return false; + } + return dcm_filehandle_read_frame(error, filehandle, frame_number); }