00001 /* 00002 * 00003 * Copyright (C) 2002-2010, OFFIS e.V. 00004 * All rights reserved. See COPYRIGHT file for details. 00005 * 00006 * This software and supporting documentation were developed by 00007 * 00008 * OFFIS e.V. 00009 * R&D Division Health 00010 * Escherweg 2 00011 * D-26121 Oldenburg, Germany 00012 * 00013 * 00014 * Module: dcmimage 00015 * 00016 * Author: Marco Eichelberg 00017 * 00018 * Purpose: class DcmQuantFloydSteinberg 00019 * 00020 * Last Update: $Author: joergr $ 00021 * Update Date: $Date: 2010-10-14 13:16:29 $ 00022 * CVS/RCS Revision: $Revision: 1.5 $ 00023 * Status: $State: Exp $ 00024 * 00025 * CVS/RCS Log at end of file 00026 * 00027 */ 00028 00029 00030 #ifndef DIQTFS_H 00031 #define DIQTFS_H 00032 00033 00034 #include "dcmtk/config/osconfig.h" 00035 #include "dcmtk/dcmimage/diqtpix.h" /* for DcmQuantPixel */ 00036 #include "dcmtk/ofstd/ofcond.h" /* for OFCondition */ 00037 00038 00042 #define DcmQuantFloydSteinbergScale 1024 00043 00044 00048 class DcmQuantFloydSteinberg 00049 { 00050 public: 00051 00053 DcmQuantFloydSteinberg(); 00054 00056 ~DcmQuantFloydSteinberg(); 00057 00063 OFCondition initialize(unsigned long cols); 00064 00071 inline void adjust(DcmQuantPixel& px, long col, long maxval) 00072 { 00073 register long sr = px.getRed() + thisrerr[col + 1] / DcmQuantFloydSteinbergScale; 00074 register long sg = px.getGreen() + thisgerr[col + 1] / DcmQuantFloydSteinbergScale; 00075 register long sb = px.getBlue() + thisberr[col + 1] / DcmQuantFloydSteinbergScale; 00076 if ( sr < 0 ) sr = 0; 00077 else if ( sr > OFstatic_cast(long, maxval) ) sr = maxval; 00078 if ( sg < 0 ) sg = 0; 00079 else if ( sg > OFstatic_cast(long, maxval) ) sg = maxval; 00080 if ( sb < 0 ) sb = 0; 00081 else if ( sb > OFstatic_cast(long, maxval) ) sb = maxval; 00082 px.assign(OFstatic_cast(DcmQuantComponent, sr), OFstatic_cast(DcmQuantComponent, sg), OFstatic_cast(DcmQuantComponent, sb)); 00083 } 00084 00090 inline void propagate(const DcmQuantPixel& px, const DcmQuantPixel& mapped, long col) 00091 { 00092 register long err; 00093 00094 /* Propagate Floyd-Steinberg error terms. */ 00095 if ( fs_direction ) 00096 { 00097 err = ( OFstatic_cast(long, px.getRed()) - OFstatic_cast(long, mapped.getRed()) ) * DcmQuantFloydSteinbergScale; 00098 thisrerr[col + 2] += ( err * 7 ) / 16; 00099 nextrerr[col ] += ( err * 3 ) / 16; 00100 nextrerr[col + 1] += ( err * 5 ) / 16; 00101 nextrerr[col + 2] += ( err ) / 16; 00102 err = ( OFstatic_cast(long, px.getGreen()) - OFstatic_cast(long, mapped.getGreen()) ) * DcmQuantFloydSteinbergScale; 00103 thisgerr[col + 2] += ( err * 7 ) / 16; 00104 nextgerr[col ] += ( err * 3 ) / 16; 00105 nextgerr[col + 1] += ( err * 5 ) / 16; 00106 nextgerr[col + 2] += ( err ) / 16; 00107 err = ( OFstatic_cast(long, px.getBlue()) - OFstatic_cast(long, mapped.getBlue()) ) * DcmQuantFloydSteinbergScale; 00108 thisberr[col + 2] += ( err * 7 ) / 16; 00109 nextberr[col ] += ( err * 3 ) / 16; 00110 nextberr[col + 1] += ( err * 5 ) / 16; 00111 nextberr[col + 2] += ( err ) / 16; 00112 } 00113 else 00114 { 00115 err = ( OFstatic_cast(long, px.getRed()) - OFstatic_cast(long, mapped.getRed()) ) * DcmQuantFloydSteinbergScale; 00116 thisrerr[col ] += ( err * 7 ) / 16; 00117 nextrerr[col + 2] += ( err * 3 ) / 16; 00118 nextrerr[col + 1] += ( err * 5 ) / 16; 00119 nextrerr[col ] += ( err ) / 16; 00120 err = ( OFstatic_cast(long, px.getGreen()) - OFstatic_cast(long, mapped.getGreen()) ) * DcmQuantFloydSteinbergScale; 00121 thisgerr[col ] += ( err * 7 ) / 16; 00122 nextgerr[col + 2] += ( err * 3 ) / 16; 00123 nextgerr[col + 1] += ( err * 5 ) / 16; 00124 nextgerr[col ] += ( err ) / 16; 00125 err = ( OFstatic_cast(long, px.getBlue()) - OFstatic_cast(long, mapped.getBlue()) ) * DcmQuantFloydSteinbergScale; 00126 thisberr[col ] += ( err * 7 ) / 16; 00127 nextberr[col + 2] += ( err * 3 ) / 16; 00128 nextberr[col + 1] += ( err * 5 ) / 16; 00129 nextberr[col ] += ( err ) / 16; 00130 } 00131 } 00132 00140 inline void startRow(long& col, long& limitcol) 00141 { 00142 for (unsigned long c = 0; c < columns + 2; ++c) 00143 nextrerr[c] = nextgerr[c] = nextberr[c] = 0; 00144 00145 if (fs_direction) 00146 { 00147 col = 0; 00148 limitcol = columns; 00149 } 00150 else 00151 { 00152 col = columns - 1; 00153 limitcol = -1; 00154 } 00155 } 00156 00161 inline void finishRow() 00162 { 00163 temperr = thisrerr; 00164 thisrerr = nextrerr; 00165 nextrerr = temperr; 00166 temperr = thisgerr; 00167 thisgerr = nextgerr; 00168 nextgerr = temperr; 00169 temperr = thisberr; 00170 thisberr = nextberr; 00171 nextberr = temperr; 00172 fs_direction = ! fs_direction; 00173 } 00174 00179 inline void nextCol(long& col) const 00180 { 00181 if (fs_direction) ++col; else --col; 00182 } 00183 00184 private: 00185 00187 void cleanup(); 00188 00190 DcmQuantFloydSteinberg(const DcmQuantFloydSteinberg& src); 00191 00193 DcmQuantFloydSteinberg& operator=(const DcmQuantFloydSteinberg& src); 00194 00196 long *thisrerr; 00197 00199 long *nextrerr; 00200 00202 long *thisgerr; 00203 00205 long *nextgerr; 00206 00208 long *thisberr; 00209 00211 long *nextberr; 00212 00214 long *temperr; 00215 00219 int fs_direction; 00220 00222 unsigned long columns; 00223 00224 }; 00225 00226 00227 #endif 00228 00229 00230 /* 00231 * CVS/RCS Log: 00232 * $Log: diqtfs.h,v $ 00233 * Revision 1.5 2010-10-14 13:16:29 joergr 00234 * Updated copyright header. Added reference to COPYRIGHT file. 00235 * 00236 * Revision 1.4 2005/12/08 16:01:46 meichel 00237 * Changed include path schema for all DCMTK header files 00238 * 00239 * Revision 1.3 2003/12/23 12:16:59 joergr 00240 * Adapted type casts to new-style typecast operators defined in ofcast.h. 00241 * Updated copyright header. 00242 * 00243 * Revision 1.2 2002/05/15 09:53:30 meichel 00244 * Minor corrections to avoid warnings on Sun CC 2.0.1 00245 * 00246 * Revision 1.1 2002/01/25 13:32:04 meichel 00247 * Initial release of new color quantization classes and 00248 * the dcmquant tool in module dcmimage. 00249 * 00250 * 00251 */