DYT/Tool/3rdParty_x64/include/dcmtk/dcmimage/dicoopxt.h
2024-11-22 23:19:31 +08:00

418 lines
16 KiB
C++

/*
*
* Copyright (C) 1996-2016, 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: DicomColorOutputPixelTemplate (Header)
*
*/
#ifndef DICOOPXT_H
#define DICOOPXT_H
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmimage/dicoopx.h"
#include "dcmtk/dcmimage/dicopx.h"
#include "dcmtk/dcmimgle/dipxrept.h"
#include "dcmtk/ofstd/ofbmanip.h"
/*---------------------*
* class declaration *
*---------------------*/
/** Template class to create color output data
*/
template<class T1, class T2>
class DiColorOutputPixelTemplate
: public DiColorOutputPixel,
public DiPixelRepresentationTemplate<T2>
{
public:
/** constructor
*
** @param buffer storage area for the output pixel data (optional, maybe NULL)
* @param pixel pointer to intermediate pixel representation (color)
* @param count number of pixels per frame
* @param frame frame to be rendered
* @param bits1 bit depth of input data (intermediate)
* @param bits2 bit depth of output data
* @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane
* @param inverse invert pixel data if true (0/0/0 = white)
*/
DiColorOutputPixelTemplate(void *buffer,
const DiColorPixel *pixel,
const unsigned long count,
const unsigned long frame,
const int bits1, /* input depth */
const int bits2, /* output depth */
const int planar,
const int inverse)
: DiColorOutputPixel(pixel, count, frame),
Data(NULL),
DeleteData(buffer == NULL),
isPlanar(planar)
{
if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
{
Data = OFstatic_cast(T2 *, buffer);
convert(OFstatic_cast(const T1 **, OFconst_cast(void *, pixel->getData())), frame * FrameSize, bits1, bits2, planar, inverse);
}
}
/** constructor
*
** @param buffer storage area for the output pixel data (optional, maybe NULL)
* @param pixel pointer to intermediate pixel representation
* @param count number of pixels per frame
* @param frame frame to be rendered
* (#)param frames (total number of frames present in intermediate representation)
* @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane
*/
DiColorOutputPixelTemplate(void *buffer,
const DiPixel *pixel,
const unsigned long count,
const unsigned long frame,
const unsigned long /*frames*/,
const int planar)
: DiColorOutputPixel(pixel, count, frame),
Data(NULL),
DeleteData(buffer == NULL),
isPlanar(planar)
{
if ((pixel != NULL) && (Count > 0) && (FrameSize >= Count))
Data = OFstatic_cast(T2 *, buffer);
}
/** destructor
*/
virtual ~DiColorOutputPixelTemplate()
{
if (DeleteData)
delete[] Data;
}
/** get integer representation
*
** @return integer representation
*/
inline EP_Representation getRepresentation() const
{
return DiPixelRepresentationTemplate<T2>::getRepresentation();
}
/** get size of one pixel / item in the pixel array
*
** @return item size
*/
inline size_t getItemSize() const
{
return sizeof(T2) * 3;
}
/** get pointer to output pixel data
*
** @return pointer to pixel data
*/
inline const void *getData() const
{
return OFstatic_cast(const void *, Data);
}
/** get pointer to output pixel data
*
** @return pointer to pixel data
*/
virtual void *getDataPtr()
{
return OFstatic_cast(void *, Data);
}
/** get pointer to given plane of output pixel data
*
** @param plane number of the plane to be retrieved (0..2)
*
** @return pointer to beginning of plane if successful, NULL otherwise
*/
inline const void *getPlane(const int plane) const
{
void *result = NULL;
if (Data != NULL)
{
if (plane <= 0)
result = OFstatic_cast(void *, Data);
else
{
if (isPlanar)
result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2) * FrameSize);
else
result = OFstatic_cast(void *, Data + ((plane == 1) ? 1 : 2));
}
}
return result;
}
/** write pixel data of selected frame to PPM/ASCII file
*
** @param stream open C++ output stream
*
** @return status, true if successful, false otherwise
*/
int writePPM(STD_NAMESPACE ostream& stream) const
{
if (Data != NULL)
{
T2 *p = Data;
unsigned long i;
int j;
for (i = FrameSize; i != 0; --i)
for (j = 3; j != 0; --j)
stream << OFstatic_cast(unsigned long, *(p++)) << " "; // typecast to resolve problems with 'char'
return 1;
}
return 0;
}
/** write pixel data of selected frame to PPM/ASCII file
*
** @param stream open C file stream
*
** @return status, true if successful, false otherwise
*/
int writePPM(FILE *stream) const
{
if (Data != NULL)
{
T2 *p = Data;
unsigned long i;
int j;
for (i = FrameSize; i != 0; --i)
for (j = 3; j != 0; --j)
fprintf(stream, "%lu ", OFstatic_cast(unsigned long, *(p++)));
return 1;
}
return 0;
}
protected:
/// pointer to the storage area where the output data should be stored
T2 *Data;
private:
/** convert intermediate pixel data to output format (render pixel data)
*
** @param pixel pointer to intermediate pixel representation (color)
* @param start offset to first pixel to be converted
* @param bits1 bit depth of input data (intermediate)
* @param bits2 bit depth of output data
* @param planar flag indicating whether data shall be stored color-by-pixel or color-by-plane
* @param inverse invert pixel data if true (0/0/0 = white)
*/
void convert(const T1 *pixel[3],
const unsigned long start,
const int bits1,
const int bits2,
const int planar,
const int inverse)
{
if ((pixel[0] != NULL) && (pixel[1] != NULL) && (pixel[2] != NULL))
{
if (Data == NULL)
Data = new T2[FrameSize * 3];
if (Data != NULL)
{
DCMIMAGE_DEBUG("converting color pixel data to output format");
T2 *q = Data;
unsigned long i;
const T2 max2 = OFstatic_cast(T2, DicomImageClass::maxval(bits2));
if (planar)
{
const T1 *p;
if (bits1 == bits2)
{
for (int j = 0; j < 3; ++j)
{
p = pixel[j] + start;
/* invert output data */
if (inverse)
{
for (i = Count; i != 0; --i) // copy inverted data
*(q++) = max2 - OFstatic_cast(T2, *(p++));
} else {
for (i = Count; i != 0; --i) // copy
*(q++) = OFstatic_cast(T2, *(p++));
}
if (Count < FrameSize)
{
OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero
q += (FrameSize - Count);
}
}
}
else if (bits1 < bits2) // optimization possible using LUT
{
const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) /
OFstatic_cast(double, DicomImageClass::maxval(bits1));
const T2 gradient2 = OFstatic_cast(T2, gradient1);
for (int j = 0; j < 3; ++j)
{
p = pixel[j] + start;
if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
{
/* invert output data */
if (inverse)
{
for (i = Count; i != 0; --i) // expand depth & invert
*(q++) = max2 - OFstatic_cast(T2, *(p++)) * gradient2;
} else {
for (i = Count; i != 0; --i) // expand depth
*(q++) = OFstatic_cast(T2, *(p++)) * gradient2;
}
} else {
/* invert output data */
if (inverse)
{
for (i = Count; i != 0; --i) // expand depth & invert
*(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1);
} else {
for (i = Count; i != 0; --i) // expand depth
*(q++) = OFstatic_cast(T2, OFstatic_cast(double, *(p++)) * gradient1);
}
}
if (Count < FrameSize)
{
OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero
q += (FrameSize - Count);
}
} // ... to be enhanced !
}
else /* bits1 > bits2 */
{
const int shift = bits1 - bits2;
for (int j = 0; j < 3; ++j)
{
p = pixel[j] + start;
/* invert output data */
if (inverse)
{
for (i = Count; i != 0; --i) // reduce depth & invert
*(q++) = max2 - OFstatic_cast(T2, *(p++) >> shift);
} else {
for (i = Count; i != 0; --i) // reduce depth
*(q++) = OFstatic_cast(T2, *(p++) >> shift);
}
if (Count < FrameSize)
{
OFBitmanipTemplate<T2>::zeroMem(q, FrameSize - Count); // set remaining pixels of frame to zero
q += (FrameSize - Count);
}
}
}
}
else /* not planar */
{
int j;
if (bits1 == bits2)
{
/* invert output data */
if (inverse)
{
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // copy inverted data
*(q++) = max2 - OFstatic_cast(T2, pixel[j][i]);
} else {
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // copy
*(q++) = OFstatic_cast(T2, pixel[j][i]);
}
}
else if (bits1 < bits2) // optimization possible using LUT
{
const double gradient1 = OFstatic_cast(double, DicomImageClass::maxval(bits2)) /
OFstatic_cast(double, DicomImageClass::maxval(bits1));
const T2 gradient2 = OFstatic_cast(T2, gradient1);
if (gradient1 == OFstatic_cast(double, gradient2)) // integer multiplication?
{
/* invert output data */
if (inverse)
{
for (i = start; i < start + Count; ++i) // expand depth & invert
for (j = 0; j < 3; ++j)
*(q++) = max2 - OFstatic_cast(T2, pixel[j][i]) * gradient2;
} else {
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // expand depth
*(q++) = OFstatic_cast(T2, pixel[j][i]) * gradient2;
}
} else {
/* invert output data */
if (inverse)
{
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // expand depth & invert
*(q++) = max2 - OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1);
} else {
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // expand depth
*(q++) = OFstatic_cast(T2, OFstatic_cast(double, pixel[j][i]) * gradient1);
}
}
}
else /* bits1 > bits2 */
{
const int shift = bits1 - bits2;
/* invert output data */
if (inverse)
{
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // reduce depth & invert
*(q++) = max2 - OFstatic_cast(T2, pixel[j][i] >> shift);
} else {
for (i = start; i < start + Count; ++i)
for (j = 0; j < 3; ++j) // reduce depth
*(q++) = OFstatic_cast(T2, pixel[j][i] >> shift);
}
}
if (Count < FrameSize)
OFBitmanipTemplate<T2>::zeroMem(q, 3 * (FrameSize - Count)); // set remaining pixels of frame to zero
}
}
} else
Data = NULL;
}
/// flag indicating whether the output data buffer should be deleted in the destructor
int DeleteData;
/// flag indicating whether pixel data is stored color-by-pixel or color-by-plane
int isPlanar;
// --- declarations to avoid compiler warnings
DiColorOutputPixelTemplate(const DiColorOutputPixelTemplate<T1,T2> &);
DiColorOutputPixelTemplate<T1,T2> &operator=(const DiColorOutputPixelTemplate<T1,T2> &);
};
#endif