Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 864:2c545bb20dd3 jpeg
refactoring
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 10 Jun 2014 17:25:57 +0200 |
parents | 3c0d0836f704 |
children | 87791ebc1f50 |
comparison
equal
deleted
inserted
replaced
863:3c0d0836f704 | 864:2c545bb20dd3 |
---|---|
426 FromDcmtkBridge::ToJson(target, *dicom.getDataset(), maxStringLength); | 426 FromDcmtkBridge::ToJson(target, *dicom.getDataset(), maxStringLength); |
427 } | 427 } |
428 } | 428 } |
429 | 429 |
430 | 430 |
431 static void ExtractPngImageColorPreview(std::string& result, | |
432 DicomIntegerPixelAccessor& accessor) | |
433 { | |
434 assert(accessor.GetInformation().GetChannelCount() == 3); | |
435 PngWriter w; | |
436 | |
437 std::vector<uint8_t> image(accessor.GetInformation().GetWidth() * accessor.GetInformation().GetHeight() * 3, 0); | |
438 uint8_t* pixel = &image[0]; | |
439 | |
440 for (unsigned int y = 0; y < accessor.GetInformation().GetHeight(); y++) | |
441 { | |
442 for (unsigned int x = 0; x < accessor.GetInformation().GetWidth(); x++) | |
443 { | |
444 for (unsigned int c = 0; c < 3; c++, pixel++) | |
445 { | |
446 int32_t v = accessor.GetValue(x, y, c); | |
447 if (v < 0) | |
448 *pixel = 0; | |
449 else if (v > 255) | |
450 *pixel = 255; | |
451 else | |
452 *pixel = v; | |
453 } | |
454 } | |
455 } | |
456 | |
457 w.WriteToMemory(result, accessor.GetInformation().GetWidth(), accessor.GetInformation().GetHeight(), | |
458 accessor.GetInformation().GetWidth() * 3, PixelFormat_RGB24, &image[0]); | |
459 } | |
460 | |
461 | |
462 static void ExtractPngImageGrayscalePreview(std::string& result, | |
463 DicomIntegerPixelAccessor& accessor) | |
464 { | |
465 assert(accessor.GetInformation().GetChannelCount() == 1); | |
466 PngWriter w; | |
467 | |
468 int32_t min, max; | |
469 accessor.GetExtremeValues(min, max); | |
470 | |
471 std::vector<uint8_t> image(accessor.GetInformation().GetWidth() * accessor.GetInformation().GetHeight(), 0); | |
472 if (min != max) | |
473 { | |
474 uint8_t* pixel = &image[0]; | |
475 for (unsigned int y = 0; y < accessor.GetInformation().GetHeight(); y++) | |
476 { | |
477 for (unsigned int x = 0; x < accessor.GetInformation().GetWidth(); x++, pixel++) | |
478 { | |
479 int32_t v = accessor.GetValue(x, y); | |
480 *pixel = static_cast<uint8_t>( | |
481 boost::math::lround(static_cast<float>(v - min) / | |
482 static_cast<float>(max - min) * 255.0f)); | |
483 } | |
484 } | |
485 } | |
486 | |
487 w.WriteToMemory(result, accessor.GetInformation().GetWidth(), accessor.GetInformation().GetHeight(), | |
488 accessor.GetInformation().GetWidth(), PixelFormat_Grayscale8, &image[0]); | |
489 } | |
490 | |
491 | |
492 template <typename T> | |
493 static void ExtractPngImageTruncate(std::string& result, | |
494 DicomIntegerPixelAccessor& accessor, | |
495 PixelFormat format) | |
496 { | |
497 assert(accessor.GetInformation().GetChannelCount() == 1); | |
498 | |
499 PngWriter w; | |
500 | |
501 std::vector<T> image(accessor.GetInformation().GetWidth() * accessor.GetInformation().GetHeight(), 0); | |
502 T* pixel = &image[0]; | |
503 for (unsigned int y = 0; y < accessor.GetInformation().GetHeight(); y++) | |
504 { | |
505 for (unsigned int x = 0; x < accessor.GetInformation().GetWidth(); x++, pixel++) | |
506 { | |
507 int32_t v = accessor.GetValue(x, y); | |
508 if (v < static_cast<int32_t>(std::numeric_limits<T>::min())) | |
509 *pixel = std::numeric_limits<T>::min(); | |
510 else if (v > static_cast<int32_t>(std::numeric_limits<T>::max())) | |
511 *pixel = std::numeric_limits<T>::max(); | |
512 else | |
513 *pixel = static_cast<T>(v); | |
514 } | |
515 } | |
516 | |
517 w.WriteToMemory(result, accessor.GetInformation().GetWidth(), accessor.GetInformation().GetHeight(), | |
518 accessor.GetInformation().GetWidth() * sizeof(T), format, &image[0]); | |
519 } | |
520 | |
521 | |
522 | |
523 | |
524 void FromDcmtkBridge::ExtractPngImage(std::string& result, | 431 void FromDcmtkBridge::ExtractPngImage(std::string& result, |
525 DcmDataset& dataset, | 432 DcmDataset& dataset, |
526 unsigned int frame, | 433 unsigned int frame, |
527 ImageExtractionMode mode) | 434 ImageExtractionMode mode) |
528 { | 435 { |
529 // TODO CONTINUE THIS | |
530 | |
531 ImageBuffer tmp; | 436 ImageBuffer tmp; |
532 bool ok = false; | 437 bool ok = false; |
533 | 438 |
534 switch (mode) | 439 switch (mode) |
535 { | 440 { |
551 | 456 |
552 default: | 457 default: |
553 throw OrthancException(ErrorCode_ParameterOutOfRange); | 458 throw OrthancException(ErrorCode_ParameterOutOfRange); |
554 } | 459 } |
555 | 460 |
556 if (ok) | 461 if (!ok) |
557 { | |
558 ImageAccessor accessor(tmp.GetAccessor()); | |
559 PngWriter writer; | |
560 writer.WriteToMemory(result, accessor); | |
561 return; | |
562 } | |
563 else | |
564 { | 462 { |
565 throw OrthancException(ErrorCode_BadFileFormat); | 463 throw OrthancException(ErrorCode_BadFileFormat); |
566 } | 464 } |
567 | 465 |
568 | 466 ImageAccessor accessor(tmp.GetAccessor()); |
569 // See also: http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data | 467 PngWriter writer; |
570 | 468 writer.WriteToMemory(result, accessor); |
571 std::auto_ptr<DicomIntegerPixelAccessor> accessor; | |
572 | |
573 DicomMap m; | |
574 FromDcmtkBridge::Convert(m, dataset); | |
575 | |
576 std::string privateContent; | |
577 | |
578 DcmElement* e; | |
579 if (dataset.findAndGetElement(ToDcmtkBridge::Convert(DICOM_TAG_PIXEL_DATA), e).good() && | |
580 e != NULL) | |
581 { | |
582 Uint8* pixData = NULL; | |
583 if (e->getUint8Array(pixData) == EC_Normal) | |
584 { | |
585 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); | |
586 accessor->SetCurrentFrame(frame); | |
587 } | |
588 } | |
589 else if (DicomImageDecoder::DecodePsmctRle1(privateContent, dataset)) | |
590 { | |
591 LOG(INFO) << "The PMSCT_RLE1 decoding has succeeded"; | |
592 Uint8* pixData = NULL; | |
593 if (privateContent.size() > 0) | |
594 pixData = reinterpret_cast<Uint8*>(&privateContent[0]); | |
595 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, privateContent.size())); | |
596 accessor->SetCurrentFrame(frame); | |
597 } | |
598 | |
599 if (accessor.get() == NULL) | |
600 { | |
601 throw OrthancException(ErrorCode_BadFileFormat); | |
602 } | |
603 | |
604 PixelFormat format; | |
605 bool supported = false; | |
606 | |
607 if (accessor->GetInformation().GetChannelCount() == 1) | |
608 { | |
609 switch (mode) | |
610 { | |
611 case ImageExtractionMode_Preview: | |
612 supported = true; | |
613 format = PixelFormat_Grayscale8; | |
614 break; | |
615 | |
616 case ImageExtractionMode_UInt8: | |
617 supported = true; | |
618 format = PixelFormat_Grayscale8; | |
619 break; | |
620 | |
621 case ImageExtractionMode_UInt16: | |
622 supported = true; | |
623 format = PixelFormat_Grayscale16; | |
624 break; | |
625 | |
626 case ImageExtractionMode_Int16: | |
627 supported = true; | |
628 format = PixelFormat_SignedGrayscale16; | |
629 break; | |
630 | |
631 default: | |
632 supported = false; | |
633 break; | |
634 } | |
635 } | |
636 else if (accessor->GetInformation().GetChannelCount() == 3) | |
637 { | |
638 switch (mode) | |
639 { | |
640 case ImageExtractionMode_Preview: | |
641 supported = true; | |
642 format = PixelFormat_RGB24; | |
643 break; | |
644 | |
645 default: | |
646 supported = false; | |
647 break; | |
648 } | |
649 } | |
650 | |
651 if (!supported) | |
652 { | |
653 throw OrthancException(ErrorCode_NotImplemented); | |
654 } | |
655 | |
656 if (accessor.get() == NULL || | |
657 accessor->GetInformation().GetWidth() == 0 || | |
658 accessor->GetInformation().GetHeight() == 0) | |
659 { | |
660 PngWriter w; | |
661 w.WriteToMemory(result, 0, 0, 0, format, NULL); | |
662 } | |
663 else | |
664 { | |
665 switch (mode) | |
666 { | |
667 case ImageExtractionMode_Preview: | |
668 if (format == PixelFormat_Grayscale8) | |
669 ExtractPngImageGrayscalePreview(result, *accessor); | |
670 else | |
671 ExtractPngImageColorPreview(result, *accessor); | |
672 break; | |
673 | |
674 case ImageExtractionMode_UInt8: | |
675 ExtractPngImageTruncate<uint8_t>(result, *accessor, format); | |
676 break; | |
677 | |
678 case ImageExtractionMode_UInt16: | |
679 ExtractPngImageTruncate<uint16_t>(result, *accessor, format); | |
680 break; | |
681 | |
682 case ImageExtractionMode_Int16: | |
683 ExtractPngImageTruncate<int16_t>(result, *accessor, format); | |
684 break; | |
685 | |
686 default: | |
687 throw OrthancException(ErrorCode_NotImplemented); | |
688 } | |
689 } | |
690 } | 469 } |
691 | 470 |
692 | 471 |
693 void FromDcmtkBridge::ExtractPngImage(std::string& result, | 472 void FromDcmtkBridge::ExtractPngImage(std::string& result, |
694 const std::string& dicomContent, | 473 const std::string& dicomContent, |