/* * * Copyright (C) 1998-2021, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: dcmpstat * * Author: Marco Eichelberg * * Purpose: * classes: DcmPresentationState * */ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/dcmpstat/dcmpstat.h" #include "dcmtk/ofstd/ofstd.h" /* for class OFStandard */ #include "dcmtk/ofstd/ofstream.h" #include "dcmtk/ofstd/ofstring.h" #include "dcmtk/dcmpstat/dvpsdef.h" /* for constants and macros */ #include "dcmtk/dcmpstat/dvpscu.h" /* for DVPSCurve */ #include "dcmtk/dcmpstat/dvpsvl.h" /* for DVPSVOILUT */ #include "dcmtk/dcmpstat/dvpsvw.h" /* for DVPSVOIWindow */ #include "dcmtk/dcmpstat/dvpsov.h" /* for DVPSOverlay */ #include "dcmtk/dcmpstat/dvpsda.h" /* for DVPSDisplayedArea */ #include "dcmtk/dcmpstat/dvpssv.h" /* for DVPSSoftcopyVOI */ #include "dcmtk/dcmpstat/dvpshlp.h" /* for class DVPSHelper */ #include "dcmtk/dcmpstat/dvpsgl.h" /* for DVPSGraphicLayer, needed by MSVC5 with STL */ #include "dcmtk/dcmpstat/dvpsrs.h" /* for DVPSReferencedSeries, needed by MSVC5 with STL */ #include "dcmtk/dcmpstat/dvpsal.h" /* for DVPSOverlayCurveActivationLayer, needed by MSVC5 with STL */ #include "dcmtk/dcmpstat/dvpsga.h" /* for DVPSGraphicAnnotation, needed by MSVC5 with STL */ #include "dcmtk/dcmpstat/dvpsri.h" /* for DVPSReferencedImage, needed by MSVC5 with STL */ #include "dcmtk/dcmpstat/dvpstx.h" /* for DVPSTextObject, needed by MSVC5 with STL */ #include "dcmtk/dcmpstat/dvpsgr.h" /* for DVPSGraphicObject, needed by MSVC5 with STL */ OFLogger DCM_dcmpstatLogger = OFLog::getLogger("dcmtk.dcmpstat"); OFLogger DCM_dcmpstatDumpLogger = OFLog::getLogger("dcmtk.dcmpstat.dump"); OFLogger DCM_dcmpstatLogfileLogger = OFLog::getLogger("dcmtk.dcmpstat.logfile"); /* --------------- class DcmPresentationState --------------- */ DcmPresentationState::DcmPresentationState() : patientName(DCM_PatientName) , patientID(DCM_PatientID) , patientBirthDate(DCM_PatientBirthDate) , patientSex(DCM_PatientSex) , studyInstanceUID(DCM_StudyInstanceUID) , studyDate(DCM_StudyDate) , studyTime(DCM_StudyTime) , referringPhysicianName(DCM_ReferringPhysicianName) , studyID(DCM_StudyID) , accessionNumber(DCM_AccessionNumber) , seriesInstanceUID(DCM_SeriesInstanceUID) , seriesNumber(DCM_SeriesNumber) , manufacturer(DCM_Manufacturer) , displayedAreaSelectionList() , presentationLUT() , imageNumber(DCM_InstanceNumber) , presentationLabel(DCM_ContentLabel) , presentationDescription(DCM_ContentDescription) , presentationCreationDate(DCM_PresentationCreationDate) , presentationCreationTime(DCM_PresentationCreationTime) , presentationCreatorsName(DCM_ContentCreatorName) , referencedSeriesList() , sOPInstanceUID(DCM_SOPInstanceUID) , specificCharacterSet(DCM_SpecificCharacterSet) , instanceCreationDate(DCM_InstanceCreationDate) , instanceCreationTime(DCM_InstanceCreationTime) , instanceCreatorUID(DCM_InstanceCreatorUID) , useShutterRectangular(OFFalse) , useShutterCircular(OFFalse) , useShutterPolygonal(OFFalse) , useShutterBitmap(OFFalse) , shutterShape(DCM_ShutterShape) , shutterLeftVerticalEdge(DCM_ShutterLeftVerticalEdge) , shutterRightVerticalEdge(DCM_ShutterRightVerticalEdge) , shutterUpperHorizontalEdge(DCM_ShutterUpperHorizontalEdge) , shutterLowerHorizontalEdge(DCM_ShutterLowerHorizontalEdge) , centerOfCircularShutter(DCM_CenterOfCircularShutter) , radiusOfCircularShutter(DCM_RadiusOfCircularShutter) , verticesOfThePolygonalShutter(DCM_VerticesOfThePolygonalShutter) , shutterPresentationValue(DCM_ShutterPresentationValue) , shutterOverlayGroup(DCM_ShutterOverlayGroup) , overlayList() , activationLayerList() , graphicAnnotationList() , imageRotation(DCM_ImageRotation) , imageHorizontalFlip(DCM_ImageHorizontalFlip) , graphicLayerList() , useModalityRescale(OFFalse) , useModalityLUT(OFFalse) , modalityLUTDescriptor(DCM_LUTDescriptor) , modalityLUTExplanation(DCM_LUTExplanation) , modalityLUTType(DCM_ModalityLUTType) , modalityLUTData(DCM_LUTData) , rescaleIntercept(DCM_RescaleIntercept) , rescaleSlope(DCM_RescaleSlope) , rescaleType(DCM_RescaleType) , softcopyVOIList() { createInstanceUID(); } DcmPresentationState::~DcmPresentationState() { } void DcmPresentationState::clear() { patientName.clear(); patientID.clear(); patientBirthDate.clear(); patientSex.clear(); studyInstanceUID.clear(); studyDate.clear(); studyTime.clear(); referringPhysicianName.clear(); studyID.clear(); accessionNumber.clear(); seriesInstanceUID.clear(); seriesNumber.clear(); manufacturer.clear(); displayedAreaSelectionList.clear(); presentationLUT.clear(); imageNumber.clear(); presentationLabel.clear(); presentationDescription.clear(); presentationCreationDate.clear(); presentationCreationTime.clear(); presentationCreatorsName.clear(); referencedSeriesList.clear(); sOPInstanceUID.clear(); specificCharacterSet.clear(); instanceCreationDate.clear(); instanceCreationTime.clear(); instanceCreatorUID.clear(); shutterShape.clear(); shutterLeftVerticalEdge.clear(); shutterRightVerticalEdge.clear(); shutterUpperHorizontalEdge.clear(); shutterLowerHorizontalEdge.clear(); centerOfCircularShutter.clear(); radiusOfCircularShutter.clear(); verticesOfThePolygonalShutter.clear(); shutterPresentationValue.clear(); shutterOverlayGroup.clear(); overlayList.clear(); activationLayerList.clear(); graphicAnnotationList.clear(); imageRotation.clear(); imageHorizontalFlip.clear(); graphicLayerList.clear(); useModalityRescale = OFFalse; useModalityLUT = OFFalse; modalityLUTDescriptor.clear(); modalityLUTExplanation.clear(); modalityLUTType.clear(); modalityLUTData.clear(); rescaleIntercept.clear(); rescaleSlope.clear(); rescaleType.clear(); softcopyVOIList.clear(); return; } const char *DcmPresentationState::createInstanceUID() { char uid[100]; OFString aString; char *puid = NULL; OFCondition result = sOPInstanceUID.putString(dcmGenerateUniqueIdentifier(uid)); DVPSHelper::currentDate(aString); DVPSHelper::setDefault(result, instanceCreationDate, aString.c_str()); DVPSHelper::currentTime(aString); DVPSHelper::setDefault(result, instanceCreationTime, aString.c_str()); if (EC_Normal == result) { if (EC_Normal != sOPInstanceUID.getString(puid)) puid=NULL; } return puid; } const char *DcmPresentationState::getInstanceUID() { char *puid = NULL; if (EC_Normal != sOPInstanceUID.getString(puid)) puid=NULL; return puid; } const char *DcmPresentationState::getSOPClassUID() { return UID_GrayscaleSoftcopyPresentationStateStorage; } const char *DcmPresentationState::getPatientID() { char *c = NULL; if (EC_Normal == patientID.getString(c)) return c; else return NULL; } const char *DcmPresentationState::getStudyUID() { char *c = NULL; if (EC_Normal == studyInstanceUID.getString(c)) return c; else return NULL; } OFCondition DcmPresentationState::createDummyValues(OFBool replaceSOPInstanceUID) { OFCondition result = EC_Normal; char uid[100]; OFString aString; DVPSHelper::setDefault(result, patientName, DEFAULT_patientName); SET_UID(studyInstanceUID) SET_UID(seriesInstanceUID) DVPSHelper::setDefault(result, imageNumber, DEFAULT_imageNumber); DVPSHelper::setDefault(result, presentationLabel, DEFAULT_presentationLabel); DVPSHelper::currentDate(aString); DVPSHelper::setDefault(result, presentationCreationDate, aString.c_str() ); DVPSHelper::currentTime(aString); DVPSHelper::setDefault(result, presentationCreationTime, aString.c_str() ); if ((result==EC_Normal)&&(replaceSOPInstanceUID ||(sOPInstanceUID.getLength()==0))) { sOPInstanceUID.putString(dcmGenerateUniqueIdentifier(uid)); DVPSHelper::currentDate(aString); DVPSHelper::setDefault(result, instanceCreationDate, aString.c_str() ); DVPSHelper::currentTime(aString); DVPSHelper::setDefault(result, instanceCreationTime, aString.c_str() ); } // default for specific character set is -absent-. // DVPSHelper::setDefault(result, specificCharacterSet, DEFAULT_specificCharacterSet ); // create some dummy defaults for shutters if (shutterPresentationValue.getVM() != 1) shutterPresentationValue.putUint16(0); DVPSHelper::setDefault(result, shutterLeftVerticalEdge, "1"); DVPSHelper::setDefault(result, shutterRightVerticalEdge, "1024"); DVPSHelper::setDefault(result, shutterUpperHorizontalEdge, "1"); DVPSHelper::setDefault(result, shutterLowerHorizontalEdge, "1024"); DVPSHelper::setDefault(result, centerOfCircularShutter, "512\\512"); DVPSHelper::setDefault(result, radiusOfCircularShutter, "512"); DVPSHelper::setDefault(result, verticesOfThePolygonalShutter, "1\\1\\1\\1024\\1024\\1024\\1024\\1\\1\\1"); if (shutterOverlayGroup.getVM() != 1) shutterOverlayGroup.putUint16(0x6000); // create defaults for Spatial Transformation Module if (result==EC_Normal) { if (imageRotation.getVM() != 1) result = imageRotation.putUint16(0); } DVPSHelper::setDefault(result, imageHorizontalFlip, "N"); // create defaults for Modality Rescale DVPSHelper::setDefault(result, rescaleIntercept, "0"); DVPSHelper::setDefault(result, rescaleSlope, "1"); DVPSHelper::setDefault(result, rescaleType, "UNSPECIFIED"); return result; } OFCondition DcmPresentationState::read(DcmItem &dset) { OFCondition result = EC_Normal; DcmStack stack; DcmSequenceOfItems *seq; DcmItem *item; clear(); // re-initialize Presentation State object /* check SOP class UID and modality first */ DcmUniqueIdentifier sopclassuid(DCM_SOPClassUID); DcmCodeString modality(DCM_Modality); OFString aString; READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, sopclassuid) READ_FROM_DATASET(DcmCodeString, EVR_CS, modality) if (sopclassuid.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("SOPClassUID absent or empty in presentation state"); } else if (sopclassuid.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("SOPClassUID VM != 1 in presentation state"); } if (modality.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("Modality absent or empty in presentation state"); } else if (modality.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("Modality VM != 1 in presentation state"); } sopclassuid.getOFString(aString,0); if (aString != UID_GrayscaleSoftcopyPresentationStateStorage) { result=EC_IllegalCall; DCMPSTAT_WARN("SOP Class UID does not match GrayscaleSoftcopyPresentationStateStorage"); } modality.getOFString(aString,0); if (aString != "PR") { result=EC_IllegalCall; DCMPSTAT_WARN("Modality does not match 'PR' for presentation state"); } if (result==EC_Normal) { READ_FROM_DATASET(DcmPersonName, EVR_PN, patientName) READ_FROM_DATASET(DcmLongString, EVR_LO, patientID) READ_FROM_DATASET(DcmDate, EVR_DA, patientBirthDate) READ_FROM_DATASET(DcmCodeString, EVR_CS, patientSex) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, studyInstanceUID) READ_FROM_DATASET(DcmDate, EVR_DA, studyDate) READ_FROM_DATASET(DcmTime, EVR_TM, studyTime) READ_FROM_DATASET(DcmPersonName, EVR_PN, referringPhysicianName) READ_FROM_DATASET(DcmShortString, EVR_SH, studyID) READ_FROM_DATASET(DcmShortString, EVR_SH, accessionNumber) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, seriesInstanceUID) READ_FROM_DATASET(DcmIntegerString, EVR_IS, seriesNumber) READ_FROM_DATASET(DcmLongString, EVR_LO, manufacturer) READ_FROM_DATASET(DcmIntegerString, EVR_IS, imageNumber) READ_FROM_DATASET(DcmCodeString, EVR_CS, presentationLabel) READ_FROM_DATASET(DcmLongString, EVR_LO, presentationDescription) READ_FROM_DATASET(DcmDate, EVR_DA, presentationCreationDate) READ_FROM_DATASET(DcmTime, EVR_TM, presentationCreationTime) READ_FROM_DATASET(DcmPersonName, EVR_PN, presentationCreatorsName) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, sOPInstanceUID) READ_FROM_DATASET(DcmCodeString, EVR_CS, specificCharacterSet) READ_FROM_DATASET(DcmDate, EVR_DA, instanceCreationDate) READ_FROM_DATASET(DcmTime, EVR_TM, instanceCreationTime) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, instanceCreatorUID) READ_FROM_DATASET(DcmCodeString, EVR_CS, shutterShape) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterLeftVerticalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterRightVerticalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterUpperHorizontalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterLowerHorizontalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, centerOfCircularShutter) READ_FROM_DATASET(DcmIntegerString, EVR_IS, radiusOfCircularShutter) READ_FROM_DATASET(DcmIntegerString, EVR_IS, verticesOfThePolygonalShutter) READ_FROM_DATASET(DcmUnsignedShort, EVR_US, shutterPresentationValue) READ_FROM_DATASET(DcmUnsignedShort, EVR_US, shutterOverlayGroup) READ_FROM_DATASET(DcmUnsignedShort, EVR_US, imageRotation) READ_FROM_DATASET(DcmCodeString, EVR_CS, imageHorizontalFlip) READ_FROM_DATASET(DcmDecimalString, EVR_DS, rescaleIntercept) READ_FROM_DATASET(DcmDecimalString, EVR_DS, rescaleSlope) READ_FROM_DATASET(DcmLongString, EVR_LO, rescaleType) } /* read Modality LUT Sequence */ if (result==EC_Normal) { stack.clear(); if ((EC_Normal == dset.search(DCM_ModalityLUTSequence, stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_SQ)) { seq=(DcmSequenceOfItems *)stack.top(); if (seq->card() ==1) { item = seq->getItem(0); stack.clear(); // LUTDescriptor can be US or SS. For now we only handle US. if ((EC_Normal == item->search((DcmTagKey &)modalityLUTDescriptor.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US)) { modalityLUTDescriptor = *((DcmUnsignedShort *)(stack.top())); } stack.clear(); if ((EC_Normal == item->search((DcmTagKey &)modalityLUTExplanation.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_LO)) { modalityLUTExplanation = *((DcmLongString *)(stack.top())); } stack.clear(); // LUTData can be OW, US or SS. For now we only handle US. if ((EC_Normal == item->search((DcmTagKey &)modalityLUTData.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US)) { modalityLUTData = *((DcmUnsignedShort *)(stack.top())); } stack.clear(); if ((EC_Normal == item->search((DcmTagKey &)modalityLUTType.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_LO)) { modalityLUTType = *((DcmLongString *)(stack.top())); } } else { result=EC_TagNotFound; DCMPSTAT_WARN("Modality LUT SQ does not have exactly one item in presentation state"); } } } if (result==EC_Normal) result = overlayList.read(dset); if (result==EC_Normal) result = activationLayerList.read(dset); if (result==EC_Normal) result = graphicLayerList.read(dset); if (result==EC_Normal) result = referencedSeriesList.read(dset); if (result==EC_Normal) result = graphicAnnotationList.read(dset); if (result==EC_Normal) result = displayedAreaSelectionList.read(dset); if (result==EC_Normal) result = softcopyVOIList.read(dset); if (result==EC_Normal) result = presentationLUT.read(dset, OFFalse); /* Now perform basic sanity checks and adjust use flags */ if (result==EC_Normal) { if (patientName.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("patientName absent or empty in presentation state"); } else if (patientName.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("patientName VM != 1 in presentation state"); } if (studyInstanceUID.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("studyInstanceUID absent or empty in presentation state"); } else if (studyInstanceUID.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("studyInstanceUID VM != 1 in presentation state"); } if (displayedAreaSelectionList.size() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("displayedAreaSelectionSQ absent or empty in presentation state"); } if (imageNumber.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("instanceNumber absent or empty in presentation state"); } else if (imageNumber.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("instanceNumber VM != 1 in presentation state"); } if (presentationLabel.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("presentationLabel absent or empty in presentation state"); } else if (presentationLabel.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("presentationLabel VM != 1 in presentation state"); } if (presentationCreationDate.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("presentationCreationDate absent or empty in presentation state"); } else if (presentationCreationDate.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("presentationCreationDate VM != 1 in presentation state"); } if (presentationCreationTime.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("presentationCreationTime absent or empty in presentation state"); } else if (presentationCreationTime.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("presentationCreationTime VM != 1 in presentation state"); } if (sOPInstanceUID.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("sOPInstanceUID absent or empty in presentation state"); } else if (sOPInstanceUID.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("sOPInstanceUID VM != 1 in presentation state"); } /* if imageRotation or imageHorizontalFlip are present, then both must be present. */ if ((imageRotation.getLength() > 0)&&(imageHorizontalFlip.getLength() == 0)) { result=EC_IllegalCall; DCMPSTAT_WARN("imageRotation present but imageHorizontalFlip absent or empty in presentation state"); } if ((imageRotation.getLength() == 0)&&(imageHorizontalFlip.getLength() > 0)) { result=EC_IllegalCall; DCMPSTAT_WARN("imageHorizontalFlip present but imageRotation absent or empty in presentation state"); } /* Modality LUT */ if (rescaleIntercept.getLength() > 0) { useModalityRescale = OFTrue; if (rescaleSlope.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("rescaleIntercept present but rescaleSlope absent or empty in presentation state"); } else if (rescaleSlope.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("rescaleIntercept present but rescaleSlope VM != 1 in presentation state"); } if (rescaleType.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("rescaleIntercept present but rescaleType absent or empty in presentation state"); } else if (rescaleType.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("rescaleIntercept present but rescaleType VM != 1 in presentation state"); } if (rescaleIntercept.getVM() != 1) { result=EC_IllegalCall; DCMPSTAT_WARN("rescaleIntercept present but VM != 1 in presentation state"); } } else useModalityRescale = OFFalse; if (modalityLUTData.getLength() > 0) { useModalityLUT = OFTrue; if (modalityLUTDescriptor.getLength() == 0) { result=EC_IllegalCall; DCMPSTAT_WARN("modalityLUTData present but modalityLUTDescriptor absent or empty in presentation state"); } else if (modalityLUTDescriptor.getVM() != 3) { result=EC_IllegalCall; DCMPSTAT_WARN("modalityLUTData present but modalityLUTDescriptor VM != 3 in presentation state"); } } else useModalityLUT = OFFalse; /* we may not have both modality rescale and LUT */ if (useModalityRescale && useModalityLUT) { result=EC_IllegalCall; DCMPSTAT_WARN("both modality rescale and LUT present in presentation state"); } } /* end result==EC_Normal */ /* check shutters */ if (result==EC_Normal) { // now we examine the shutterShape for the Shutter modules Uint32 i; aString.clear(); useShutterRectangular=OFFalse; useShutterCircular=OFFalse; useShutterPolygonal=OFFalse; useShutterBitmap=OFFalse; for (i=0; i= 0x6000) { if (!overlayList.haveOverlayGroup(shuttergroup)) { result=EC_IllegalCall; DCMPSTAT_WARN("bitmap shutter specified but referenced overlay group missing in presentation state"); } } else { result=EC_IllegalCall; DCMPSTAT_WARN("wrong overlay group specified for bitmap shutter in presentation state"); } } /* check that referenced series list is non-empty and that every series contains images and that all referenced images share the same SOP class UID. */ if (result.good() && (!referencedSeriesList.isValid())) { // referencedSeriesList.isValid() has already displayed an error message in verbose mode result = EC_IllegalCall; } /* check that there is no mask module present. We don't support Mask and therefore are obliged to reject any presentation state containing a mask! */ stack.clear(); if (EC_Normal == dset.search(DCM_MaskSubtractionSequence, stack, ESM_fromHere, OFFalse)) { result=EC_IllegalCall; DCMPSTAT_WARN("mask module present in presentation state, but unsupported"); } stack.clear(); if (EC_Normal == dset.search(DCM_RecommendedViewingMode, stack, ESM_fromHere, OFFalse)) { result=EC_IllegalCall; DCMPSTAT_WARN("mask module present in presentation state, but unsupported"); } return result; } OFCondition DcmPresentationState::createDefaultDisplayedArea(DcmItem &dset) { DcmUnsignedShort rows(DCM_Rows); DcmUnsignedShort columns(DCM_Columns); DcmUniqueIdentifier sopclassUID(DCM_SOPClassUID); DcmUniqueIdentifier imageUID(DCM_SOPInstanceUID); DcmDecimalString imagerPixelSpacing(DCM_ImagerPixelSpacing); DcmDecimalString pixelSpacing(DCM_PixelSpacing); DcmIntegerString pixelAspectRatio(DCM_PixelAspectRatio); Uint16 cols_uint=0; Uint16 rows_uint=0; char *c_sopclassUID = NULL; char *c_imageUID = NULL; char *pixelspacing = NULL; OFCondition result = EC_Normal; DcmStack stack; READ_FROM_DATASET(DcmUnsignedShort, EVR_US, rows) READ_FROM_DATASET(DcmUnsignedShort, EVR_US, columns) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, sopclassUID) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, imageUID) READ_FROM_DATASET(DcmDecimalString, EVR_DS, imagerPixelSpacing) READ_FROM_DATASET(DcmDecimalString, EVR_DS, pixelSpacing) READ_FROM_DATASET(DcmIntegerString, EVR_IS, pixelAspectRatio) if (result == EC_Normal) result = columns.getUint16(cols_uint,0); if (result == EC_Normal) result = rows.getUint16(rows_uint,0); if (result == EC_Normal) result = sopclassUID.getString(c_sopclassUID); if (result == EC_Normal) result = imageUID.getString(c_imageUID); /* create displayed area selection item for this image */ if (EC_Normal == result) { DVPSDisplayedArea *area = displayedAreaSelectionList.createDisplayedArea( referencedSeriesList, c_sopclassUID, c_imageUID, 1, 1, DVPSB_currentImage); if (area) { if (EC_Normal == result) result = area->setDisplayedArea(DVPSD_scaleToFit, (Sint32)1, (Sint32)1, (Sint32)cols_uint, (Sint32)rows_uint); if (EC_Normal == result) { OFBool foundRatio = OFFalse; if ((imagerPixelSpacing.getVM()==2)&&(EC_Normal==imagerPixelSpacing.getString(pixelspacing))) { result = area->setDisplayedAreaPixelSpacing(pixelspacing); if (EC_Normal==result) foundRatio = OFTrue; } if ((! foundRatio)&&(pixelSpacing.getVM()==2)&&(EC_Normal==pixelSpacing.getString(pixelspacing))) { result = area->setDisplayedAreaPixelSpacing(pixelspacing); if (EC_Normal==result) foundRatio = OFTrue; } if ((! foundRatio)&&(pixelAspectRatio.getVM()==2)&&(EC_Normal==pixelAspectRatio.getString(pixelspacing))) { result = area->setDisplayedAreaPixelAspectRatio(pixelspacing); if (EC_Normal==result) foundRatio = OFTrue; } if (! foundRatio) result = area->setDisplayedAreaPixelAspectRatio(1.0); } } else result = EC_MemoryExhausted; } return result; } OFCondition DcmPresentationState::createFromImage( DcmItem &dset, DVPSoverlayActivation overlayActivation, DVPSVOIActivation voiActivation, OFBool curveActivation, OFBool shutterActivation, OFBool presentationActivation, DVPSGraphicLayering layering, const char *aetitle, const char *filesetID, const char *filesetUID) { OFCondition result = EC_Normal; DcmStack stack; DcmSequenceOfItems *seq; DcmItem *item; char uid[100]; OFString aString; OFString ofsopclassUID; OFString ofimageUID; OFBool isMonochrome1 = OFFalse; DcmUniqueIdentifier sopclassUID(DCM_SOPClassUID); DcmUniqueIdentifier imageUID(DCM_SOPInstanceUID); DcmCodeString photometricInterpretation(DCM_PhotometricInterpretation); DcmCodeString presentationLUTShape(DCM_PresentationLUTShape); clear(); // re-initialize Presentation State object /* copy some image attributes we will need later */ READ_FROM_DATASET(DcmCodeString, EVR_CS, photometricInterpretation) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, sopclassUID) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, imageUID) sopclassUID.getOFString(ofsopclassUID,0); imageUID.getOFString(ofimageUID,0); /* copy attributes for Patient, General Study and General Equipment * modules from image object. Also copy specific character set (SOP common). */ READ_FROM_DATASET(DcmPersonName, EVR_PN, patientName) READ_FROM_DATASET(DcmLongString, EVR_LO, patientID) READ_FROM_DATASET(DcmDate, EVR_DA, patientBirthDate) READ_FROM_DATASET(DcmCodeString, EVR_CS, patientSex) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, studyInstanceUID) READ_FROM_DATASET(DcmDate, EVR_DA, studyDate) READ_FROM_DATASET(DcmTime, EVR_TM, studyTime) READ_FROM_DATASET(DcmPersonName, EVR_PN, referringPhysicianName) READ_FROM_DATASET(DcmShortString, EVR_SH, studyID) READ_FROM_DATASET(DcmShortString, EVR_SH, accessionNumber) READ_FROM_DATASET(DcmLongString, EVR_LO, manufacturer) READ_FROM_DATASET(DcmCodeString, EVR_CS, specificCharacterSet) /* if there is a modality rescale, copy it now. * Later we decide whether we want to use it. */ READ_FROM_DATASET(DcmDecimalString, EVR_DS, rescaleIntercept) READ_FROM_DATASET(DcmDecimalString, EVR_DS, rescaleSlope) READ_FROM_DATASET(DcmLongString, EVR_LO, rescaleType) if ((result==EC_Normal) && shutterActivation) { /* if there is a display shutter in the image (i.e. in XA, RF, DX), copy it. * We never copy bitmap shutters. */ READ_FROM_DATASET(DcmCodeString, EVR_CS, shutterShape) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterLeftVerticalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterRightVerticalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterUpperHorizontalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, shutterLowerHorizontalEdge) READ_FROM_DATASET(DcmIntegerString, EVR_IS, centerOfCircularShutter) READ_FROM_DATASET(DcmIntegerString, EVR_IS, radiusOfCircularShutter) READ_FROM_DATASET(DcmIntegerString, EVR_IS, verticesOfThePolygonalShutter) READ_FROM_DATASET(DcmUnsignedShort, EVR_US, shutterPresentationValue) } if ((result==EC_Normal) && presentationActivation) { /* if there is a Presentation LUT shape in the image (i.e. in DX), copy it. * We never copy presentation LUT sequences. */ READ_FROM_DATASET(DcmCodeString, EVR_CS, presentationLUTShape) } /* read Modality LUT Sequence */ if (result==EC_Normal) { stack.clear(); if ((EC_Normal == dset.search(DCM_ModalityLUTSequence, stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_SQ)) { seq=(DcmSequenceOfItems *)stack.top(); if (seq->card() >0) { item = seq->getItem(0); stack.clear(); // LUTDescriptor can be US or SS. For now we only handle US. if ((EC_Normal == item->search((DcmTagKey &)modalityLUTDescriptor.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US)) { modalityLUTDescriptor = *((DcmUnsignedShort *)(stack.top())); } stack.clear(); if ((EC_Normal == item->search((DcmTagKey &)modalityLUTExplanation.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_LO)) { modalityLUTExplanation = *((DcmLongString *)(stack.top())); } stack.clear(); // LUTData can be OW, US or SS. For now we only handle US. if ((EC_Normal == item->search((DcmTagKey &)modalityLUTData.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US)) { modalityLUTData = *((DcmUnsignedShort *)(stack.top())); } stack.clear(); if ((EC_Normal == item->search((DcmTagKey &)modalityLUTType.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_LO)) { modalityLUTType = *((DcmLongString *)(stack.top())); } } else result=EC_TagNotFound; } } /* copy overlays if appropriate */ if ((result==EC_Normal)&&(overlayActivation==DVPSO_copyOverlays)) result = overlayList.read(dset); /* Now perform basic sanity checks and adjust use flags */ if ((studyInstanceUID.getLength() == 0)||(studyInstanceUID.getVM() != 1)) result=EC_IllegalCall; if (photometricInterpretation.getVM() == 1) { aString.clear(); photometricInterpretation.getOFString(aString,0); if ((aString == "MONOCHROME1")||(aString == "MONOCHROME 1")) isMonochrome1 = OFTrue; else if ((aString != "MONOCHROME2")&&(aString != "MONOCHROME 2")) { result = EC_IllegalCall; DCMPSTAT_WARN("Wrong image photometric interpretation - not MONOCHROME1/2"); } } if (result==EC_Normal) { if ((patientName.getLength() == 0)||(patientName.getVM() != 1)) result = patientName.putString(DEFAULT_patientName); } if (result==EC_Normal) { result = imageNumber.putString(DEFAULT_imageNumber); } if (result==EC_Normal) { result = presentationLabel.putString(DEFAULT_presentationLabel); } if (result==EC_Normal) { aString.clear(); DVPSHelper::currentDate(aString); result = presentationCreationDate.putString(aString.c_str()); } if (result==EC_Normal) { aString.clear(); DVPSHelper::currentTime(aString); result = presentationCreationTime.putString(aString.c_str()); } if (result==EC_Normal) result = seriesInstanceUID.putString(dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT)); if (result==EC_Normal) result = sOPInstanceUID.putString(dcmGenerateUniqueIdentifier(uid)); if (result==EC_Normal) result = seriesNumber.putString(DEFAULT_seriesNumber); /* If no other character set is specified by the image, we use ISO_IR 100 as the default */ if ((result==EC_Normal) && (specificCharacterSet.getLength() == 0)) result = specificCharacterSet.putString(DEFAULT_specificCharacterSet); if (result==EC_Normal) { /* Presentation LUT Shape */ if (isMonochrome1) presentationLUT.setType(DVPSP_inverse); else presentationLUT.setType(DVPSP_identity); if (presentationLUTShape.getVM() == 1) { aString.clear(); presentationLUTShape.getOFString(aString,0); if (aString == "IDENTITY") presentationLUT.setType(DVPSP_identity); if (aString == "INVERSE") presentationLUT.setType(DVPSP_inverse); if (aString == "LIN OD") { DCMPSTAT_WARN("LIN OD found in presentation state; set to IDENTITY"); presentationLUT.setType(DVPSP_identity); } } } if (result==EC_Normal) { /* Modality LUT */ if ((rescaleIntercept.getVM() == 1) && (rescaleSlope.getVM() == 1)) { useModalityRescale = OFTrue; modalityLUTData.clear(); modalityLUTDescriptor.clear(); modalityLUTExplanation.clear(); modalityLUTType.clear(); // be lenient with Modality rescale type. If missing or wrong, just invent a value. if (rescaleType.getVM() != 1) rescaleType.putString("US"); } else useModalityRescale = OFFalse; // these three SOP classes use the X-Ray Image Module in which the meaning // of the Modality LUT transformation is "inversersed" and, therefore, // must not be copied into the presentation state if ((ofsopclassUID == UID_XRayAngiographicImageStorage) || (ofsopclassUID == UID_XRayRadiofluoroscopicImageStorage) || (ofsopclassUID == UID_RETIRED_XRayAngiographicBiPlaneImageStorage)) { modalityLUTData.clear(); modalityLUTDescriptor.clear(); modalityLUTExplanation.clear(); modalityLUTType.clear(); useModalityLUT = OFFalse; } if ((modalityLUTDescriptor.getVM() == 3) && (modalityLUTData.getLength() > 0)) { useModalityLUT = OFTrue; rescaleIntercept.clear(); rescaleSlope.clear(); rescaleType.clear(); } else useModalityLUT = OFFalse; } /* check shutters */ if (result==EC_Normal) { // now we examine the shutterShape for the Shutter modules Uint32 i; aString.clear(); useShutterRectangular=OFFalse; useShutterCircular=OFFalse; useShutterPolygonal=OFFalse; useShutterBitmap=OFFalse; for (i=0; i0) aString += '\\'; aString += "CIRCULAR"; } if (useShutterPolygonal) { if (aString.size() >0) aString += '\\'; aString += "POLYGONAL"; } shutterShape.putString(aString.c_str()); if ((shutterPresentationValue.getLength() == 0)||(shutterPresentationValue.getVM() != 1)) { shutterPresentationValue.clear(); shutterPresentationValue.putUint16(DEFAULT_shutterPresentationValue,0); } } } /* browse the image for overlays and curves, create activation tags and * graphic layers as appropriate. */ if (result==EC_Normal) result = activationLayerList.createFromImage(dset, graphicLayerList, overlayList, overlayActivation, curveActivation, layering); /* create reference for this image */ if (EC_Normal == result) result = addImageReference(dset, aetitle, filesetID, filesetUID); /* create displayed area selection item for this image */ if (EC_Normal == result) result = createDefaultDisplayedArea(dset); /* create softcopy VOI LUT sequence item for this image if necessary */ if (EC_Normal == result) result = softcopyVOIList.createFromImage(dset, referencedSeriesList, ofsopclassUID.c_str(), ofimageUID.c_str(), voiActivation); return result; } OFCondition DcmPresentationState::write(DcmItem &dset, OFBool replaceSOPInstanceUID) { OFCondition result = EC_Normal; DcmElement *delem=NULL; DcmSequenceOfItems *dseq=NULL; DcmItem *ditem=NULL; cleanupLayers(); /* remove unused layers */ createDummyValues(replaceSOPInstanceUID); /* add SOP Class UID */ DcmUniqueIdentifier sopclassuid(DCM_SOPClassUID); if (result==EC_Normal) { result = sopclassuid.putString(UID_GrayscaleSoftcopyPresentationStateStorage); } ADD_TO_DATASET(DcmUniqueIdentifier, sopclassuid) /* add Modality */ DcmCodeString modality(DCM_Modality); if (result==EC_Normal) { result = modality.putString("PR"); } ADD_TO_DATASET(DcmCodeString, modality) ADD_TO_DATASET(DcmPersonName, patientName) ADD_TO_DATASET(DcmLongString, patientID) ADD_TO_DATASET(DcmDate, patientBirthDate) ADD_TO_DATASET(DcmCodeString, patientSex) ADD_TO_DATASET(DcmUniqueIdentifier, studyInstanceUID) ADD_TO_DATASET(DcmDate, studyDate) ADD_TO_DATASET(DcmTime, studyTime) ADD_TO_DATASET(DcmPersonName, referringPhysicianName) ADD_TO_DATASET(DcmShortString, studyID) ADD_TO_DATASET(DcmShortString, accessionNumber) ADD_TO_DATASET(DcmCodeString, modality) ADD_TO_DATASET(DcmUniqueIdentifier, seriesInstanceUID) ADD_TO_DATASET(DcmIntegerString, seriesNumber) ADD_TO_DATASET(DcmLongString, manufacturer) ADD_TO_DATASET(DcmIntegerString, imageNumber) ADD_TO_DATASET(DcmCodeString, presentationLabel) ADD_TO_DATASET(DcmLongString, presentationDescription) ADD_TO_DATASET(DcmDate, presentationCreationDate) ADD_TO_DATASET(DcmTime, presentationCreationTime) ADD_TO_DATASET(DcmPersonName, presentationCreatorsName) ADD_TO_DATASET(DcmUniqueIdentifier, sOPInstanceUID) if (specificCharacterSet.getLength() >0) { ADD_TO_DATASET(DcmCodeString, specificCharacterSet) } if (instanceCreationDate.getLength() >0) { ADD_TO_DATASET(DcmDate, instanceCreationDate) } if (instanceCreationTime.getLength() >0) { ADD_TO_DATASET(DcmTime, instanceCreationTime) } if (instanceCreatorUID.getLength() >0) { ADD_TO_DATASET(DcmUniqueIdentifier, instanceCreatorUID) } shutterShape.clear(); if (useShutterRectangular || useShutterCircular || useShutterPolygonal) { OFString aString; if (useShutterRectangular) aString = "RECTANGULAR"; if (useShutterCircular) { if (aString.size() > 0) aString += '\\'; aString += "CIRCULAR"; } if (useShutterPolygonal) { if (aString.size() > 0) aString += '\\'; aString += "POLYGONAL"; } shutterShape.putString(aString.c_str()); } else if (useShutterBitmap) { shutterShape.putString("BITMAP"); } if (useShutterRectangular || useShutterCircular || useShutterPolygonal) { ADD_TO_DATASET(DcmCodeString, shutterShape) ADD_TO_DATASET(DcmUnsignedShort, shutterPresentationValue) if (useShutterRectangular) { ADD_TO_DATASET(DcmIntegerString, shutterLeftVerticalEdge) ADD_TO_DATASET(DcmIntegerString, shutterRightVerticalEdge) ADD_TO_DATASET(DcmIntegerString, shutterUpperHorizontalEdge) ADD_TO_DATASET(DcmIntegerString, shutterLowerHorizontalEdge) } if (useShutterCircular) { ADD_TO_DATASET(DcmIntegerString, centerOfCircularShutter) ADD_TO_DATASET(DcmIntegerString, radiusOfCircularShutter) } if (useShutterPolygonal) { ADD_TO_DATASET(DcmIntegerString, verticesOfThePolygonalShutter) } } else if (useShutterBitmap) { ADD_TO_DATASET(DcmCodeString, shutterShape) ADD_TO_DATASET(DcmUnsignedShort, shutterPresentationValue) ADD_TO_DATASET(DcmUnsignedShort, shutterOverlayGroup) } if (EC_Normal == result) result = referencedSeriesList.write(dset); if (EC_Normal == result) result = overlayList.write(dset); if (EC_Normal == result) result = activationLayerList.write(dset); if (EC_Normal == result) result = graphicAnnotationList.write(dset); if (EC_Normal == result) result = displayedAreaSelectionList.write(dset); if (EC_Normal == result) result = softcopyVOIList.write(dset); if (EC_Normal == result) result = graphicLayerList.write(dset); if (EC_Normal == result) result = presentationLUT.write(dset, OFFalse); // strictly speaking we are not allowed to include the Spatial Transformation // Module if neither rotation nor flipping are needed. OFString aString; OFBool haveRotation=OFFalse; OFBool haveFlip=OFFalse; if (imageRotation.getVM() == 1) { Uint16 urot=0; imageRotation.getUint16(urot,0); if (urot) haveRotation=OFTrue; } if (imageHorizontalFlip.getLength() > 0) { imageHorizontalFlip.getOFString(aString, 0, OFTrue); if (aString == "Y") haveFlip=OFTrue; } if (haveRotation || haveFlip) { ADD_TO_DATASET(DcmUnsignedShort, imageRotation) ADD_TO_DATASET(DcmCodeString, imageHorizontalFlip) } if (useModalityRescale) { ADD_TO_DATASET(DcmDecimalString, rescaleIntercept) ADD_TO_DATASET(DcmDecimalString, rescaleSlope) ADD_TO_DATASET(DcmLongString, rescaleType) } else if (useModalityLUT) { if (result == EC_Normal) { ditem = new DcmItem(); if (ditem) { dseq = new DcmSequenceOfItems(DCM_ModalityLUTSequence); if (dseq) { delem = new DcmUnsignedShort(modalityLUTDescriptor); if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted; delem = new DcmUnsignedShort(modalityLUTData); if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted; delem = new DcmLongString(modalityLUTType); if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted; if (modalityLUTExplanation.getLength() >0) { delem = new DcmLongString(modalityLUTExplanation); if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted; } if (result==EC_Normal) { dseq->insert(ditem); dset.insert(dseq, OFTrue /*replaceOld*/); } else { // out of memory during creation of sequence contents. delete dseq; delete ditem; result = EC_MemoryExhausted; } } else { // could allocate item but not sequence. Bail out. delete ditem; result = EC_MemoryExhausted; } } else result = EC_MemoryExhausted; } } return result; } OFCondition DcmPresentationState::addImageReference( const char *studyUID, const char *seriesUID, const char *sopclassUID, const char *instanceUID, const char *frames, const char *aetitle, const char *filesetID, const char *filesetUID) { if ((studyUID==NULL)||(seriesUID==NULL)||(sopclassUID==NULL)||(instanceUID==NULL)) return EC_IllegalCall; OFString study; studyInstanceUID.getOFString(study,0); if (study != studyUID) { DCMPSTAT_WARN("cannot add reference to image with different Study Instance UID."); return EC_IllegalCall; } return referencedSeriesList.addImageReference(seriesUID, sopclassUID, instanceUID, frames, aetitle, filesetID, filesetUID); } OFCondition DcmPresentationState::addImageReference( DcmItem &dset, const char *aetitle, const char *filesetID, const char *filesetUID) { DcmIntegerString numberOfFrames(DCM_NumberOfFrames); DcmUniqueIdentifier studyUID(DCM_StudyInstanceUID); DcmUniqueIdentifier seriesUID(DCM_SeriesInstanceUID); DcmUniqueIdentifier sopclassUID(DCM_SOPClassUID); DcmUniqueIdentifier imageUID(DCM_SOPInstanceUID); OFString ofstudyUID; OFString ofseriesUID; OFString ofsopclassUID; OFString ofimageUID; OFString aString; char buf[20]; Sint32 i=0; Sint32 ofnumberOfFrames=0; DcmStack stack; READ_FROM_DATASET(DcmIntegerString, EVR_IS, numberOfFrames) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, studyUID) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, seriesUID) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, sopclassUID) READ_FROM_DATASET(DcmUniqueIdentifier, EVR_UI, imageUID) numberOfFrames.getSint32(ofnumberOfFrames,0); seriesUID.getOFString(ofseriesUID,0); sopclassUID.getOFString(ofsopclassUID,0); imageUID.getOFString(ofimageUID,0); studyUID.getOFString(ofstudyUID,0); OFCondition result = EC_Normal; /* if the image is multiframe, reference all frames */ if (ofnumberOfFrames > 1) { for (i=0; igetOverlayGroup()); return 0; } const char *DcmPresentationState::getOverlayInPresentationStateLabel(size_t idx) { DVPSOverlay *overlay = overlayList.getOverlay(idx); if (overlay) return overlay->getOverlayLabel(); return NULL; } const char *DcmPresentationState::getOverlayInPresentationStateDescription(size_t idx) { DVPSOverlay *overlay = overlayList.getOverlay(idx); if (overlay) return overlay->getOverlayDescription(); return NULL; } size_t DcmPresentationState::getOverlayInPresentationStateActivationLayer(size_t idx) { DVPSOverlay *overlay = overlayList.getOverlay(idx); if (overlay) { const char *layerName = activationLayerList.getActivationLayer(0x6000+overlay->getOverlayGroup()); if (layerName) return graphicLayerList.getGraphicLayerIndex(layerName); } return DVPS_IDX_NONE; } OFBool DcmPresentationState::overlayIsBitmapShutter(size_t idx) { if (shutterOverlayGroup.getLength() == 0) return OFFalse; Uint16 shutterGroup=0; if (EC_Normal == shutterOverlayGroup.getUint16(shutterGroup,0)) { DVPSOverlay *overlay = overlayList.getOverlay(idx); if (overlay) return (shutterGroup == 0x6000+overlay->getOverlayGroup()); } return OFFalse; } OFBool DcmPresentationState::overlayInPresentationStateIsROI(size_t idx) { DVPSOverlay *overlay = overlayList.getOverlay(idx); if (overlay) return overlay->isROI(); return OFFalse; } OFCondition DcmPresentationState::moveOverlay(size_t old_layer, size_t idx, size_t new_layer) { const char *lname = graphicLayerList.getGraphicLayerName(new_layer); if (lname==NULL) return EC_IllegalCall; Uint16 group = activationLayerList.getActivationGroup( graphicLayerList.getGraphicLayerName(old_layer), idx, OFFalse); if (group == 0) return EC_IllegalCall; activationLayerList.removeActivation(group); return activationLayerList.setActivation(group, lname); }