/* * * Copyright (C) 2015-2016, 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 * */ #include "dcmtk/config/osconfig.h" #include "dcmtk/dcmseg/segutils.h" #include "dcmtk/dcmseg/segdef.h" DcmIODTypes::Frame* DcmSegUtils::packBinaryFrame(Uint8* pixelData, const Uint16 rows, const Uint16 columns) { // Sanity checking const size_t numPixels = rows*columns; if (numPixels == 0) { DCMSEG_ERROR("Unable to pack binary segmentation frame: Rows or Columns is 0"); return NULL; } if (!pixelData) { DCMSEG_ERROR("Unable to pack binary segmentation frame: No pixel data provided"); return NULL; } DcmIODTypes::Frame* frame = new DcmIODTypes::Frame(); if (frame == NULL) { DCMSEG_ERROR("Could not pack binary segmentation frame: Memory exhausted"); return NULL; } frame->length = getBytesForBinaryFrame(numPixels); frame->pixData = new Uint8[frame->length]; if (frame->pixData == 0) { delete frame; return NULL; } memset(frame->pixData, 0, frame->length); size_t bytePos = 0; for (size_t count = 0; count < numPixels; count++) { // Compute byte position bytePos = count / 8; frame->pixData[bytePos] |= (pixelData[count] != 0) /* value to set */ << (count % 8 /* bit position (0-7) within byte */); } return frame; } DcmIODTypes::Frame* DcmSegUtils::unpackBinaryFrame(const DcmIODTypes::Frame* frame, Uint16 rows, Uint16 cols) { // Sanity checking if ( (frame == NULL) || (rows == 0) || (cols == 0) ) { DCMSEG_ERROR("Cannot unpack binary frame, invalid input data"); return NULL; } // Create result frame in memory size_t numBits = rows * cols; DcmIODTypes::Frame* result = new DcmIODTypes::Frame(); if (result) { result->pixData = new Uint8[numBits]; result->length = numBits; } if ( !result || !(result->pixData) ) { DCMSEG_ERROR("Cannot unpack binary frame, memory exhausted"); return NULL; } memset(result->pixData, 0, result->length); // Transform and copy from packed frame to unpacked result frame size_t bytePos = 0; for (size_t count = 0; count < numBits; count++) { // Compute byte position bytePos = count / 8; // Bit position (0-7) within byte Uint8 bitpos = (count % 8); if ( (frame->pixData[bytePos] & (1 << bitpos) /* check whether bit at bitpos is set*/) ) { result->pixData[count] = 1; } else { result->pixData[count] = 0; } } return result; } size_t DcmSegUtils::getBytesForBinaryFrame(const size_t& numPixels) { // check whether the 1-bit pixels exactly fit into bytes size_t remainder = numPixels % 8; // number of bytes that work on an exact fit size_t bytesRequired = numPixels / 8; // add one byte if we have a remainder if (remainder > 0) bytesRequired++; return bytesRequired; } void DcmSegUtils::shiftRight(Uint8* buf, size_t bufLen, Uint8 numBits) { if (numBits > 7) { DCMSEG_ERROR("Invalid input data: shiftRight() can only shift 0-7 bits"); return; } Uint8 carryOver = 0; for (size_t x = 0; x < bufLen; x++) { // Store current byte since we need its last bits Uint8 current = buf[x]; buf[x] >>= numBits; // If there is a carry over from the last handled byte, add it buf[x] |= carryOver; // Compute carry over bits for next byte handled carryOver = current << (8-numBits); // bits we need to shift over to start (left hand side) of buf[x+1] } } void DcmSegUtils::shiftLeft(Uint8* buf, size_t bufLen, Uint8 numBits) { if (numBits > 7) { DCMSEG_ERROR("Invalid input data: shiftLeft() can only shift 0-7 bits"); return; } for (size_t x = 0; x < bufLen-1; x++) { // Shift current byte buf[x] = buf[x] << numBits; // isolate portion of next byte that must be shifted into current byte Uint8 next = (buf[x+1] >> (8-numBits)); // Shift current byte buf[x] |= next; } // Shift last byte manually buf[bufLen-1] <<= numBits; } void DcmSegUtils::debugDumpBin(Uint8* buffer, size_t length, const char* what) { for (size_t n=0; n= 0; i--) { result[i]= (b & 1) + '0'; b >>= 1; } return result; }