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();