/* * * Copyright (C) 2002-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: dcmimage * * Author: Marco Eichelberg * * Purpose: class DcmQuantColorTable * */ #ifndef DIQTCTAB_H #define DIQTCTAB_H #include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/oftypes.h" /* for OFBool */ #include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ #include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */ #include "dcmtk/dcmimage/diqthash.h" /* for DcmQuantHistogramItem */ #include "dcmtk/ofstd/ofstring.h" /* for class OFString */ class DicomImage; class DcmItem; /** this class implements a color table that can either be * a look-up table or an image color histogram. */ class DCMTK_DCMIMAGE_EXPORT DcmQuantColorTable { public: /// constructor DcmQuantColorTable(); /// destructor ~DcmQuantColorTable(); /// resets the object to default-constructed state void clear(); /** returns the number of colors in the color table * @return number of colors in color table */ inline unsigned long getColors() const { return numColors; } /** creates a description string suitable for use as * Derivation Description. * @param str description string returned in this parameter */ void setDescriptionString(OFString& str) const; /** creates a color table containing a histogram of the given * image. Pixel sample values are downsampled if necessary * to make sure the histogram fits into the given size limit. * @param image color image for which a histogram is computed * @param maxcolors maximum number of colors allowed in histogram. * If necessary, pixel sample values are down-sampled to enforce * this maximum. * @return EC_Normal if successful, an error code otherwise. */ OFCondition computeHistogram(DicomImage& image, unsigned long maxcolors); /** after a call to computeHistogram(), this method * returns the maximum pixel value to which all color samples * were down-sampled during computation of the histogram. */ inline unsigned long getMaxVal() const { return maxval; } /** returns the color at index idx. * @param idx index, must be < getColors() * @return const reference to color */ inline const DcmQuantPixel& getPixel(unsigned long idx) const { #ifdef DEBUG assert(array && idx < numColors); #endif return *(array[idx]); } /** returns the red color component at index idx * @param idx index, must be < getColors() * @return red color component */ inline DcmQuantComponent getRed(unsigned long idx) const { #ifdef DEBUG assert(array && idx < numColors); #endif return array[idx]->getRed(); } /** returns the green color component at index idx * @param idx index, must be < getColors() * @return green color component */ inline DcmQuantComponent getGreen(unsigned long idx) const { #ifdef DEBUG assert(array && idx < numColors); #endif return array[idx]->getGreen(); } /** returns the blue color component at index idx * @param idx index, must be < getColors() * @return blue color component */ inline DcmQuantComponent getBlue(unsigned long idx) const { #ifdef DEBUG assert(array && idx < numColors); #endif return array[idx]->getBlue(); } /** computes a color LUT for the given image histogram. * This median-cut colormap generator is based * on Paul Heckbert's paper "Color Image Quantization for Frame Buffer * Display", SIGGRAPH '82 Proceedings, page 297. * @param histogram image color histogram * @param sum number of pixels in image (colums * rows * frames) * @param theMaxval maximum value to which pixels were * downsampled for histogram computation * @param numberOfColors desired number of colors in color LUT * @param largeType algorithm used for determining the largest dimension * in the Median Cut algorithm * @param repType algorithm for choosing a representative color for each * box in the Median Cut algorithm * @return EC_Normal if successful, an error code otherwise. */ OFCondition medianCut( DcmQuantColorTable& histogram, unsigned long sum, unsigned long theMaxval, unsigned long numberOfColors, DcmLargestDimensionType largeType, DcmRepresentativeColorType repType); /** determines for a given color the closest match in the color LUT. * @param px color to look up in LUT * @return index of closest match in LUT, -1 if look-up table empty */ inline int computeIndex(const DcmQuantPixel& px) const { int result = -1; int r2, g2, b2; long newdist; int r1 = OFstatic_cast(int, px.getRed()); int g1 = OFstatic_cast(int, px.getGreen()); int b1 = OFstatic_cast(int, px.getBlue()); long dist = 2000000000; for (unsigned long i = 0; i < numColors; ++i) { r2 = r1 - OFstatic_cast(int, array[i]->getRed()); g2 = g1 - OFstatic_cast(int, array[i]->getGreen()); b2 = b1 - OFstatic_cast(int, array[i]->getBlue()); newdist = r2*r2 + g2*g2 + b2*b2; if (newdist < dist) { result = OFstatic_cast(int, i); dist = newdist; if (dist < array[i]->getValue()) i=numColors; // break out of for loop } } return result; } /** writes the current color table into a DICOM object, encoded as * Red/Green/Blue Palette Color Lookup Table and Data. * @param target DICOM dataset to write to * @param writeAsOW if true, LUT data is encoded as OW, otherwise LUT data * is encoded as US. A LUT with 64k entries is always encoded as OW since * a US data element with 64k entries cannot be written in explicit VR. * @param write16BitEntries if true, LUT data is encoded with 16 bits per entry * @return EC_Normal if successful, an error code otherwise. */ OFCondition write( DcmItem& target, OFBool writeAsOW, OFBool write16BitEntries); private: /** after a call to medianCut(), this method computes for each entry in * the color map the minimum of the euclidean distances to any other * of the entries. Any color which has an euclidean distance of less * than half of this distance is necessarily mapped to this entry. * This data is used by computeIndex() */ void computeClusters(); /// private undefined copy constructor DcmQuantColorTable(const DcmQuantColorTable& src); /// private undefined copy assignment operator DcmQuantColorTable& operator=(const DcmQuantColorTable& src); /// color table data DcmQuantHistogramItemPointer *array; /// number of entries in color table unsigned long numColors; /** maximum pixel value to which all color samples * were down-sampled during computation of the histogram. */ unsigned long maxval; }; #endif