Mercurial > hg > orthanc-stone
comparison Samples/Sdl/Loader.cpp @ 678:6f10f9a6676a
turning DicomVolumeImage into a bean class
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 16 May 2019 11:20:43 +0200 |
parents | 3805ffa2833d |
children | 0eb26f514ac5 |
comparison
equal
deleted
inserted
replaced
669:3805ffa2833d | 678:6f10f9a6676a |
---|---|
1484 { | 1484 { |
1485 private: | 1485 private: |
1486 std::auto_ptr<OrthancStone::ImageBuffer3D> image_; | 1486 std::auto_ptr<OrthancStone::ImageBuffer3D> image_; |
1487 std::vector<DicomInstanceParameters*> slices_; | 1487 std::vector<DicomInstanceParameters*> slices_; |
1488 | 1488 |
1489 static const DicomInstanceParameters& | 1489 void CheckSlice(size_t index, |
1490 GetSliceParameters(const OrthancStone::SlicesSorter& slices, | 1490 const DicomInstanceParameters& reference) const |
1491 size_t index) | 1491 { |
1492 { | 1492 const DicomInstanceParameters& slice = *slices_[index]; |
1493 return dynamic_cast<const DicomInstanceParameters&>(slices.GetSlicePayload(index)); | |
1494 } | |
1495 | |
1496 static void CheckSlice(const OrthancStone::SlicesSorter& slices, | |
1497 size_t index, | |
1498 const OrthancStone::CoordinateSystem3D& reference, | |
1499 const DicomInstanceParameters& a) | |
1500 { | |
1501 const OrthancStone::CoordinateSystem3D& slice = slices.GetSliceGeometry(index); | |
1502 const DicomInstanceParameters& b = GetSliceParameters(slices, index); | |
1503 | 1493 |
1504 if (!OrthancStone::GeometryToolbox::IsParallel(reference.GetNormal(), slice.GetNormal())) | 1494 if (!OrthancStone::GeometryToolbox::IsParallel( |
1495 reference.GetGeometry().GetNormal(), | |
1496 slice.GetGeometry().GetNormal())) | |
1505 { | 1497 { |
1506 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, | 1498 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, |
1507 "A slice in the volume image is not parallel to the others"); | 1499 "A slice in the volume image is not parallel to the others"); |
1508 } | 1500 } |
1509 | 1501 |
1510 if (a.GetExpectedPixelFormat() != b.GetExpectedPixelFormat()) | 1502 if (reference.GetExpectedPixelFormat() != slice.GetExpectedPixelFormat()) |
1511 { | 1503 { |
1512 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, | 1504 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat, |
1513 "The pixel format changes across the slices of the volume image"); | 1505 "The pixel format changes across the slices of the volume image"); |
1514 } | 1506 } |
1515 | 1507 |
1516 if (a.GetImageInformation().GetWidth() != b.GetImageInformation().GetWidth() || | 1508 if (reference.GetImageInformation().GetWidth() != slice.GetImageInformation().GetWidth() || |
1517 a.GetImageInformation().GetHeight() != b.GetImageInformation().GetHeight()) | 1509 reference.GetImageInformation().GetHeight() != slice.GetImageInformation().GetHeight()) |
1518 { | 1510 { |
1519 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize, | 1511 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize, |
1520 "The width/height of slices are not constant in the volume image"); | 1512 "The width/height of slices are not constant in the volume image"); |
1521 } | 1513 } |
1522 | 1514 |
1523 if (!OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingX(), b.GetPixelSpacingX()) || | 1515 if (!OrthancStone::LinearAlgebra::IsNear(reference.GetPixelSpacingX(), slice.GetPixelSpacingX()) || |
1524 !OrthancStone::LinearAlgebra::IsNear(a.GetPixelSpacingY(), b.GetPixelSpacingY())) | 1516 !OrthancStone::LinearAlgebra::IsNear(reference.GetPixelSpacingY(), slice.GetPixelSpacingY())) |
1525 { | 1517 { |
1526 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, | 1518 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, |
1527 "The pixel spacing of the slices change across the volume image"); | 1519 "The pixel spacing of the slices change across the volume image"); |
1528 } | 1520 } |
1529 } | 1521 } |
1530 | 1522 |
1531 | 1523 |
1532 static void CheckVolume(const OrthancStone::SlicesSorter& slices) | 1524 void CheckVolume() const |
1533 { | 1525 { |
1534 for (size_t i = 0; i < slices.GetSlicesCount(); i++) | 1526 for (size_t i = 0; i < slices_.size(); i++) |
1535 { | 1527 { |
1536 if (GetSliceParameters(slices, i).GetImageInformation().GetNumberOfFrames() != 1) | 1528 assert(slices_[i] != NULL); |
1529 if (slices_[i]->GetImageInformation().GetNumberOfFrames() != 1) | |
1537 { | 1530 { |
1538 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, | 1531 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadGeometry, |
1539 "This class does not support multi-frame images"); | 1532 "This class does not support multi-frame images"); |
1540 } | 1533 } |
1541 } | 1534 } |
1542 | 1535 |
1543 if (slices.GetSlicesCount() != 0) | 1536 if (slices_.size() != 0) |
1544 { | 1537 { |
1545 const OrthancStone::CoordinateSystem3D& reference = slices.GetSliceGeometry(0); | 1538 const DicomInstanceParameters& reference = *slices_[0]; |
1546 const DicomInstanceParameters& dicom = GetSliceParameters(slices, 0); | 1539 |
1547 | 1540 for (size_t i = 1; i < slices_.size(); i++) |
1548 for (size_t i = 1; i < slices.GetSlicesCount(); i++) | 1541 { |
1549 { | 1542 CheckSlice(i, reference); |
1550 CheckSlice(slices, i, reference, dicom); | |
1551 } | 1543 } |
1552 } | 1544 } |
1553 } | 1545 } |
1554 | 1546 |
1555 | 1547 |
1584 { | 1576 { |
1585 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, | 1577 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, |
1586 "Cannot sort the 3D slices of a DICOM series"); | 1578 "Cannot sort the 3D slices of a DICOM series"); |
1587 } | 1579 } |
1588 | 1580 |
1589 slices_.reserve(slices.GetSlicesCount()); | 1581 if (slices.GetSlicesCount() == 0) |
1590 | 1582 { |
1591 for (size_t i = 0; i < slices.GetSlicesCount(); i++) | 1583 // Empty volume |
1592 { | 1584 image_.reset(new OrthancStone::ImageBuffer3D(Orthanc::PixelFormat_Grayscale8, 0, 0, 0, |
1593 slices_.push_back(new DicomInstanceParameters(GetSliceParameters(slices, i))); | 1585 false /* don't compute range */)); |
1594 } | 1586 } |
1595 | 1587 else |
1596 CheckVolume(slices); | 1588 { |
1597 | 1589 slices_.reserve(slices.GetSlicesCount()); |
1598 const double spacingZ = slices.ComputeSpacingBetweenSlices(); | 1590 |
1599 LOG(INFO) << "Computed spacing between slices: " << spacingZ << "mm"; | 1591 for (size_t i = 0; i < slices.GetSlicesCount(); i++) |
1592 { | |
1593 const DicomInstanceParameters& slice = | |
1594 dynamic_cast<const DicomInstanceParameters&>(slices.GetSlicePayload(i)); | |
1595 slices_.push_back(new DicomInstanceParameters(slice)); | |
1596 } | |
1597 | |
1598 CheckVolume(); | |
1599 | |
1600 const double spacingZ = slices.ComputeSpacingBetweenSlices(); | |
1601 LOG(INFO) << "Computed spacing between slices: " << spacingZ << "mm"; | |
1600 | 1602 |
1601 const DicomInstanceParameters& parameters = GetSliceParameters(slices, 0); | 1603 const DicomInstanceParameters& parameters = *slices_[0]; |
1602 | 1604 |
1603 image_.reset(new OrthancStone::ImageBuffer3D(parameters.GetExpectedPixelFormat(), | 1605 image_.reset(new OrthancStone::ImageBuffer3D(parameters.GetExpectedPixelFormat(), |
1604 parameters.GetImageInformation().GetWidth(), | 1606 parameters.GetImageInformation().GetWidth(), |
1605 parameters.GetImageInformation().GetHeight(), | 1607 parameters.GetImageInformation().GetHeight(), |
1606 slices.GetSlicesCount(), false /* don't compute range */)); | 1608 slices.GetSlicesCount(), false /* don't compute range */)); |
1607 | 1609 |
1608 image_->SetAxialGeometry(slices.GetSliceGeometry(0)); | 1610 image_->SetAxialGeometry(slices.GetSliceGeometry(0)); |
1609 image_->SetVoxelDimensions(parameters.GetPixelSpacingX(), parameters.GetPixelSpacingY(), spacingZ); | 1611 image_->SetVoxelDimensions(parameters.GetPixelSpacingX(), parameters.GetPixelSpacingY(), spacingZ); |
1612 } | |
1613 | |
1610 image_->Clear(); | 1614 image_->Clear(); |
1611 } | 1615 } |
1612 | 1616 |
1613 bool IsGeometryReady() const | 1617 bool IsGeometryReady() const |
1614 { | 1618 { |
1623 } | 1627 } |
1624 else | 1628 else |
1625 { | 1629 { |
1626 return *image_; | 1630 return *image_; |
1627 } | 1631 } |
1628 } | 1632 } |
1633 | |
1634 size_t GetSlicesCount() const | |
1635 { | |
1636 if (!IsGeometryReady()) | |
1637 { | |
1638 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
1639 } | |
1640 else | |
1641 { | |
1642 assert(slices_.size() == image_->GetDepth()); | |
1643 return slices_.size(); | |
1644 } | |
1645 } | |
1646 | |
1647 const DicomInstanceParameters& GetSlice(size_t index) const | |
1648 { | |
1649 if (!IsGeometryReady()) | |
1650 { | |
1651 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
1652 } | |
1653 else if (index >= slices_.size()) | |
1654 { | |
1655 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
1656 } | |
1657 else | |
1658 { | |
1659 assert(slices_.size() == image_->GetDepth()); | |
1660 return *slices_[index]; | |
1661 } | |
1662 } | |
1629 }; | 1663 }; |
1630 | 1664 |
1631 | 1665 |
1632 | 1666 |
1633 class AxialVolumeOrthancLoader : public OrthancStone::IObserver | 1667 class AxialVolumeOrthancLoader : public OrthancStone::IObserver |