/* * * Copyright (C) 1996-2015, 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: dcmimgle * * Author: Joerg Riesmeier * * Purpose: DicomOverlayPlane (Header) * */ #ifndef DIOVPLN_H #define DIOVPLN_H #include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/ofstring.h" #include "dcmtk/ofstd/ofcast.h" #include "dcmtk/dcmimgle/diutils.h" #define INCLUDE_CSTDDEF #include "dcmtk/ofstd/ofstdinc.h" /*------------------------* * forward declarations * *------------------------*/ class DcmOverlayData; class DcmLongString; class DiDocument; /*---------------------* * class declaration * *---------------------*/ /** Class to handle a single overlay plane */ class DCMTK_DCMIMGLE_EXPORT DiOverlayPlane { public: /** constructor * ** @param docu pointer to dataset (encapsulated) * @param group group number of the overlay plane * @param alloc value for bits allocated of the surrounding image * @param stored value for bits stored of the surrounding image * @param high value for high bit of the surrounding image */ DiOverlayPlane(const DiDocument *docu, const unsigned int group, Uint16 alloc, const Uint16 stored, const Uint16 high); /** constructor, additional * ** @param group group number of the overlay plane * @param left_pos x-coordinate of the plane origin * @param top_pos y-coordinate of the plane origin * @param columns width of the overlay plane * @param rows height of the overlay plane * @param data element containing the plane data * @param label element containing the plane label * @param description element containing the plane description * @param mode overlay plane mode */ DiOverlayPlane(const unsigned int group, const Sint16 left_pos, const Sint16 top_pos, const Uint16 columns, const Uint16 rows, const DcmOverlayData &data, const DcmLongString &label, const DcmLongString &description, const EM_Overlay mode); /** constructor, copy * ** @param plane reference overlay plane to be copied * @param bit position of the plane bit * @param data pointer to buffer for plane data * @param temp temporary buffer used to extract plane information * @param width width of the array where the plane is stored * @param height height of the array where the plane is stored * @param columns width of the overlay plane * @param rows height of the overlay plane */ DiOverlayPlane(DiOverlayPlane *plane, const unsigned int bit, Uint16 *data, Uint16 *temp, const Uint16 width, const Uint16 height, const Uint16 columns, const Uint16 rows); /** destructor */ ~DiOverlayPlane(); /** get x-coordinate of overlay plane origin * ** @param left_pos offset to be subtracted from the actual value (optional) * ** @return x-coordinate of overlay plane origin */ inline Sint16 getLeft(const Sint32 left_pos = 0) const { return OFstatic_cast(Sint16, OFstatic_cast(Sint32, Left) - left_pos); } /** get y-coordinate of overlay plane origin * ** @param top_pos offset to be subtracted from the actual value (optional) * ** @return y-coordinate of overlay plane origin */ inline Sint16 getTop(const Sint32 top_pos = 0) const { return OFstatic_cast(Sint16, OFstatic_cast(Sint32, Top) - top_pos); } /** get width of overlay plane * ** @return width of overlay plane */ inline Uint16 getWidth() const { return Width; } /** get height of overlay plane * ** @return height of overlay plane */ inline Uint16 getHeight() const { return Height; } /** get right border of overlay plane origin * ** @param left_pos offset to be subtracted from the actual value (optional). * ** @return right border of overlay plane origin. Negative values are set to 0. */ inline Uint16 getRight(const Sint32 left_pos = 0) const { return (OFstatic_cast(Sint32, Left) + OFstatic_cast(Sint32, Width) - left_pos > 0) ? OFstatic_cast(Uint16, OFstatic_cast(Sint32, Left) + OFstatic_cast(Sint32, Width) - left_pos) : 0; } /** get bottom border of overlay plane origin * ** @param top_pos offset to be subtracted from the actual value (optional). * ** @return bottom border of overlay plane origin. Negative values are set to 0. */ inline Uint16 getBottom(const Sint32 top_pos = 0) const { return (OFstatic_cast(Sint32, Top) + OFstatic_cast(Sint32, Height) - top_pos > 0) ? OFstatic_cast(Uint16, OFstatic_cast(Sint32, Top) + OFstatic_cast(Sint32, Height) - top_pos) : 0; } /** check whether overlay plane is valid * ** @return true if plane is valid, false otherwise */ inline int isValid() const { return Valid; } /** check whether overlay plane is visible * ** @return true if plane is visible, false otherwise */ inline int isVisible() const { return Visible; } /** make overlay plane visible */ inline void show() { Visible = 1; } /** make overlay plane invisible */ inline void hide() { Visible = 0; } /** move overlay plane to a new place * ** @param left_pos x-coordinate of the new plane origin (maybe negative) * @param top_pos y-coordinate of the new plane origin (maybe negative) */ void place(const signed int left_pos, const signed int top_pos); /** set scaling factor in x- and y-direction * ** @param xfactor scaling factor in x-direction * @param yfactor scaling factor in y-direction */ void setScaling(const double xfactor, const double yfactor); /** set flipping * ** @param horz flip horizontally if true * @param vert flip vertically if true * @param columns width of surrounding image (incl. origin offset) * @param rows height of surrounding image (incl. origin offset) */ void setFlipping(const int horz, const int vert, const signed long columns, const signed long rows); /** set rotation * ** @param degree angle by which the plane should be rotated * @param left_pos x-coordinate of the origin for all overlay planes * @param top_pos y-coordinate of the origin for all overlay planes * @param columns width of surrounding image (already rotated) * @param rows height of surrounding image (already rotated) */ void setRotation(const int degree, const signed long left_pos, const signed long top_pos, const Uint16 columns, const Uint16 rows); /** make overlay plane visible and set parameters * ** @param fore foreground color of the plane (in percent: 0.0-1.0) * @param thresh threshold value for 'threshold replace' (0.0-1.0) * @param mode new overlay plane mode (EMO_Default for stored mode) */ void show(const double fore, const double thresh, const EM_Overlay mode); /** make overlay plane visible and set p-value. * Only applicable for bitmap shutters. * ** @param pvalue p-value to be used for the overlay plane (0..65535) * ** @return status, true if successful, false otherwise */ int show(const Uint16 pvalue); /** get number of frames * ** @return number of frames */ inline unsigned long getNumberOfFrames() const { return NumberOfFrames; } /** get foreground color of the plane * ** @return foreground color (in percent: 0.0-1.0) */ inline double getForeground() const { return Foreground; } /** get threshold value of the plane * ** @return threshold value (in percent: 0.0-1.0) */ inline double getThreshold() const { return Threshold; } /** get p-value of the plane. * Only valid for bitmap shutters. * ** @return p-value (0..65535) */ inline Uint16 getPValue() const { return PValue; } /** get overlay plane mode * ** @return overlay plane mode */ inline EM_Overlay getMode() const { return Mode; } /** check whether overlay plane is embedded in the pixel data * ** @return true if plane is embedded, false otherwise */ inline int isEmbedded() const { return EmbeddedData; } /** get label of overlay plane * ** @return label if successful, NULL otherwise */ const char *getLabel() const { return (Label.empty()) ? OFstatic_cast(const char *, NULL) : Label.c_str(); } /** get description of overlay plane * ** @return description if successful, NULL otherwise */ const char *getDescription() const { return (Description.empty()) ? OFstatic_cast(const char *, NULL) : Description.c_str(); } /** get group number of overlay plane * ** @return group number (0x6000-0x60ff) */ Uint16 getGroupNumber() const { return GroupNumber; } /** get overlay plane data as an array of 1/8/16 bit values. * Overlay plane is clipped to the area specified by the four min/max coordinates. * Memory isn't handled internally and must therefore be deleted from calling program. * ** @param frame number of frame * @param xmin x-coordinate of the top left hand corner * @param ymin y-coordinate of the top left hand corner * @param xmax x-coordinate of the bottom right hand corner * @param ymax y-coordinate of the bottom right hand corner * @param bits number of bits (stored) in the resulting array * @param fore foreground color used for the plane (0x00-0xff) * @param back transparent background color (0x00-0xff) * ** @return pointer to pixel data if successful, NULL otherwise */ void *getData(const unsigned long frame, const Uint16 xmin, const Uint16 ymin, const Uint16 xmax, const Uint16 ymax, const int bits, const Uint16 fore, const Uint16 back); /** create overlay plane data in (6xxx,3000) format. * (1 bit allocated and stored, foreground color is 1, background color is 0, * data is 16 bit padded - even length) * Memory isn't handled internally and must therefore be deleted from calling program. * ** @param buffer stores pointer to overlay data (memory is allocated internally) * @param width returns width of overlay plane (in pixels) * @param height returns height of overlay plane (in pixels) * @param frames returns number of frames (multiple overlay frames possible!) * ** @return number of bytes allocated for the 'buffer' if successful, 0 otherwise */ unsigned long create6xxx3000Data(Uint8 *&buffer, unsigned int &width, unsigned int &height, unsigned long &frames); /** reset internal 'cursor' to the beginning of the specified frame * ** @param frame number of current frame * ** @return status, true if successful, false otherwise */ inline int reset(const unsigned long frame); /** get value of the current overlay plane bit and move 'cursor' to the next position * ** @return true if plane bit is set, false otherwise */ inline int getNextBit(); /** set internal 'cursor' to a specific position * ** @param x new x-coordinate to start from * @param y new y-coordinate to start from */ inline void setStart(const Uint16 x, const Uint16 y); protected: /// number of frames Uint32 NumberOfFrames; /// number of starting frame Uint16 ImageFrameOrigin; /// first frame to be processed (from DicomImage constructor) Uint32 FirstFrame; /// y-coordinate of overlay plane's origin Sint16 Top; /// x-coordinate of overlay plane's origin Sint16 Left; /// visible height Uint16 Height; /// visible width Uint16 Width; /// number of (stored) rows Uint16 Rows; /// number of (stored) columns Uint16 Columns; /// number of allocated bits per pixel Uint16 BitsAllocated; /// position of overlay plane bit Uint16 BitPosition; /// "color" of overlay plane (in percent: '0.0' = dark, '1.0' = bright) double Foreground; /// threshold value used for "threshold replace" double Threshold; /// P-value used for bitmap shutters Uint16 PValue; /// current overlay mode EM_Overlay Mode; /// default (stored) overlay mode EM_Overlay DefaultMode; /// label of overlay plane OFString Label; /// textual description of overlay plane OFString Description; /// group number of overlay plane Uint16 GroupNumber; /// validity status int Valid; /// visibility status int Visible; private: /// current bit position unsigned long BitPos; /// starting bit position of current frame unsigned long StartBitPos; /// x-coordinate of first pixel in surrounding memory buffer unsigned int StartLeft; /// y-coordinate of first pixel in surrounding memory buffer unsigned int StartTop; /// true, if overlay data in embedded in pixel data int EmbeddedData; /// pointer to current element of 'Data' const Uint16 *Ptr; /// pointer to starting element of current frame const Uint16 *StartPtr; /// pointer to overlay data (standalone) or pixel data (embedded) const Uint16 *Data; // --- declarations to avoid compiler warnings DiOverlayPlane(const DiOverlayPlane &); DiOverlayPlane &operator=(const DiOverlayPlane &); }; /********************************************************************/ inline int DiOverlayPlane::reset(const unsigned long frame) { int result = 0; if (Valid && (Data != NULL)) { const Uint32 frameNumber = OFstatic_cast(Uint32, FirstFrame + frame); DCMIMGLE_TRACE("reset overlay plane in group 0x" << STD_NAMESPACE hex << GroupNumber << " to start position"); DCMIMGLE_TRACE(" frameNumber: " << frameNumber << " (" << FirstFrame << "+" << frame << "), ImageFrameOrigin: " << ImageFrameOrigin << ", NumberOfFrames: " << NumberOfFrames); if ((frameNumber >= ImageFrameOrigin) && (frameNumber < ImageFrameOrigin + NumberOfFrames)) { const unsigned long bits = (OFstatic_cast(unsigned long, StartLeft) + OFstatic_cast(unsigned long, StartTop) * OFstatic_cast(unsigned long, Columns) + (frameNumber - ImageFrameOrigin) * OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns)) * OFstatic_cast(unsigned long, BitsAllocated); StartBitPos = BitPos = OFstatic_cast(unsigned long, BitPosition) + bits; DCMIMGLE_TRACE(" StartBitPos: " << StartBitPos << ", BitPosition: " << BitPosition << ", bits: " << bits); /* distinguish between embedded and separate overlay data */ if (BitsAllocated == 16) StartPtr = Ptr = Data + (bits >> 4); else StartPtr = Data; result = (getRight() > 0) && (getBottom() > 0); } else DCMIMGLE_TRACE(" -> overlay plane does not apply to this frame"); } return result; } inline int DiOverlayPlane::getNextBit() { int result; if (BitsAllocated == 16) // optimization result = OFstatic_cast(int, *(Ptr++) & (1 << BitPosition)); else { Ptr = StartPtr + (BitPos >> 4); // div 16 result = OFstatic_cast(int, *Ptr & (1 << (BitPos & 0xf))); // mod 16 BitPos += BitsAllocated; // next bit } return result; } inline void DiOverlayPlane::setStart(const Uint16 x, const Uint16 y) { if (BitsAllocated == 16) Ptr = StartPtr + OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + OFstatic_cast(unsigned long, x - Left); else BitPos = StartBitPos + (OFstatic_cast(unsigned long, y - Top) * OFstatic_cast(unsigned long, Columns) + OFstatic_cast(unsigned long, x - Left)) * OFstatic_cast(unsigned long, BitsAllocated); } #endif