/* * * Copyright (C) 2015-2019, Open Connections GmbH * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation are maintained by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: dcmseg * * Author: Michael Onken * * Purpose: Helper functions for the dcmseg module * */ #ifndef SEGUTILS_H #define SEGUTILS_H #include "dcmtk/config/osconfig.h" #include "dcmtk/dcmseg/segdef.h" #include "dcmtk/dcmseg/segtypes.h" /** Class that contains helper functionality for the dcmseg module */ class DCMTK_DCMSEG_EXPORT DcmSegUtils { public: /** Pack the given segmentation pixel data, provided "unpacked", into * the packed format expected by DICOM * @param pixelData Pixel data in unpacked format * @param rows Number of rows in the pixel data * @param columns The number of columns in the pixel data * @return The frame data if successful, NULL if an error occurs */ static DcmIODTypes::Frame* packBinaryFrame(const Uint8* pixelData, const Uint16 rows, const Uint16 columns); /** Compute the number of bytes required for a binary pixel data frame, * given the number of pixels * @param numPixels The total number of pixels * @return The number of bytes required to pack the data into a binary * segmentation frame */ static size_t getBytesForBinaryFrame(const size_t& numPixels); /** Unpacks a binary segmentation frame into a "sparse" pixel data frame where * every resulting byte represents a single bit of the frame being either * 0 (not set) or 1 (set). * @param frame The input buffer with the frame in packed format * @param rows The rows of the frame * @param cols The cols of the frame * @return The segmentation frame in unpacked format. NULL in case of error. */ static DcmIODTypes::Frame* unpackBinaryFrame(const DcmIODTypes::Frame* frame, Uint16 rows, Uint16 cols); /** Aligns 1 bit per pixel frame data to make the frame start at a * specific bit position within the first byte. This is used in the context * that dcmseg holds the frames in memory aligned to exact byte positions, * while the DICOM encoding might require a frame to start at an arbitrary * bit position since all (1 bit per pixel) frames are directly concatenated * one after another (i.e. if one frame does not occupy a number of bits * dividable by 8, not all frames will be aligned at exact byte positions). * Note that each byte is filled from the right, i.e. the first pixel will * represented by the bit at the very right of the first byte, and the 9th * pixel will be in the very right position of the following byte. * This is not a regular bit shift operation since the bits from the previous * frame are on the left of the byte, but must be aligned at the right. The * current frame starts from the first bit, occupying the unused bits of * the last frame and then continuing in the next byte at the first bit * from the left. * Example for two bit shift: * Input buffer bytes: hgfedcba 87654321 * Result: fedcba00 654321hg * The 00 in the first byte must be handled by the caller (will * contain the two bits of the previous frame). * See also dcmseg/tests/tutils.cc for more examples. * @param buf The address of the memory buffer to shift * @param bufLen The length of the buf memory block in bytes * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. */ static void alignFrameOnBitPosition(Uint8* buf, const size_t bufLen, const Uint8 numBits); /** Aligns 1 bit per pixel frame data starting at a given bit position in the * provided buffer with the start of that buffer. This is used to create * a frame structure where all the bytes (including the first one) only * contain data from the frame at hand. * Note that each byte is filled from the right, i.e. the first pixel will * represented by the bit at the very right of the first byte, and the 9th * pixel will be in the very right position of the following byte. * Example: * 3 bytes input buffer: edcbaZYX mlkjihgf utsrqpon * Result after aligning 3 bits: fghedcba ponmlkji 000utsrq * The 000 are unused bits and therefore zeroed out in the last byte. Bits * ZYX will be shifted out which is ok since it does not belong to the * current frame. See also dcmseg/tests/tutils.cc for more examples. * @param buf The address of the memory buffer to shift * @param bufLen The length of the buf memory block in bytes * @param numBits The number of bits to shift. Must be 0 <= numBits <= 7. */ static void alignFrameOnByteBoundary(Uint8* buf, const size_t bufLen, const Uint8 numBits); /** Dumps a byte as binary number to a string. Only useful for * debugging purposes. * @param b The byte to dump * @return A string containing b as a binary number */ static OFString debugByte2Bin(Uint8 b); /** Dumps a memory block byte for byte to the debug log stream. Only useful * for debugging purposes. * @param buffer The address of the memory block to dump * @param length The length of memory to be dumped * @param what String describing what is dumped. */ static void debugDumpBin(Uint8* buffer, size_t length, const char* what); }; #endif // SEGUTILS_H