1212#define strdup (v ) _strdup(v)
1313#endif
1414
15- #include <assert.h>
1615#include <ctype.h>
1716#include <stdbool.h>
1817#include <stdlib.h>
@@ -51,19 +50,26 @@ struct _DcmFilehandle {
5150 // image properties we need to track
5251 uint32_t frame_width ;
5352 uint32_t frame_height ;
54- uint32_t frames_across ;
5553 uint32_t num_frames ;
5654 struct PixelDescription desc ;
5755 DcmLayout layout ;
5856
59- // both zero-indexed and length num_frames
60- uint32_t * frame_index ;
57+ // zero-indexed and length num_frames
6158 int64_t * offset_table ;
6259
60+ // frames form a grid of tiles, there can be more tiles than frames in
61+ // sparse mode
62+ uint32_t tiles_across ;
63+ uint32_t tiles_down ;
64+ uint32_t num_tiles ;
65+
66+ // zero-indexed and of length num_tiles
67+ uint32_t * frame_index ;
68+
6369 // the last top level tag the scanner saw
6470 uint32_t last_tag ;
6571
66- // used to count frames as we scan perframefunctionalgroup
72+ // used to count frames as we scan per frame functional group sequence
6773 uint32_t frame_number ;
6874 int32_t column_position ;
6975 int32_t row_position ;
@@ -320,11 +326,13 @@ static bool get_frame_size(DcmError **error,
320326}
321327
322328
323- static bool get_frames_across (DcmError * * error ,
324- const DcmDataSet * metadata ,
325- uint32_t * frames_across )
329+ static bool get_tiles (DcmError * * error ,
330+ const DcmDataSet * metadata ,
331+ uint32_t * tiles_across ,
332+ uint32_t * tiles_down )
326333{
327334 int64_t width ;
335+ int64_t height ;
328336 uint32_t frame_width ;
329337 uint32_t frame_height ;
330338
@@ -337,7 +345,13 @@ static bool get_frames_across(DcmError **error,
337345 width = frame_width ;
338346 (void ) get_tag_int (NULL , metadata , "TotalPixelMatrixColumns" , & width );
339347
340- * frames_across = width / frame_width + !!(width % frame_width );
348+ // TotalPixelMatrixColumns is optional and defaults to Columns, ie. one
349+ // frame across
350+ height = frame_width ;
351+ (void ) get_tag_int (NULL , metadata , "TotalPixelMatrixRows" , & height );
352+
353+ * tiles_across = width / frame_width + !!(width % frame_width );
354+ * tiles_down = height / frame_height + !!(height % frame_height );
341355
342356 return true;
343357}
@@ -819,17 +833,20 @@ const DcmDataSet *dcm_filehandle_get_metadata_subset(DcmError **error,
819833 meta ,
820834 & filehandle -> frame_width ,
821835 & filehandle -> frame_height ) ||
822- !get_frames_across (error , meta , & filehandle -> frames_across ) ||
823836 !get_num_frames (error , meta , & filehandle -> num_frames ) ||
837+ !get_tiles (error , meta ,
838+ & filehandle -> tiles_across , & filehandle -> tiles_down ) ||
824839 !set_pixel_description (error , meta , & filehandle -> desc )) {
825840 dcm_dataset_destroy (meta );
826841 return false;
827842 }
843+ filehandle -> num_tiles = filehandle -> tiles_across *
844+ filehandle -> tiles_down ;
828845
829846 // we support sparse and full frame layout, defaulting to full if
830847 // no type is specified
831848 //
832- // we flip to SPARSE if there's a PerFrameFunctionalGroupsSequence
849+ // we flip to SPARSE if there's a per frame functional group sequence
833850 // containing frame positions, see below
834851 const char * type ;
835852 if (get_tag_str (NULL , meta , "DimensionOrganizationType" , & type )) {
@@ -886,12 +903,12 @@ static bool parse_frame_index_sequence_end(DcmError **error,
886903
887904 DcmFilehandle * filehandle = (DcmFilehandle * ) client ;
888905
889- // have we seen a valid pair of frame positions
906+ // have we seen a valid pair of tile positions
890907 if (tag == TAG_PLANE_POSITION_SLIDE_SEQUENCE &&
891908 filehandle -> column_position != -1 &&
892909 filehandle -> row_position != -1 ) {
893- // we don't support fractional frame positioning ... they must be
894- // exactly aligned on frame boundaries
910+ // we don't support fractional tile positioning ... they must be
911+ // exactly aligned on tile boundaries
895912 if ((filehandle -> column_position - 1 ) % filehandle -> frame_width != 0 ||
896913 (filehandle -> row_position - 1 ) % filehandle -> frame_height != 0 ) {
897914 dcm_error_set (error , DCM_ERROR_CODE_PARSE ,
@@ -900,15 +917,15 @@ static bool parse_frame_index_sequence_end(DcmError **error,
900917 return false;
901918 }
902919
903- // map the position of the frame to the frame number
920+ // map the position of the tile to the frame number
904921 int col = (filehandle -> column_position - 1 ) / filehandle -> frame_width ;
905922 int row = (filehandle -> row_position - 1 ) / filehandle -> frame_height ;
906- uint32_t index = col + row * filehandle -> frames_across ;
907- if (index < filehandle -> num_frames ) {
923+ uint32_t index = col + row * filehandle -> tiles_across ;
924+ if (index < filehandle -> num_tiles ) {
908925 filehandle -> frame_index [index ] = filehandle -> frame_number ;
909926
910- // we have something meaningful in PerFrameFunctionalGroupsSequence,
911- // so we must display in SPARSE mode
927+ // we have something meaningful in per frame functional group
928+ // sequence, so we must display in SPARSE mode
912929 filehandle -> layout = DCM_LAYOUT_SPARSE ;
913930 }
914931
@@ -984,14 +1001,14 @@ static bool read_frame_index(DcmError **error,
9841001 };
9851002
9861003 filehandle -> frame_index = DCM_NEW_ARRAY (error ,
987- filehandle -> num_frames ,
1004+ filehandle -> num_tiles ,
9881005 uint32_t );
9891006 if (filehandle -> frame_index == NULL ) {
9901007 return false;
9911008 }
9921009
9931010 // we may not have all frames ... set to missing initially
994- for (uint32_t i = 0 ; i < filehandle -> num_frames ; i ++ ) {
1011+ for (uint32_t i = 0 ; i < filehandle -> num_tiles ; i ++ ) {
9951012 filehandle -> frame_index [i ] = 0xffffffff ;
9961013 }
9971014
@@ -1204,24 +1221,17 @@ DcmFrame *dcm_filehandle_read_frame_position(DcmError **error,
12041221 return NULL ;
12051222 }
12061223
1207- if (column >= filehandle -> frames_across ) {
1208- dcm_error_set (error , DCM_ERROR_CODE_PARSE ,
1209- "Reading Frame position failed" ,
1210- "Column must be less than %u" ,
1211- filehandle -> frames_across );
1212- return NULL ;
1213- }
1214-
1215- uint32_t index = column + row * filehandle -> frames_across ;
1216-
1217- if (index >= filehandle -> num_frames ) {
1224+ if (column >= filehandle -> tiles_across ||
1225+ row >= filehandle -> tiles_down ) {
12181226 dcm_error_set (error , DCM_ERROR_CODE_PARSE ,
12191227 "Reading Frame position failed" ,
1220- "Row must be less than %u" ,
1221- filehandle -> num_frames / filehandle -> frames_across );
1228+ "Column and row must be less than %u, %u" ,
1229+ filehandle -> tiles_across ,
1230+ filehandle -> tiles_down );
12221231 return NULL ;
12231232 }
12241233
1234+ uint32_t index = column + row * filehandle -> tiles_across ;
12251235 if (filehandle -> layout == DCM_LAYOUT_SPARSE ) {
12261236 index = filehandle -> frame_index [index ];
12271237 if (index == 0xffffffff ) {
0 commit comments