/usr/include/dcmtk/dcmimage/diqtfs.h is in libdcmtk-dev 3.6.2-3build3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | /*
*
* 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 DcmQuantFloydSteinberg
*
*/
#ifndef DIQTFS_H
#define DIQTFS_H
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */
#include "dcmtk/ofstd/ofcond.h" /* for OFCondition */
/** Floyd-Steinberg error vectors are stored internally as integer numbers
* containing the error multiplied by this constant.
*/
#define DcmQuantFloydSteinbergScale 1024
/** this class implements Floyd-Steinberg error diffusion.
* It is used during the color quantization of an image.
*/
class DCMTK_DCMIMAGE_EXPORT DcmQuantFloydSteinberg
{
public:
/// constructor
DcmQuantFloydSteinberg();
/// destructor
~DcmQuantFloydSteinberg();
/** initializes the Floyd-Steinberg error vectors for an image with the
* given number of columns.
* @param cols number of columns in image
* @return EC_Normal if successful, an error code otherwise.
*/
OFCondition initialize(unsigned long cols);
/** uses the Floyd-Steinberg error vectors to adjust the color of the current image pixel.
* @param px the original image pixel is passed in this parameter. Upon return, the pixel
* value contains the new value after error diffusion.
* @param col column in which the current pixel is located, must be [0..columns-1]
* @param maxval maximum value for each color component.
*/
inline void adjust(DcmQuantPixel& px, long col, long maxval)
{
long sr = px.getRed() + thisrerr[col + 1] / DcmQuantFloydSteinbergScale;
long sg = px.getGreen() + thisgerr[col + 1] / DcmQuantFloydSteinbergScale;
long sb = px.getBlue() + thisberr[col + 1] / DcmQuantFloydSteinbergScale;
if ( sr < 0 ) sr = 0;
else if ( sr > OFstatic_cast(long, maxval) ) sr = maxval;
if ( sg < 0 ) sg = 0;
else if ( sg > OFstatic_cast(long, maxval) ) sg = maxval;
if ( sb < 0 ) sb = 0;
else if ( sb > OFstatic_cast(long, maxval) ) sb = maxval;
px.assign(OFstatic_cast(DcmQuantComponent, sr), OFstatic_cast(DcmQuantComponent, sg), OFstatic_cast(DcmQuantComponent, sb));
}
/** propagates the Floyd-Steinberg error terms for one pixel.
* @param px color value the current image pixel should have (after adjustment)
* @param mapped color value (selected from the color LUT) the current image pixel really uses
* @param col column in which the current pixel is located, must be [0..columns-1]
*/
inline void propagate(const DcmQuantPixel& px, const DcmQuantPixel& mapped, long col)
{
long err;
/* Propagate Floyd-Steinberg error terms. */
if ( fs_direction )
{
err = ( OFstatic_cast(long, px.getRed()) - OFstatic_cast(long, mapped.getRed()) ) * DcmQuantFloydSteinbergScale;
thisrerr[col + 2] += ( err * 7 ) / 16;
nextrerr[col ] += ( err * 3 ) / 16;
nextrerr[col + 1] += ( err * 5 ) / 16;
nextrerr[col + 2] += ( err ) / 16;
err = ( OFstatic_cast(long, px.getGreen()) - OFstatic_cast(long, mapped.getGreen()) ) * DcmQuantFloydSteinbergScale;
thisgerr[col + 2] += ( err * 7 ) / 16;
nextgerr[col ] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col + 2] += ( err ) / 16;
err = ( OFstatic_cast(long, px.getBlue()) - OFstatic_cast(long, mapped.getBlue()) ) * DcmQuantFloydSteinbergScale;
thisberr[col + 2] += ( err * 7 ) / 16;
nextberr[col ] += ( err * 3 ) / 16;
nextberr[col + 1] += ( err * 5 ) / 16;
nextberr[col + 2] += ( err ) / 16;
}
else
{
err = ( OFstatic_cast(long, px.getRed()) - OFstatic_cast(long, mapped.getRed()) ) * DcmQuantFloydSteinbergScale;
thisrerr[col ] += ( err * 7 ) / 16;
nextrerr[col + 2] += ( err * 3 ) / 16;
nextrerr[col + 1] += ( err * 5 ) / 16;
nextrerr[col ] += ( err ) / 16;
err = ( OFstatic_cast(long, px.getGreen()) - OFstatic_cast(long, mapped.getGreen()) ) * DcmQuantFloydSteinbergScale;
thisgerr[col ] += ( err * 7 ) / 16;
nextgerr[col + 2] += ( err * 3 ) / 16;
nextgerr[col + 1] += ( err * 5 ) / 16;
nextgerr[col ] += ( err ) / 16;
err = ( OFstatic_cast(long, px.getBlue()) - OFstatic_cast(long, mapped.getBlue()) ) * DcmQuantFloydSteinbergScale;
thisberr[col ] += ( err * 7 ) / 16;
nextberr[col + 2] += ( err * 3 ) / 16;
nextberr[col + 1] += ( err * 5 ) / 16;
nextberr[col ] += ( err ) / 16;
}
}
/** starts error diffusion for a new row.
* The error vectors for the next image row are initialized to zero.
* The initial and last column of the current row are determined
* @param col initial column for the current row returned in this parameter
* @param limitcol limit column (one past the last valid column) for the
* current row returned in this parameter. May become negative.
*/
inline void startRow(long& col, long& limitcol)
{
for (unsigned long c = 0; c < columns + 2; ++c)
nextrerr[c] = nextgerr[c] = nextberr[c] = 0;
if (fs_direction)
{
col = 0;
limitcol = columns;
}
else
{
col = columns - 1;
limitcol = -1;
}
}
/** finishes error diffusion for one image row. The direction flag is
* inverted and the error vectors for the "current" and "next" image row
* are swapped.
*/
inline void finishRow()
{
temperr = thisrerr;
thisrerr = nextrerr;
nextrerr = temperr;
temperr = thisgerr;
thisgerr = nextgerr;
nextgerr = temperr;
temperr = thisberr;
thisberr = nextberr;
nextberr = temperr;
fs_direction = ! fs_direction;
}
/** increases or decreases the column number
* depending on the direction flag.
* @param col column number, may become negative
*/
inline void nextCol(long& col) const
{
if (fs_direction) ++col; else --col;
}
private:
/// frees all memory allocated by the error vectors
void cleanup();
/// private undefined copy constructor
DcmQuantFloydSteinberg(const DcmQuantFloydSteinberg& src);
/// private undefined copy assignment operator
DcmQuantFloydSteinberg& operator=(const DcmQuantFloydSteinberg& src);
/// current red error vector. Points to an array of (columns + 2) entries.
long *thisrerr;
/// red error vector for next row. Points to an array of (columns + 2) entries.
long *nextrerr;
/// current green error vector. Points to an array of (columns + 2) entries.
long *thisgerr;
/// green error vector for next row. Points to an array of (columns + 2) entries.
long *nextgerr;
/// current blue error vector. Points to an array of (columns + 2) entries.
long *thisberr;
/// blue error vector for next row. Points to an array of (columns + 2) entries.
long *nextberr;
/// temporary pointer used for swapping error vectors
long *temperr;
/** boolean flag indicating in which direction (left to right/right to left)
* the FS distribution should be done. Flag is inverted after each row.
*/
int fs_direction;
/// number of columns in image
unsigned long columns;
};
#endif
|