Mercurial > hg > orthanc
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, ¶meters, | 479 OFCondition c = codec.decodeFrame(&representationParameter, GetPixelSequence(dataset), ¶meters, |
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); |