Mercurial > hg > orthanc-stone
comparison Framework/Radiography/RadiographyScene.cpp @ 481:159a465e27bd am-touch-events
reworked RadiographyScene export to export to an Orthanc::Image too
author | am@osimis.io |
---|---|
date | Thu, 14 Feb 2019 16:23:59 +0100 |
parents | 3c28542229a3 |
children | 29fc066b6f65 |
comparison
equal
deleted
inserted
replaced
480:2f6ecb5037ea | 481:159a465e27bd |
---|---|
537 minValue = 0; | 537 minValue = 0; |
538 maxValue = 0; | 538 maxValue = 0; |
539 } | 539 } |
540 } | 540 } |
541 | 541 |
542 | 542 Orthanc::Image* RadiographyScene::ExportToImage(double pixelSpacingX, |
543 double pixelSpacingY, | |
544 ImageInterpolation interpolation, | |
545 bool invert, | |
546 int64_t maxValue /* for inversion */) | |
547 { | |
548 if (pixelSpacingX <= 0 || | |
549 pixelSpacingY <= 0) | |
550 { | |
551 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
552 } | |
553 | |
554 LOG(INFO) << "Exporting DICOM"; | |
555 | |
556 Extent2D extent = GetSceneExtent(); | |
557 | |
558 int w = std::ceil(extent.GetWidth() / pixelSpacingX); | |
559 int h = std::ceil(extent.GetHeight() / pixelSpacingY); | |
560 | |
561 if (w < 0 || h < 0) | |
562 { | |
563 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
564 } | |
565 | |
566 Orthanc::Image layers(Orthanc::PixelFormat_Float32, | |
567 static_cast<unsigned int>(w), | |
568 static_cast<unsigned int>(h), false); | |
569 | |
570 AffineTransform2D view = AffineTransform2D::Combine( | |
571 AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), | |
572 AffineTransform2D::CreateOffset(-extent.GetX1(), -extent.GetY1())); | |
573 | |
574 // wipe background before rendering | |
575 Orthanc::ImageProcessing::Set(layers, 0); | |
576 | |
577 Render(layers, view, interpolation); | |
578 | |
579 std::auto_ptr<Orthanc::Image> rendered(new Orthanc::Image(Orthanc::PixelFormat_Grayscale16, | |
580 layers.GetWidth(), layers.GetHeight(), false)); | |
581 | |
582 Orthanc::ImageProcessing::Convert(*rendered, layers); | |
583 if (invert) | |
584 Orthanc::ImageProcessing::Invert(*rendered, maxValue); | |
585 | |
586 return rendered.release(); | |
587 } | |
588 | |
589 | |
590 // Export using PAM is faster than using PNG, but requires Orthanc | |
591 // core >= 1.4.3 | |
543 void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, | 592 void RadiographyScene::ExportDicom(OrthancApiClient& orthanc, |
544 const Orthanc::DicomMap& dicom, | 593 const Orthanc::DicomMap& dicom, |
545 const std::string& parentOrthancId, | 594 const std::string& parentOrthancId, |
546 double pixelSpacingX, | 595 double pixelSpacingX, |
547 double pixelSpacingY, | 596 double pixelSpacingY, |
549 ImageInterpolation interpolation, | 598 ImageInterpolation interpolation, |
550 bool usePam) | 599 bool usePam) |
551 { | 600 { |
552 Json::Value createDicomRequestContent; | 601 Json::Value createDicomRequestContent; |
553 | 602 |
554 ExportToCreateDicomRequest(createDicomRequestContent, dicom, pixelSpacingX, pixelSpacingY, invert, interpolation, usePam); | 603 std::auto_ptr<Orthanc::Image> rendered(ExportToImage(pixelSpacingX, pixelSpacingY, interpolation)); // note: we don't invert the image in the pixels data because we'll set the PhotometricDisplayMode correctly in the DICOM tags |
555 | |
556 if (!parentOrthancId.empty()) | |
557 { | |
558 createDicomRequestContent["Parent"] = parentOrthancId; | |
559 } | |
560 | |
561 orthanc.PostJsonAsyncExpectJson( | |
562 "/tools/create-dicom", createDicomRequestContent, | |
563 new Callable<RadiographyScene, OrthancApiClient::JsonResponseReadyMessage> | |
564 (*this, &RadiographyScene::OnDicomExported), | |
565 NULL, NULL); | |
566 } | |
567 | |
568 // Export using PAM is faster than using PNG, but requires Orthanc | |
569 // core >= 1.4.3 | |
570 void RadiographyScene::ExportToCreateDicomRequest(Json::Value& createDicomRequestContent, | |
571 const Orthanc::DicomMap& dicom, | |
572 double pixelSpacingX, | |
573 double pixelSpacingY, | |
574 bool invert, | |
575 ImageInterpolation interpolation, | |
576 bool usePam) | |
577 { | |
578 if (pixelSpacingX <= 0 || | |
579 pixelSpacingY <= 0) | |
580 { | |
581 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
582 } | |
583 | |
584 LOG(INFO) << "Exporting DICOM"; | |
585 | |
586 Extent2D extent = GetSceneExtent(); | |
587 | |
588 int w = std::ceil(extent.GetWidth() / pixelSpacingX); | |
589 int h = std::ceil(extent.GetHeight() / pixelSpacingY); | |
590 | |
591 if (w < 0 || h < 0) | |
592 { | |
593 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
594 } | |
595 | |
596 Orthanc::Image layers(Orthanc::PixelFormat_Float32, | |
597 static_cast<unsigned int>(w), | |
598 static_cast<unsigned int>(h), false); | |
599 | |
600 AffineTransform2D view = AffineTransform2D::Combine( | |
601 AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), | |
602 AffineTransform2D::CreateOffset(-extent.GetX1(), -extent.GetY1())); | |
603 | |
604 // wipe background before rendering | |
605 Orthanc::ImageProcessing::Set(layers, 0); | |
606 | |
607 Render(layers, view, interpolation); | |
608 | |
609 Orthanc::Image rendered(Orthanc::PixelFormat_Grayscale16, | |
610 layers.GetWidth(), layers.GetHeight(), false); | |
611 Orthanc::ImageProcessing::Convert(rendered, layers); | |
612 | 604 |
613 std::string base64; | 605 std::string base64; |
614 | 606 |
615 { | 607 { |
616 std::string content; | 608 std::string content; |
617 | 609 |
618 if (usePam) | 610 if (usePam) |
619 { | 611 { |
620 Orthanc::PamWriter writer; | 612 Orthanc::PamWriter writer; |
621 writer.WriteToMemory(content, rendered); | 613 writer.WriteToMemory(content, *rendered); |
622 } | 614 } |
623 else | 615 else |
624 { | 616 { |
625 Orthanc::PngWriter writer; | 617 Orthanc::PngWriter writer; |
626 writer.WriteToMemory(content, rendered); | 618 writer.WriteToMemory(content, *rendered); |
627 } | 619 } |
628 | 620 |
629 Orthanc::Toolbox::EncodeBase64(base64, content); | 621 Orthanc::Toolbox::EncodeBase64(base64, content); |
630 } | 622 } |
631 | 623 |
678 | 670 |
679 // This is Data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme | 671 // This is Data URI scheme: https://en.wikipedia.org/wiki/Data_URI_scheme |
680 createDicomRequestContent["Content"] = ("data:" + | 672 createDicomRequestContent["Content"] = ("data:" + |
681 std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + | 673 std::string(usePam ? Orthanc::MIME_PAM : Orthanc::MIME_PNG) + |
682 ";base64," + base64); | 674 ";base64," + base64); |
683 } | 675 |
684 | 676 if (!parentOrthancId.empty()) |
677 { | |
678 createDicomRequestContent["Parent"] = parentOrthancId; | |
679 } | |
680 | |
681 orthanc.PostJsonAsyncExpectJson( | |
682 "/tools/create-dicom", createDicomRequestContent, | |
683 new Callable<RadiographyScene, OrthancApiClient::JsonResponseReadyMessage> | |
684 (*this, &RadiographyScene::OnDicomExported), | |
685 NULL, NULL); | |
686 } | |
685 | 687 |
686 void RadiographyScene::OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) | 688 void RadiographyScene::OnDicomExported(const OrthancApiClient::JsonResponseReadyMessage& message) |
687 { | 689 { |
688 LOG(INFO) << "DICOM export was successful: " | 690 LOG(INFO) << "DICOM export was successful: " |
689 << message.GetJson().toStyledString(); | 691 << message.GetJson().toStyledString(); |