@@ -47,6 +47,8 @@ limitations under the License.
4747#include " tensorflow/core/framework/op_kernel.h"
4848#include " tensorflow/core/framework/shape_inference.h"
4949#include " tensorflow/core/framework/types.h"
50+ #include " absl/strings/str_split.h"
51+ #include " absl/strings/numbers.h"
5052
5153// clang-format on
5254
@@ -319,7 +321,6 @@ class DecodeDICOMDataOp : public OpKernel {
319321
320322 const Tensor *in_tags;
321323 OP_REQUIRES_OK (context, context->input (" tags" , &in_tags));
322- auto in_tags_flat = in_tags->flat <uint32>();
323324
324325 // Create an output tensor
325326 Tensor *out_tag_values = NULL ;
@@ -337,26 +338,128 @@ class DecodeDICOMDataOp : public OpKernel {
337338 OFCondition cond = dfile.read (dataBuf);
338339 dfile.transferEnd ();
339340
340- DcmDataset *dset = dfile.getDataset ();
341+ DcmItem *item = static_cast <DcmItem *>( dfile.getDataset () );
341342 DcmMetaInfo *meta = dfile.getMetaInfo ();
342343
343- for (unsigned int tag_i = 0 ; tag_i < in_tags_flat.size (); ++tag_i) {
344- uint32 tag_value = in_tags_flat (tag_i);
345- uint16 tag_group_number = (uint16)((tag_value & 0xFFFF0000 ) >> 16 );
346- uint16 tag_element_number = (uint16)((tag_value & 0x0000FFFF ) >> 0 );
347- DcmTag tag (tag_group_number, tag_element_number);
344+ for (int64 tag_i = 0 ; tag_i < in_tags->NumElements (); ++tag_i) {
345+ DcmTag tag;
346+ if (in_tags->dtype () == DT_STRING) {
347+ uint16 tag_group_number, tag_element_number;
348+ const auto &in_tags_flat = in_tags->flat <tstring>();
349+ const tstring &tag_sequence = in_tags_flat (tag_i);
350+ std::vector<absl::string_view> tag_sequence_views;
351+ if (tag_sequence[0 ] == ' [' &&
352+ tag_sequence[tag_sequence.size () - 1 ] == ' ]' ) {
353+ tag_sequence_views =
354+ absl::StrSplit (absl::string_view (tag_sequence.data () + 1 ,
355+ tag_sequence.size () - 2 ),
356+ " ][" );
357+ } else {
358+ tag_sequence_views.push_back (
359+ absl::string_view (tag_sequence.data (), tag_sequence.size ()));
360+ }
361+
362+ OP_REQUIRES (
363+ context, (tag_sequence_views.size () % 2 == 1 ),
364+ errors::InvalidArgument (
365+ " tag sequences should have 2xn + 1 elements, received: " ,
366+ tag_sequence_views.size ()));
367+
368+ // Walk through before the last element of value
369+ for (size_t i = 0 ; i < tag_sequence_views.size () - 1 ; i += 2 ) {
370+ absl::string_view tag_value (tag_sequence_views[i].data (),
371+ tag_sequence_views[i].size ());
372+ OP_REQUIRES_OK (context, GetDcmTag (tag_value, &tag));
373+
374+ absl::string_view number_value (tag_sequence_views[i + 1 ].data (),
375+ tag_sequence_views[i + 1 ].size ());
376+ uint32 number = 0 ;
377+ OP_REQUIRES (
378+ context,
379+ absl::numbers_internal::safe_strtou32_base (number_value, &number,
380+ 0 ),
381+ errors::InvalidArgument (" number should be an integer, received " ,
382+ number_value));
383+
384+ DcmItem *lookup;
385+ OFCondition condition =
386+ item->findAndGetSequenceItem (tag, lookup, number);
387+ OP_REQUIRES (context, condition.good (),
388+ errors::InvalidArgument (" item findAndGetSequenceItem: " ,
389+ condition.text ()));
390+ item = lookup;
391+ }
392+
393+ // The last element of value
394+ absl::string_view tag_value (tag_sequence_views.back ().data (),
395+ tag_sequence_views.back ().size ());
396+ OP_REQUIRES_OK (context, GetDcmTag (tag_value, &tag));
397+ } else {
398+ const auto &in_tags_flat = in_tags->flat <uint32>();
399+ uint32 tag_value = in_tags_flat (tag_i);
400+ OP_REQUIRES_OK (context, GetDcmTag (tag_value, &tag));
401+ }
348402
349403 OFString val;
350- if (dset->tagExists (tag)) {
351- dset->findAndGetOFStringArray (tag, val);
404+ if (item->tagExists (tag)) {
405+ OFCondition condition = item->findAndGetOFStringArray (tag, val);
406+ OP_REQUIRES (context, condition.good (),
407+ errors::InvalidArgument (" item findAndGetOFStringArray: " ,
408+ condition.text ()));
352409 } else if (meta->tagExists (tag)) {
353- meta->findAndGetOFStringArray (tag, val);
410+ OFCondition condition = meta->findAndGetOFStringArray (tag, val);
411+ OP_REQUIRES (context, condition.good (),
412+ errors::InvalidArgument (" meta findAndGetOFStringArray: " ,
413+ condition.text ()));
354414 } else {
355415 val = OFString (" " );
356416 }
357417 out_tag_values_flat (tag_i) = val.c_str ();
358418 }
359419 }
420+
421+ private:
422+ Status GetDcmTag (const uint32 tag_value, DcmTag *tag) {
423+ uint16 tag_group_number = (uint16)((tag_value & 0xFFFF0000 ) >> 16 );
424+ uint16 tag_element_number = (uint16)((tag_value & 0x0000FFFF ) >> 0 );
425+ *tag = DcmTag (tag_group_number, tag_element_number);
426+ return Status::OK ();
427+ }
428+ Status GetDcmTag (const absl::string_view tag_value, DcmTag *tag) {
429+ std::vector<absl::string_view> number_views =
430+ absl::StrSplit (tag_value, ' ,' );
431+ if (number_views.size () != 2 ) {
432+ return errors::InvalidArgument (
433+ " sequence should consist of group and "
434+ " element numbers, received " ,
435+ tag_value);
436+ }
437+ uint32 number = 0 ;
438+ if (!absl::numbers_internal::safe_strtou32_base (number_views[0 ], &number,
439+ 0 )) {
440+ return errors::InvalidArgument (
441+ " group number should be an integer, received " , number_views[0 ]);
442+ }
443+ if (number > std::numeric_limits<short >::max ()) {
444+ return errors::InvalidArgument (" group number should be uint16, received " ,
445+ number_views[0 ]);
446+ }
447+ uint16 tag_group_number = number;
448+
449+ if (!absl::numbers_internal::safe_strtou32_base (number_views[1 ], &number,
450+ 0 )) {
451+ return errors::InvalidArgument (
452+ " element number should be an integer, received " , number_views[1 ]);
453+ }
454+ if (number > std::numeric_limits<short >::max ()) {
455+ return errors::InvalidArgument (
456+ " element number should be uint16, received " , number_views[1 ]);
457+ }
458+ uint16 tag_element_number = number;
459+
460+ *tag = DcmTag (tag_group_number, tag_element_number);
461+ return Status::OK ();
462+ }
360463};
361464
362465// Register the CPU kernels.
0 commit comments