comparison OrthancServer/Internals/DicomImageDecoder.cpp @ 1903:554ec8422ec5

refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 05 Jan 2016 13:58:13 +0100
parents 8b0ee8d5e6d0
children 4be8accf8768
comparison
equal deleted inserted replaced
1902:8b0ee8d5e6d0 1903:554ec8422ec5
106 { 106 {
107 static const DicomTag DICOM_TAG_CONTENT(0x07a1, 0x100a); 107 static const DicomTag DICOM_TAG_CONTENT(0x07a1, 0x100a);
108 static const DicomTag DICOM_TAG_COMPRESSION_TYPE(0x07a1, 0x1011); 108 static const DicomTag DICOM_TAG_COMPRESSION_TYPE(0x07a1, 0x1011);
109 109
110 110
111 static bool IsJpegLossless(const DcmDataset& dataset)
112 {
113 // http://support.dcmtk.org/docs/dcxfer_8h-source.html
114 return (dataset.getOriginalXfer() == EXS_JPEGLSLossless ||
115 dataset.getOriginalXfer() == EXS_JPEGLSLossy);
116 }
117
118
119 static bool IsPsmctRle1(DcmDataset& dataset) 111 static bool IsPsmctRle1(DcmDataset& dataset)
120 { 112 {
121 DcmElement* e; 113 DcmElement* e;
122 char* c; 114 char* c;
123 115
326 << " photometric interpretation"; 318 << " photometric interpretation";
327 throw OrthancException(ErrorCode_NotImplemented); 319 throw OrthancException(ErrorCode_NotImplemented);
328 } 320 }
329 321
330 return new Image(format, info.GetWidth(), info.GetHeight()); 322 return new Image(format, info.GetWidth(), info.GetHeight());
331 }
332
333
334 bool DicomImageDecoder::IsUncompressedImage(const DcmDataset& dataset)
335 {
336 // http://support.dcmtk.org/docs/dcxfer_8h-source.html
337 return (dataset.getOriginalXfer() == EXS_Unknown ||
338 dataset.getOriginalXfer() == EXS_LittleEndianImplicit ||
339 dataset.getOriginalXfer() == EXS_BigEndianImplicit ||
340 dataset.getOriginalXfer() == EXS_LittleEndianExplicit ||
341 dataset.getOriginalXfer() == EXS_BigEndianExplicit);
342 } 323 }
343 324
344 325
345 template <typename PixelType> 326 template <typename PixelType>
346 static void CopyPixels(ImageAccessor& target, 327 static void CopyPixels(ImageAccessor& target,
374 } 355 }
375 } 356 }
376 357
377 358
378 ImageAccessor* DicomImageDecoder::DecodeUncompressedImage(DcmDataset& dataset, 359 ImageAccessor* DicomImageDecoder::DecodeUncompressedImage(DcmDataset& dataset,
379 unsigned int frame)
380 {
381 if (!IsUncompressedImage(dataset))
382 {
383 throw OrthancException(ErrorCode_BadParameterType);
384 }
385
386 return DecodeUncompressedImageInternal(dataset, frame);
387 }
388
389
390 ImageAccessor* DicomImageDecoder::DecodeUncompressedImageInternal(DcmDataset& dataset,
391 unsigned int frame) 360 unsigned int frame)
392 { 361 {
393 ImageSource source; 362 ImageSource source;
394 source.Setup(dataset, frame); 363 source.Setup(dataset, frame);
395 364
474 443
475 return target.release(); 444 return target.release();
476 } 445 }
477 446
478 447
479 #if ORTHANC_JPEG_LOSSLESS_ENABLED == 1 448 static DcmPixelSequence* GetPixelSequence(DcmDataset& dataset)
480 ImageAccessor* DicomImageDecoder::DecodeJpegLossless(DcmDataset& dataset, 449 {
481 unsigned int frame)
482 {
483 if (!IsJpegLossless(dataset))
484 {
485 throw OrthancException(ErrorCode_BadParameterType);
486 }
487
488 DcmElement *element = NULL; 450 DcmElement *element = NULL;
489 if (!dataset.findAndGetElement(ToDcmtkBridge::Convert(DICOM_TAG_PIXEL_DATA), element).good()) 451 if (!dataset.findAndGetElement(ToDcmtkBridge::Convert(DICOM_TAG_PIXEL_DATA), element).good())
490 { 452 {
491 throw OrthancException(ErrorCode_BadFileFormat); 453 throw OrthancException(ErrorCode_BadFileFormat);
492 } 454 }
493 455
494 DcmPixelData& pixelData = dynamic_cast<DcmPixelData&>(*element); 456 DcmPixelData& pixelData = dynamic_cast<DcmPixelData&>(*element);
495 DcmPixelSequence* pixelSequence = NULL; 457 DcmPixelSequence* pixelSequence = NULL;
496 if (!pixelData.getEncapsulatedRepresentation 458 if (!pixelData.getEncapsulatedRepresentation
497 (dataset.getOriginalXfer(), NULL, pixelSequence).good()) 459 (dataset.getOriginalXfer(), NULL, pixelSequence).good() ||
460 pixelSequence == NULL)
498 { 461 {
499 throw OrthancException(ErrorCode_BadFileFormat); 462 throw OrthancException(ErrorCode_BadFileFormat);
500 } 463 }
501 464
502 std::auto_ptr<ImageAccessor> target(CreateImage(dataset)); 465 return pixelSequence;
503 466 }
504 /** 467
505 * The "DJLSLosslessDecoder" and "DJLSNearLosslessDecoder" in DCMTK 468
506 * are exactly the same, except for the "supportedTransferSyntax()" 469 static ImageAccessor* ApplyCodec(const DcmCodec& codec,
507 * virtual function. 470 const DcmCodecParameter& parameters,
508 * http://support.dcmtk.org/docs/classDJLSDecoderBase.html 471 DcmDataset& dataset,
509 **/ 472 unsigned int frame)
510 473 {
511 DJLSLosslessDecoder decoder; DJLSCodecParameter parameters; 474 std::auto_ptr<ImageAccessor> target(DicomImageDecoder::CreateImage(dataset));
512 //DJLSNearLosslessDecoder decoder; DJLSCodecParameter parameters;
513 475
514 Uint32 startFragment = 0; // Default 476 Uint32 startFragment = 0; // Default
515 OFString decompressedColorModel; // Out 477 OFString decompressedColorModel; // Out
516 DJ_RPLossless representationParameter; 478 DJ_RPLossless representationParameter;
517 OFCondition c = decoder.decodeFrame(&representationParameter, pixelSequence, &parameters, 479 OFCondition c = codec.decodeFrame(&representationParameter, GetPixelSequence(dataset), &parameters,
518 &dataset, frame, startFragment, target->GetBuffer(), 480 &dataset, frame, startFragment, target->GetBuffer(),
519 target->GetSize(), decompressedColorModel); 481 target->GetSize(), decompressedColorModel);
520 482
521 if (!c.good()) 483 if (c.good())
522 { 484 {
523 throw OrthancException(ErrorCode_InternalError); 485 return target.release();
524 } 486 }
525 487 else
526 return target.release(); 488 {
527 } 489 LOG(ERROR) << "Cannot decode an image";
528 #endif 490 throw OrthancException(ErrorCode_BadFileFormat);
529 491 }
530 492 }
531 493
532 494
533 ImageAccessor* DicomImageDecoder::Decode(ParsedDicomFile& dicom, 495 ImageAccessor* DicomImageDecoder::Decode(ParsedDicomFile& dicom,
534 unsigned int frame) 496 unsigned int frame)
535 { 497 {
536 DcmDataset& dataset = *dicom.GetDcmtkObject().getDataset(); 498 DcmFileFormat& ff = dicom.GetDcmtkObject();
537 499 DcmDataset& dataset = *ff.getDataset();
538 if (IsUncompressedImage(dataset)) 500
501 /**
502 * Deal with uncompressed, raw images.
503 * http://support.dcmtk.org/docs/dcxfer_8h-source.html
504 **/
505 if (dataset.getOriginalXfer() == EXS_Unknown ||
506 dataset.getOriginalXfer() == EXS_LittleEndianImplicit ||
507 dataset.getOriginalXfer() == EXS_BigEndianImplicit ||
508 dataset.getOriginalXfer() == EXS_LittleEndianExplicit ||
509 dataset.getOriginalXfer() == EXS_BigEndianExplicit)
539 { 510 {
540 return DecodeUncompressedImage(dataset, frame); 511 return DecodeUncompressedImage(dataset, frame);
541 } 512 }
542 513
543 #if ORTHANC_JPEG_LOSSLESS_ENABLED == 1 514 #if ORTHANC_JPEG_LOSSLESS_ENABLED == 1
544 if (IsJpegLossless(dataset)) 515 if (dataset.getOriginalXfer() == EXS_JPEGLSLossless ||
516 dataset.getOriginalXfer() == EXS_JPEGLSLossy)
545 { 517 {
546 LOG(INFO) << "Decoding a JPEG-LS image"; 518 LOG(INFO) << "Decoding a JPEG-LS image";
547 return DecodeJpegLossless(dataset, frame); 519 /**
520 * The "DJLSLosslessDecoder" and "DJLSNearLosslessDecoder" in DCMTK
521 * are exactly the same, except for the "supportedTransferSyntax()"
522 * virtual function.
523 * http://support.dcmtk.org/docs/classDJLSDecoderBase.html
524 **/
525
526 DJLSLosslessDecoder decoder; DJLSCodecParameter parameters;
527 //DJLSNearLosslessDecoder decoder; DJLSCodecParameter parameters;
528
529 return ApplyCodec(decoder, parameters, dataset, frame);
548 } 530 }
549 #endif 531 #endif
550 532
551 533
552 #if ORTHANC_JPEG_ENABLED == 1 534 #if ORTHANC_JPEG_ENABLED == 1
567 std::auto_ptr<DcmDataset> converted(dynamic_cast<DcmDataset*>(dataset.clone())); 549 std::auto_ptr<DcmDataset> converted(dynamic_cast<DcmDataset*>(dataset.clone()));
568 converted->chooseRepresentation(EXS_LittleEndianExplicit, NULL); 550 converted->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
569 551
570 if (converted->canWriteXfer(EXS_LittleEndianExplicit)) 552 if (converted->canWriteXfer(EXS_LittleEndianExplicit))
571 { 553 {
572 return DecodeUncompressedImageInternal(*converted, frame); 554 return DecodeUncompressedImage(*converted, frame);
573 } 555 }
574 } 556 }
575 557
576 LOG(ERROR) << "Cannot decode a DICOM image with the built-in decoder"; 558 LOG(ERROR) << "Cannot decode a DICOM image with the built-in decoder";
577 throw OrthancException(ErrorCode_BadFileFormat); 559 throw OrthancException(ErrorCode_BadFileFormat);