OFFIS DCMTK  Version 3.6.0
discalet.h
1 /*
2  *
3  * Copyright (C) 1996-2011, OFFIS e.V.
4  * All rights reserved. See COPYRIGHT file for details.
5  *
6  * This software and supporting documentation were developed by
7  *
8  * OFFIS e.V.
9  * R&D Division Health
10  * Escherweg 2
11  * D-26121 Oldenburg, Germany
12  *
13  *
14  * Module: dcmimgle
15  *
16  * Author: Joerg Riesmeier
17  *
18  * Purpose: DicomScaleTemplates (Header)
19  *
20  * Last Update: $Author: joergr $
21  * Update Date: $Date: 2011-11-17 16:13:16 $
22  * CVS/RCS Revision: $Revision: 1.36 $
23  * Status: $State: Exp $
24  *
25  * CVS/RCS Log at end of file
26  *
27  */
28 
29 
30 #ifndef DISCALET_H
31 #define DISCALET_H
32 
33 #include "dcmtk/config/osconfig.h"
34 
35 #include "dcmtk/ofstd/ofcast.h"
36 
37 #include "dcmtk/dcmimgle/ditranst.h"
38 #include "dcmtk/dcmimgle/dipxrept.h"
39 
40 
41 /*---------------------*
42  * macro definitions *
43  *---------------------*/
44 
45 #define SCALE_FACTOR 4096
46 #define HALFSCALE_FACTOR 2048
47 
48 
49 /*--------------------*
50  * helper functions *
51  *--------------------*/
52 
53 // help function to set scaling values
54 static inline void setScaleValues(Uint16 data[],
55  const Uint16 min,
56  const Uint16 max)
57 {
58  register Uint16 remainder = max % min;
59  Uint16 step0 = max / min;
60  Uint16 step1 = max / min;
61  if (remainder > OFstatic_cast(Uint16, min / 2))
62  {
63  remainder = min - remainder;
64  ++step0;
65  } else
66  ++step1;
67  const double count = OFstatic_cast(double, min) / (OFstatic_cast(double, remainder) + 1);
68  register Uint16 i;
69  register double c = count;
70  for (i = 0; i < min; ++i)
71  {
72  if ((i >= OFstatic_cast(Uint16, c)) && (remainder > 0))
73  {
74  --remainder;
75  c += count;
76  data[i] = step1;
77  }
78  else
79  data[i] = step0;
80  }
81 }
82 
83 // cubic value interpolation using Catmull-Rom formula.
84 // the interpolated pixel lies between the second and the third original pixels
85 static inline double cubicValue(const double v1,
86  const double v2,
87  const double v3,
88  const double v4,
89  const double dD,
90  const double minVal,
91  const double maxVal)
92 {
93  double dVal = 0.5 * ((((-v1 + 3 * v2 - 3 * v3 + v4) * dD + (2 * v1 - 5 * v2 + 4 * v3 - v4)) * dD + (-v1 + v3)) * dD + (v2 + v2));
94  return (dVal < minVal) ? minVal : ((dVal > maxVal) ? maxVal : dVal);
95 }
96 
97 
98 /*---------------------*
99  * class declaration *
100  *---------------------*/
101 
105 template<class T>
107  : public DiTransTemplate<T>
108 {
109 
110  public:
111 
126  DiScaleTemplate(const int planes,
127  const Uint16 columns, /* resolution of source image */
128  const Uint16 rows,
129  const signed long left_pos, /* origin of clipping area */
130  const signed long top_pos,
131  const Uint16 src_cols, /* extension of clipping area */
132  const Uint16 src_rows,
133  const Uint16 dest_cols, /* extension of destination image */
134  const Uint16 dest_rows,
135  const Uint32 frames, /* number of frames */
136  const int bits = 0)
137  : DiTransTemplate<T>(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits),
138  Left(left_pos),
139  Top(top_pos),
140  Columns(columns),
141  Rows(rows)
142  {
143  }
144 
155  DiScaleTemplate(const int planes,
156  const Uint16 src_cols, /* resolution of source image */
157  const Uint16 src_rows,
158  const Uint16 dest_cols, /* resolution of destination image */
159  const Uint16 dest_rows,
160  const Uint32 frames, /* number of frames */
161  const int bits = 0)
162  : DiTransTemplate<T>(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits),
163  Left(0),
164  Top(0),
165  Columns(src_cols),
166  Rows(src_rows)
167  {
168  }
169 
173  {
174  }
175 
180  inline int isSigned() const
181  {
183  return rep.isSigned();
184  }
185 
194  void scaleData(const T *src[],
195  T *dest[],
196  const int interpolate,
197  const T value = 0)
198  {
199  if ((src != NULL) && (dest != NULL))
200  {
201  DCMIMGLE_TRACE("Col/Rows: " << Columns << " " << Rows << OFendl
202  << "Left/Top: " << Left << " " << Top << OFendl
203  << "Src X/Y: " << this->Src_X << " " << this->Src_Y << OFendl
204  << "Dest X/Y: " << this->Dest_X << " " << this->Dest_Y);
205  if ((Left + OFstatic_cast(signed long, this->Src_X) <= 0) || (Top + OFstatic_cast(signed long, this->Src_Y) <= 0) ||
206  (Left >= OFstatic_cast(signed long, Columns)) || (Top >= OFstatic_cast(signed long, Rows)))
207  { // no image to be displayed
208  DCMIMGLE_DEBUG("clipping area is fully outside the image boundaries");
209  this->fillPixel(dest, value); // ... fill bitmap
210  }
211  else if ((this->Src_X == this->Dest_X) && (this->Src_Y == this->Dest_Y)) // no scaling
212  {
213  if ((Left == 0) && (Top == 0) && (Columns == this->Src_X) && (Rows == this->Src_Y))
214  this->copyPixel(src, dest); // copying
215  else if ((Left >= 0) && (OFstatic_cast(Uint16, Left + this->Src_X) <= Columns) &&
216  (Top >= 0) && (OFstatic_cast(Uint16, Top + this->Src_Y) <= Rows))
217  clipPixel(src, dest); // clipping
218  else
219  clipBorderPixel(src, dest, value); // clipping (with border)
220  }
221  else if ((interpolate == 1) && (this->Bits <= MAX_INTERPOLATION_BITS))
222  interpolatePixel(src, dest); // interpolation (pbmplus)
223  else if ((interpolate == 4) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y) &&
224  (this->Src_X >= 3) && (this->Src_Y >= 3))
225  bicubicPixel(src, dest); // bicubic magnification
226  else if ((interpolate >= 3) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y) &&
227  (this->Src_X >= 2) && (this->Src_Y >= 2))
228  bilinearPixel(src, dest); // bilinear magnification
229  else if ((interpolate >= 1) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y))
230  expandPixel(src, dest); // interpolated expansion (c't)
231  else if ((interpolate >= 1) && (this->Src_X >= this->Dest_X) && (this->Src_Y >= this->Dest_Y))
232  reducePixel(src, dest); // interpolated reduction (c't)
233  else if ((interpolate >= 1) && (this->Bits <= MAX_INTERPOLATION_BITS))
234  interpolatePixel(src, dest); // interpolation (pbmplus), fallback
235  else if ((this->Dest_X % this->Src_X == 0) && (this->Dest_Y % this->Src_Y == 0))
236  replicatePixel(src, dest); // replication
237  else if ((this->Src_X % this->Dest_X == 0) && (this->Src_Y % this->Dest_Y == 0))
238  suppressPixel(src, dest); // supression
239  else
240  scalePixel(src, dest); // general scaling
241  }
242  }
243 
244  protected:
245 
247  const signed long Left;
249  const signed long Top;
251  const Uint16 Columns;
253  const Uint16 Rows;
254 
255 
256  private:
257 
264  void clipPixel(const T *src[],
265  T *dest[])
266  {
267  DCMIMGLE_DEBUG("using clip image to specified area algorithm");
268  const unsigned long x_feed = Columns - this->Src_X;
269  const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns);
270  register Uint16 x;
271  register Uint16 y;
272  register const T *p;
273  register T *q;
274  for (int j = 0; j < this->Planes; ++j)
275  {
276  p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
277  q = dest[j];
278  for (unsigned long f = this->Frames; f != 0; --f)
279  {
280  for (y = this->Dest_Y; y != 0; --y)
281  {
282  for (x = this->Dest_X; x != 0; --x)
283  *(q++) = *(p++);
284  p += x_feed;
285  }
286  p += y_feed;
287  }
288  }
289  }
290 
297  void clipBorderPixel(const T *src[],
298  T *dest[],
299  const T value)
300  {
301  DCMIMGLE_DEBUG("using clip image to specified area and add border algorithm");
302  const Uint16 s_left = (Left > 0) ? OFstatic_cast(Uint16, Left) : 0;
303  const Uint16 s_top = (Top > 0) ? OFstatic_cast(Uint16, Top) : 0;
304  const Uint16 d_left = (Left < 0 ? OFstatic_cast(Uint16, -Left) : 0);
305  const Uint16 d_top = (Top < 0) ? OFstatic_cast(Uint16, -Top) : 0;
306  const Uint16 d_right = (OFstatic_cast(unsigned long, this->Src_X) + OFstatic_cast(unsigned long, s_left) <
307  OFstatic_cast(unsigned long, Columns) + OFstatic_cast(unsigned long, d_left)) ?
308  (this->Src_X - 1) : (Columns + d_left - s_left - 1);
309  const Uint16 d_bottom = (OFstatic_cast(unsigned long, this->Src_Y) + OFstatic_cast(unsigned long, s_top) <
310  OFstatic_cast(unsigned long, Rows) + OFstatic_cast(unsigned long, d_top)) ?
311  (this->Src_Y - 1) : (Rows + d_top - s_top - 1);
312  const Uint16 x_count = d_right - d_left + 1;
313  const Uint16 y_count = d_bottom - d_top + 1;
314  const unsigned long s_start = OFstatic_cast(unsigned long, s_top) * OFstatic_cast(unsigned long, Columns) + s_left;
315  const unsigned long x_feed = Columns - x_count;
316  const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - y_count) * Columns;
317  const unsigned long t_feed = OFstatic_cast(unsigned long, d_top) * OFstatic_cast(unsigned long, this->Src_X);
318  const unsigned long b_feed = OFstatic_cast(unsigned long, this->Src_Y - d_bottom - 1) * OFstatic_cast(unsigned long, this->Src_X);
319 
320  /*
321  * The approach is to divide the destination image in up to four areas outside the source image
322  * plus one area for the source image. The for and while loops are scanning linearly over the
323  * destination image and setting the appropriate value depending on the current area. This is
324  * different from most of the other algorithms in this toolkit where the source image is scanned
325  * linearly.
326  */
327  register Uint16 x;
328  register Uint16 y;
329  register unsigned long i;
330  register const T *p;
331  register T *q;
332  for (int j = 0; j < this->Planes; ++j)
333  {
334  p = src[j] + s_start;
335  q = dest[j];
336  for (unsigned long f = this->Frames; f != 0; --f)
337  {
338  for (i = t_feed; i != 0; --i) // top
339  *(q++) = value;
340  for (y = y_count; y != 0; --y) // middle part:
341  {
342  x = 0;
343  while (x < d_left) // - left
344  {
345  *(q++) = value;
346  ++x;
347  }
348  while (x <= d_right) // - middle
349  {
350  *(q++) = *(p++);
351  ++x;
352  }
353  while (x < this->Src_X) // - right
354  {
355  *(q++) = value;
356  ++x;
357  }
358  p += x_feed;
359  }
360  for (i = b_feed; i != 0; --i) // bottom
361  *(q++) = value;
362  p += y_feed;
363  }
364  }
365  }
366 
373  void replicatePixel(const T *src[],
374  T *dest[])
375  {
376  DCMIMGLE_DEBUG("using replicate pixel scaling algorithm without interpolation");
377  const Uint16 x_factor = this->Dest_X / this->Src_X;
378  const Uint16 y_factor = this->Dest_Y / this->Src_Y;
379  const unsigned long x_feed = Columns;
380  const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns);
381  const T *sp;
382  register Uint16 x;
383  register Uint16 y;
384  register Uint16 dx;
385  register Uint16 dy;
386  register const T *p;
387  register T *q;
388  register T value;
389  for (int j = 0; j < this->Planes; ++j)
390  {
391  sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
392  q = dest[j];
393  for (unsigned long f = this->Frames; f != 0; --f)
394  {
395  for (y = this->Src_Y; y != 0; --y)
396  {
397  for (dy = y_factor; dy != 0; --dy)
398  {
399  for (x = this->Src_X, p = sp; x != 0; --x)
400  {
401  value = *(p++);
402  for (dx = x_factor; dx != 0; --dx)
403  *(q++) = value;
404  }
405  }
406  sp += x_feed;
407  }
408  sp += y_feed;
409  }
410  }
411  }
412 
419  void suppressPixel(const T *src[],
420  T *dest[])
421  {
422  DCMIMGLE_DEBUG("using suppress pixel scaling algorithm without interpolation");
423  const unsigned int x_divisor = this->Src_X / this->Dest_X;
424  const unsigned long x_feed = OFstatic_cast(unsigned long, this->Src_Y / this->Dest_Y) * OFstatic_cast(unsigned long, Columns) - this->Src_X;
425  const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns);
426  register Uint16 x;
427  register Uint16 y;
428  register const T *p;
429  register T *q;
430  for (int j = 0; j < this->Planes; ++j)
431  {
432  p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
433  q = dest[j];
434  for (unsigned long f = this->Frames; f != 0; --f)
435  {
436  for (y = this->Dest_Y; y != 0; --y)
437  {
438  for (x = this->Dest_X; x != 0; --x)
439  {
440  *(q++) = *p;
441  p += x_divisor;
442  }
443  p += x_feed;
444  }
445  p += y_feed;
446  }
447  }
448  }
449 
456  void scalePixel(const T *src[],
457  T *dest[])
458  {
459  DCMIMGLE_DEBUG("using free scaling algorithm without interpolation");
460  const Uint16 xmin = (this->Dest_X < this->Src_X) ? this->Dest_X : this->Src_X; // minimum width
461  const Uint16 ymin = (this->Dest_Y < this->Src_Y) ? this->Dest_Y : this->Src_Y; // minimum height
462  Uint16 *x_step = new Uint16[xmin];
463  Uint16 *y_step = new Uint16[ymin];
464  Uint16 *x_fact = new Uint16[xmin];
465  Uint16 *y_fact = new Uint16[ymin];
466 
467  /*
468  * Approach: If one pixel line has to be added or removed it is taken from the middle of the image (1/2).
469  * For two lines it is at 1/3 and 2/3 of the image and so on. It sounds easy but it was a hard job ;-)
470  */
471 
472  if ((x_step != NULL) && (y_step != NULL) && (x_fact != NULL) && (y_fact != NULL))
473  {
474  register Uint16 x;
475  register Uint16 y;
476  if (this->Dest_X < this->Src_X)
477  setScaleValues(x_step, this->Dest_X, this->Src_X);
478  else if (this->Dest_X > this->Src_X)
479  setScaleValues(x_fact, this->Src_X, this->Dest_X);
480  if (this->Dest_X <= this->Src_X)
481  OFBitmanipTemplate<Uint16>::setMem(x_fact, 1, xmin); // initialize with default values
482  if (this->Dest_X >= this->Src_X)
483  OFBitmanipTemplate<Uint16>::setMem(x_step, 1, xmin); // initialize with default values
484  x_step[xmin - 1] += Columns - this->Src_X; // skip to next line
485  if (this->Dest_Y < this->Src_Y)
486  setScaleValues(y_step, this->Dest_Y, this->Src_Y);
487  else if (this->Dest_Y > this->Src_Y)
488  setScaleValues(y_fact, this->Src_Y, this->Dest_Y);
489  if (this->Dest_Y <= this->Src_Y)
490  OFBitmanipTemplate<Uint16>::setMem(y_fact, 1, ymin); // initialize with default values
491  if (this->Dest_Y >= this->Src_Y)
492  OFBitmanipTemplate<Uint16>::setMem(y_step, 1, ymin); // initialize with default values
493  y_step[ymin - 1] += Rows - this->Src_Y; // skip to next frame
494  const T *sp;
495  register Uint16 dx;
496  register Uint16 dy;
497  register const T *p;
498  register T *q;
499  register T value;
500  for (int j = 0; j < this->Planes; ++j)
501  {
502  sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
503  q = dest[j];
504  for (unsigned long f = 0; f < this->Frames; ++f)
505  {
506  for (y = 0; y < ymin; ++y)
507  {
508  for (dy = 0; dy < y_fact[y]; ++dy)
509  {
510  for (x = 0, p = sp; x < xmin; ++x)
511  {
512  value = *p;
513  for (dx = 0; dx < x_fact[x]; ++dx)
514  *(q++) = value;
515  p += x_step[x];
516  }
517  }
518  sp += OFstatic_cast(unsigned long, y_step[y]) * OFstatic_cast(unsigned long, Columns);
519  }
520  }
521  }
522  }
523  delete[] x_step;
524  delete[] y_step;
525  delete[] x_fact;
526  delete[] y_fact;
527  }
528 
529 
535  void interpolatePixel(const T *src[],
536  T *dest[])
537  {
538  DCMIMGLE_DEBUG("using scaling algorithm with interpolation from pbmplus toolkit");
539  if ((this->Src_X != Columns) || (this->Src_Y != Rows))
540  {
541  DCMIMGLE_ERROR("interpolated scaling and clipping at the same time not implemented ... ignoring clipping region");
542  this->Src_X = Columns; // temporarily removed 'const' for 'Src_X' in class 'DiTransTemplate'
543  this->Src_Y = Rows; // ... 'Src_Y' ...
544  }
545 
546  /*
547  * based on scaling algorithm from "Extended Portable Bitmap Toolkit" (pbmplus10dec91)
548  * (adapted to be used with signed pixel representation, inverse images - mono1,
549  * various bit depths, multi-frame and multi-plane/color images)
550  */
551 
552  register Uint16 x;
553  register Uint16 y;
554  register const T *p;
555  register T *q;
556  const T *sp = NULL; // initialization avoids compiler warning
557  const T *fp;
558  T *sq;
559 
560  const unsigned long sxscale = OFstatic_cast(unsigned long, (OFstatic_cast(double, this->Dest_X) / OFstatic_cast(double, this->Src_X)) * SCALE_FACTOR);
561  const unsigned long syscale = OFstatic_cast(unsigned long, (OFstatic_cast(double, this->Dest_Y) / OFstatic_cast(double, this->Src_Y)) * SCALE_FACTOR);
562  const signed long maxvalue = DicomImageClass::maxval(this->Bits - isSigned());
563 
564  T *xtemp = new T[this->Src_X];
565  signed long *xvalue = new signed long[this->Src_X];
566 
567  if ((xtemp == NULL) || (xvalue == NULL))
568  {
569  DCMIMGLE_ERROR("can't allocate temporary buffers for interpolation scaling");
570  this->clearPixel(dest);
571  } else {
572  for (int j = 0; j < this->Planes; ++j)
573  {
574  fp = src[j];
575  sq = dest[j];
576  for (unsigned long f = this->Frames; f != 0; --f)
577  {
578  for (x = 0; x < this->Src_X; ++x)
579  xvalue[x] = HALFSCALE_FACTOR;
580  register unsigned long yfill = SCALE_FACTOR;
581  register unsigned long yleft = syscale;
582  register int yneed = 1;
583  int ysrc = 0;
584  for (y = 0; y < this->Dest_Y; ++y)
585  {
586  if (this->Src_Y == this->Dest_Y)
587  {
588  sp = fp;
589  for (x = this->Src_X, p = sp, q = xtemp; x != 0; --x)
590  *(q++) = *(p++);
591  fp += this->Src_X;
592  }
593  else
594  {
595  while (yleft < yfill)
596  {
597  if (yneed && (ysrc < OFstatic_cast(int, this->Src_Y)))
598  {
599  sp = fp;
600  fp += this->Src_X;
601  ++ysrc;
602  }
603  for (x = 0, p = sp; x < this->Src_X; ++x)
604  xvalue[x] += yleft * OFstatic_cast(signed long, *(p++));
605  yfill -= yleft;
606  yleft = syscale;
607  yneed = 1;
608  }
609  if (yneed && (ysrc < OFstatic_cast(int, this->Src_Y)))
610  {
611  sp = fp;
612  fp += this->Src_X;
613  ++ysrc;
614  yneed = 0;
615  }
616  register signed long v;
617  for (x = 0, p = sp, q = xtemp; x < this->Src_X; ++x)
618  {
619  v = xvalue[x] + yfill * OFstatic_cast(signed long, *(p++));
620  v /= SCALE_FACTOR;
621  *(q++) = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v);
622  xvalue[x] = HALFSCALE_FACTOR;
623  }
624  yleft -= yfill;
625  if (yleft == 0)
626  {
627  yleft = syscale;
628  yneed = 1;
629  }
630  yfill = SCALE_FACTOR;
631  }
632  if (this->Src_X == this->Dest_X)
633  {
634  for (x = this->Dest_X, p = xtemp, q = sq; x != 0; --x)
635  *(q++) = *(p++);
636  sq += this->Dest_X;
637  }
638  else
639  {
640  register signed long v = HALFSCALE_FACTOR;
641  register unsigned long xfill = SCALE_FACTOR;
642  register unsigned long xleft;
643  register int xneed = 0;
644  q = sq;
645  for (x = 0, p = xtemp; x < this->Src_X; ++x, ++p)
646  {
647  xleft = sxscale;
648  while (xleft >= xfill)
649  {
650  if (xneed)
651  {
652  ++q;
653  v = HALFSCALE_FACTOR;
654  }
655  v += xfill * OFstatic_cast(signed long, *p);
656  v /= SCALE_FACTOR;
657  *q = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v);
658  xleft -= xfill;
659  xfill = SCALE_FACTOR;
660  xneed = 1;
661  }
662  if (xleft > 0)
663  {
664  if (xneed)
665  {
666  ++q;
667  v = HALFSCALE_FACTOR;
668  xneed = 0;
669  }
670  v += xleft * OFstatic_cast(signed long, *p);
671  xfill -= xleft;
672  }
673  }
674  if (xfill > 0)
675  v += xfill * OFstatic_cast(signed long, *(--p));
676  if (!xneed)
677  {
678  v /= SCALE_FACTOR;
679  *q = OFstatic_cast(T, (v > maxvalue) ? maxvalue : v);
680  }
681  sq += this->Dest_X;
682  }
683  }
684  }
685  }
686  }
687  delete[] xtemp;
688  delete[] xvalue;
689  }
690 
691 
697  void expandPixel(const T *src[],
698  T *dest[])
699  {
700  DCMIMGLE_DEBUG("using expand pixel scaling algorithm with interpolation from c't magazine");
701  const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X);
702  const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y);
703  const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns);
704  const T *sp;
705  double bx, ex;
706  double by, ey;
707  int bxi, exi;
708  int byi, eyi;
709  unsigned long offset;
710  double value, sum;
711  double x_part, y_part;
712  double l_factor, r_factor;
713  double t_factor, b_factor;
714  register int xi;
715  register int yi;
716  register Uint16 x;
717  register Uint16 y;
718  register const T *p;
719  register T *q;
720 
721  /*
722  * based on scaling algorithm from "c't - Magazin fuer Computertechnik" (c't 11/94)
723  * (adapted to be used with signed pixel representation, inverse images - mono1,
724  * various bit depths, multi-frame and multi-plane/color images, combined clipping/scaling)
725  */
726 
727  for (int j = 0; j < this->Planes; ++j)
728  {
729  sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
730  q = dest[j];
731  for (unsigned long f = 0; f < this->Frames; ++f)
732  {
733  for (y = 0; y < this->Dest_Y; ++y)
734  {
735  by = y_factor * OFstatic_cast(double, y);
736  ey = y_factor * (OFstatic_cast(double, y) + 1.0);
737  byi = OFstatic_cast(int, by);
738  eyi = OFstatic_cast(int, ey);
739  if (OFstatic_cast(double, eyi) == ey)
740  --eyi;
741  y_part = OFstatic_cast(double, eyi) / y_factor;
742  b_factor = y_part - OFstatic_cast(double, y);
743  t_factor = (OFstatic_cast(double, y) + 1.0) - y_part;
744  for (x = 0; x < this->Dest_X; ++x)
745  {
746  value = 0;
747  bx = x_factor * OFstatic_cast(double, x);
748  ex = x_factor * (OFstatic_cast(double, x) + 1.0);
749  bxi = OFstatic_cast(int, bx);
750  exi = OFstatic_cast(int, ex);
751  if (OFstatic_cast(double, exi) == ex)
752  --exi;
753  x_part = OFstatic_cast(double, exi) / x_factor;
754  l_factor = x_part - OFstatic_cast(double, x);
755  r_factor = (OFstatic_cast(double, x) + 1.0) - x_part;
756  offset = OFstatic_cast(unsigned long, byi) * OFstatic_cast(unsigned long, Columns);
757  for (yi = byi; yi <= eyi; ++yi)
758  {
759  p = sp + offset + bxi;
760  for (xi = bxi; xi <= exi; ++xi)
761  {
762  sum = OFstatic_cast(double, *(p++));
763  if (bxi != exi)
764  {
765  if (xi == bxi)
766  sum *= l_factor;
767  else
768  sum *= r_factor;
769  }
770  if (byi != eyi)
771  {
772  if (yi == byi)
773  sum *= b_factor;
774  else
775  sum *= t_factor;
776  }
777  value += sum;
778  }
779  offset += Columns;
780  }
781  *(q++) = OFstatic_cast(T, value + 0.5);
782  }
783  }
784  sp += f_size;
785  }
786  }
787  }
788 
789 
795  void reducePixel(const T *src[],
796  T *dest[])
797  {
798  DCMIMGLE_DEBUG("using reduce pixel scaling algorithm with interpolation from c't magazine");
799  const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X);
800  const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y);
801  const double xy_factor = x_factor * y_factor;
802  const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns);
803  const T *sp;
804  double bx, ex;
805  double by, ey;
806  int bxi, exi;
807  int byi, eyi;
808  unsigned long offset;
809  double value, sum;
810  double l_factor, r_factor;
811  double t_factor, b_factor;
812  register int xi;
813  register int yi;
814  register Uint16 x;
815  register Uint16 y;
816  register const T *p;
817  register T *q;
818 
819  /*
820  * based on scaling algorithm from "c't - Magazin fuer Computertechnik" (c't 11/94)
821  * (adapted to be used with signed pixel representation, inverse images - mono1,
822  * various bit depths, multi-frame and multi-plane/color images, combined clipping/scaling)
823  */
824 
825  for (int j = 0; j < this->Planes; ++j)
826  {
827  sp = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
828  q = dest[j];
829  for (unsigned long f = 0; f < this->Frames; ++f)
830  {
831  for (y = 0; y < this->Dest_Y; ++y)
832  {
833  by = y_factor * OFstatic_cast(double, y);
834  ey = y_factor * (OFstatic_cast(double, y) + 1.0);
835  byi = OFstatic_cast(int, by);
836  eyi = OFstatic_cast(int, ey);
837  if (OFstatic_cast(double, eyi) == ey)
838  --eyi;
839  b_factor = 1 + OFstatic_cast(double, byi) - by;
840  t_factor = ey - OFstatic_cast(double, eyi);
841  for (x = 0; x < this->Dest_X; ++x)
842  {
843  value = 0;
844  bx = x_factor * OFstatic_cast(double, x);
845  ex = x_factor * (OFstatic_cast(double, x) + 1.0);
846  bxi = OFstatic_cast(int, bx);
847  exi = OFstatic_cast(int, ex);
848  if (OFstatic_cast(double, exi) == ex)
849  --exi;
850  l_factor = 1 + OFstatic_cast(double, bxi) - bx;
851  r_factor = ex - OFstatic_cast(double, exi);
852  offset = OFstatic_cast(unsigned long, byi) * OFstatic_cast(unsigned long, Columns);
853  for (yi = byi; yi <= eyi; ++yi)
854  {
855  p = sp + offset + bxi;
856  for (xi = bxi; xi <= exi; ++xi)
857  {
858  sum = OFstatic_cast(double, *(p++)) / xy_factor;
859  if (xi == bxi)
860  sum *= l_factor;
861  else if (xi == exi)
862  sum *= r_factor;
863  if (yi == byi)
864  sum *= b_factor;
865  else if (yi == eyi)
866  sum *= t_factor;
867  value += sum;
868  }
869  offset += Columns;
870  }
871  *(q++) = OFstatic_cast(T, value + 0.5);
872  }
873  }
874  sp += f_size;
875  }
876  }
877  }
878 
884  void bilinearPixel(const T *src[],
885  T *dest[])
886  {
887  DCMIMGLE_DEBUG("using magnification algorithm with bilinear interpolation contributed by Eduard Stanescu");
888  const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X);
889  const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y);
890  const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns);
891  const unsigned long l_offset = OFstatic_cast(unsigned long, this->Src_Y - 1) * OFstatic_cast(unsigned long, this->Dest_X);
892  register Uint16 x;
893  register Uint16 y;
894  register T *pD;
895  register T *pCurrTemp;
896  register const T *pCurrSrc;
897  Uint16 nSrcIndex;
898  double dOff;
899  T *pT;
900  const T *pS;
901  const T *pF;
902 
903  // buffer used for storing temporarily the interpolated lines
904  T *pTemp = new T[OFstatic_cast(unsigned long, this->Src_Y) * OFstatic_cast(unsigned long, this->Dest_X)];
905  if (pTemp == NULL)
906  {
907  DCMIMGLE_ERROR("can't allocate temporary buffer for interpolation scaling");
908  this->clearPixel(dest);
909  } else {
910 
911  /*
912  * based on scaling algorithm contributed by Eduard Stanescu
913  * (adapted to be used with signed pixel representation, inverse images - mono1,
914  * various bit depths, multi-frame multi-plane/color images, combined clipping/scaling)
915  */
916 
917  for (int j = 0; j < this->Planes; ++j)
918  {
919  pF = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
920  pD = dest[j];
921  for (unsigned long f = this->Frames; f != 0; --f)
922  {
923  pT = pCurrTemp = pTemp;
924  pS = pCurrSrc = pF;
925  // first, interpolate the columns:
926  // column 0, just copy the source data column 0
927  for (y = this->Src_Y; y != 0; --y)
928  {
929  *(pCurrTemp) = *(pCurrSrc);
930  pCurrSrc += Columns;
931  pCurrTemp += this->Dest_X;
932  }
933  pCurrSrc = pS;
934  nSrcIndex = 0;
935  // column 1 to column Dest_X - 1
936  for (x = 1; x < this->Dest_X - 1; ++x)
937  {
938  pCurrTemp = ++pT;
939  dOff = x * x_factor - nSrcIndex;
940  dOff = (1.0 < dOff) ? 1.0 : dOff;
941  for (y = 0; y < this->Src_Y; ++y)
942  {
943  *(pCurrTemp) = OFstatic_cast(T, *(pCurrSrc) + (*(pCurrSrc + 1) - *(pCurrSrc)) * dOff);
944  pCurrSrc += Columns;
945  pCurrTemp += this->Dest_X;
946  }
947  // don't go beyond the source data
948  if ((nSrcIndex < this->Src_X - 2) && (x * x_factor >= nSrcIndex + 1))
949  {
950  pS++;
951  nSrcIndex++;
952  }
953  pCurrSrc = pS;
954  }
955  pCurrTemp = ++pT;
956  // last column, just copy the source data column Src_X
957  for (y = this->Src_Y; y != 0; --y)
958  {
959  *(pCurrTemp) = *(pCurrSrc);
960  pCurrSrc += Columns;
961  pCurrTemp += this->Dest_X;
962  }
963  // now the columns are interpolated in temp buffer, so interpolate the lines
964  pT = pCurrTemp = pTemp;
965  // line 0, just copy the temp buffer line 0
966  for (x = this->Dest_X; x != 0; --x)
967  *(pD++) = *(pCurrTemp++);
968  nSrcIndex = 0;
969  pCurrTemp = pTemp;
970  for (y = 1; y < this->Dest_Y - 1; ++y)
971  {
972  dOff = y * y_factor - nSrcIndex;
973  dOff = (1.0 < dOff) ? 1.0 : dOff;
974  for (x = this->Dest_X; x != 0; --x)
975  {
976  *(pD++) = OFstatic_cast(T, *(pCurrTemp) + (*(pCurrTemp + this->Dest_X) - *(pCurrTemp)) * dOff);
977  pCurrTemp++;
978  }
979  // don't go beyond the source data
980  if ((nSrcIndex < this->Src_Y - 2) && (y * y_factor >= nSrcIndex + 1))
981  {
982  pT += this->Dest_X;
983  nSrcIndex++;
984  }
985  pCurrTemp = pT;
986  }
987  // the last line, just copy the temp buffer line Src_X
988  pCurrTemp = pTemp + l_offset;
989  for (x = this->Dest_X; x != 0; --x)
990  *(pD++) = *(pCurrTemp++);
991  // skip to next frame
992  pF += f_size;
993  }
994  }
995  }
996  delete[] pTemp;
997  }
998 
1004  void bicubicPixel(const T *src[],
1005  T *dest[])
1006  {
1007  DCMIMGLE_DEBUG("using magnification algorithm with bicubic interpolation contributed by Eduard Stanescu");
1008  const double minVal = (isSigned()) ? -OFstatic_cast(double, DicomImageClass::maxval(this->Bits - 1, 0)) : 0.0;
1009  const double maxVal = OFstatic_cast(double, DicomImageClass::maxval(this->Bits - isSigned()));
1010  const double x_factor = OFstatic_cast(double, this->Src_X) / OFstatic_cast(double, this->Dest_X);
1011  const double y_factor = OFstatic_cast(double, this->Src_Y) / OFstatic_cast(double, this->Dest_Y);
1012  const Uint16 xDelta = OFstatic_cast(Uint16, 1 / x_factor);
1013  const Uint16 yDelta = OFstatic_cast(Uint16, 1 / y_factor);
1014  const unsigned long f_size = OFstatic_cast(unsigned long, Rows) * OFstatic_cast(unsigned long, Columns);
1015  const unsigned long l_offset = OFstatic_cast(unsigned long, this->Src_Y - 1) * OFstatic_cast(unsigned long, this->Dest_X);
1016  register Uint16 x;
1017  register Uint16 y;
1018  register T *pD;
1019  register T *pCurrTemp;
1020  register const T *pCurrSrc;
1021  Uint16 nSrcIndex;
1022  double dOff;
1023  T *pT;
1024  const T *pS;
1025  const T *pF;
1026 
1027  // buffer used for storing temporarily the interpolated lines
1028  T *pTemp = pT = pCurrTemp = new T[OFstatic_cast(unsigned long, this->Src_Y) * OFstatic_cast(unsigned long, this->Dest_X)];
1029  if (pTemp == NULL)
1030  {
1031  DCMIMGLE_ERROR("can't allocate temporary buffer for interpolation scaling");
1032  this->clearPixel(dest);
1033  } else {
1034 
1035  /*
1036  * based on scaling algorithm contributed by Eduard Stanescu
1037  * (adapted to be used with signed pixel representation, inverse images - mono1,
1038  * various bit depths, multi-frame multi-plane/color images, combined clipping/scaling)
1039  */
1040 
1041  for (int j = 0; j < this->Planes; ++j)
1042  {
1043  pF = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left;
1044  pD = dest[j];
1045  for (unsigned long f = this->Frames; f != 0; --f)
1046  {
1047  pT = pCurrTemp = pTemp;
1048  pS = pCurrSrc = pF;
1049  // first, interpolate the columns:
1050  // column 0, just copy the source data column 0
1051  for (y = this->Src_Y; y != 0; --y)
1052  {
1053  *(pCurrTemp) = *(pCurrSrc);
1054  pCurrSrc += Columns;
1055  pCurrTemp += this->Dest_X;
1056  }
1057  pCurrSrc = pS;
1058  // for the next few columns, linear interpolation
1059  for (x = 1; x < xDelta + 1; ++x)
1060  {
1061  pCurrSrc = pS;
1062  pCurrTemp = ++pT;
1063  dOff = x * x_factor;
1064  dOff = (1.0 < dOff) ? 1.0 : dOff;
1065  for (y = this->Src_Y; y != 0; --y)
1066  {
1067  *(pCurrTemp) = OFstatic_cast(T, *(pCurrSrc) + (*(pCurrSrc + 1) - *(pCurrSrc)) * dOff);
1068  pCurrSrc += Columns;
1069  pCurrTemp += this->Dest_X;
1070  }
1071  }
1072  nSrcIndex = 1;
1073  pCurrSrc = ++pS;
1074  // the majority of the columns
1075  for (x = xDelta + 1; x < this->Dest_X - 2 * xDelta; ++x)
1076  {
1077  pCurrTemp = ++pT;
1078  dOff = x * x_factor - nSrcIndex;
1079  dOff = (1.0 < dOff) ? 1.0 : dOff;
1080  for (y = this->Src_Y; y != 0; --y)
1081  {
1082  *(pCurrTemp) = OFstatic_cast(T, cubicValue(*(pCurrSrc - 1), *(pCurrSrc), *(pCurrSrc + 1), *(pCurrSrc + 2), dOff, minVal, maxVal));
1083  pCurrSrc += Columns;
1084  pCurrTemp += this->Dest_X;
1085  }
1086  // don't go beyond the source data
1087  if ((nSrcIndex < this->Src_X - 3) && (x * x_factor >= nSrcIndex + 1))
1088  {
1089  pS++;
1090  nSrcIndex++;
1091  }
1092  pCurrSrc = pS;
1093  }
1094  // last few columns except the very last one, linear interpolation
1095  for (x = this->Dest_X - 2 * xDelta; x < this->Dest_X - 1; ++x)
1096  {
1097  pCurrTemp = ++pT;
1098  dOff = x * x_factor - nSrcIndex;
1099  dOff = (1.0 < dOff) ? 1.0 : dOff;
1100  for (y = this->Src_Y; y != 0; --y)
1101  {
1102  *(pCurrTemp) = OFstatic_cast(T, *(pCurrSrc) + (*(pCurrSrc + 1) - *(pCurrSrc)) * dOff);
1103  pCurrSrc += Columns;
1104  pCurrTemp += this->Dest_X;
1105  }
1106  // don't go beyond the source data
1107  if ((nSrcIndex < this->Src_X - 2) && (x * x_factor >= nSrcIndex + 1))
1108  {
1109  pS++;
1110  nSrcIndex++;
1111  }
1112  pCurrSrc = pS;
1113  }
1114  // last column, just copy the source data column Src_X
1115  pCurrTemp = pTemp + this->Dest_X - 1;
1116  pCurrSrc = pF + this->Src_X - 1;
1117  for (y = this->Src_Y; y != 0; --y)
1118  {
1119  *(pCurrTemp) = *(pCurrSrc);
1120  pCurrSrc += Columns;
1121  pCurrTemp += this->Dest_X;
1122  }
1123  // now the columns are interpolated in temp buffer, so interpolate the lines
1124  pT = pCurrTemp = pTemp;
1125  // line 0, just copy the temp buffer line 0
1126  for (x = this->Dest_X; x != 0; --x)
1127  *(pD++) = *(pCurrTemp++);
1128  // for the next few lines, linear interpolation between line 0 and 1 of the temp buffer
1129  for (y = 1; y < yDelta + 1; ++y)
1130  {
1131  pCurrTemp = pTemp;
1132  dOff = y * y_factor;
1133  dOff = (1.0 < dOff) ? 1.0 : dOff;
1134  for (x = this->Dest_X; x != 0; --x)
1135  {
1136  *(pD++) = OFstatic_cast(T, *(pCurrTemp) + (*(pCurrTemp + this->Dest_X) - *(pCurrTemp)) * dOff);
1137  pCurrTemp++;
1138  }
1139  }
1140  nSrcIndex = 1;
1141  pCurrTemp = pT = pTemp + this->Dest_X;
1142  for (y = yDelta + 1; y < this->Dest_Y - yDelta - 1; ++y)
1143  {
1144  dOff = y * y_factor - nSrcIndex;
1145  dOff = (1.0 < dOff) ? 1.0 : dOff;
1146  for (x = this->Dest_X; x != 0; --x)
1147  {
1148  *(pD++) = OFstatic_cast(T, cubicValue(*(pCurrTemp - this->Dest_X),*(pCurrTemp), *(pCurrTemp + this->Dest_X),
1149  *(pCurrTemp + this->Dest_X + this->Dest_X), dOff, minVal, maxVal));
1150  pCurrTemp++;
1151  }
1152  // don't go beyond the source data
1153  if ((nSrcIndex < this->Src_Y - 3) && (y * y_factor >= nSrcIndex + 1))
1154  {
1155  pT += this->Dest_X;
1156  nSrcIndex++;
1157  }
1158  pCurrTemp = pT;
1159  }
1160  // the last few lines except the very last one, linear interpolation in between the second last and the last lines
1161  pCurrTemp = pT = pTemp + OFstatic_cast(unsigned long, this->Src_Y - 2) * OFstatic_cast(unsigned long, this->Dest_X);
1162  for (y = this->Dest_Y - yDelta - 1; y < this->Dest_Y - 1; ++y)
1163  {
1164  dOff = y * y_factor - nSrcIndex;
1165  dOff = (1.0 < dOff) ? 1.0 : dOff;
1166  for (x = this->Dest_X; x != 0; --x)
1167  {
1168  *(pD++) = OFstatic_cast(T, *(pCurrTemp) + (*(pCurrTemp + this->Dest_X) - *(pCurrTemp)) * dOff);
1169  pCurrTemp++;
1170  }
1171  pCurrTemp = pT;
1172  }
1173  // the the last line, just copy the temp buffer line Src_X
1174  pCurrTemp = pTemp + l_offset;
1175  for (x = this->Dest_X; x != 0; --x)
1176  *(pD++) = *(pCurrTemp++);
1177  // skip to next frame
1178  pF += f_size;
1179  }
1180  }
1181  }
1182  delete[] pTemp;
1183  }
1184 };
1185 
1186 #endif
1187 
1188 
1189 /*
1190  *
1191  * CVS/RCS Log:
1192  * $Log: discalet.h,v $
1193  * Revision 1.36 2011-11-17 16:13:16 joergr
1194  * Minor fixes to keep XCode 4.2 on Mac OS X Lion (clang compiler) quiet.
1195  *
1196  * Revision 1.35 2010-10-14 13:16:27 joergr
1197  * Updated copyright header. Added reference to COPYRIGHT file.
1198  *
1199  * Revision 1.34 2010-03-01 09:08:47 uli
1200  * Removed some unnecessary include directives in the headers.
1201  *
1202  * Revision 1.33 2009-11-25 15:49:25 joergr
1203  * Removed inclusion of header file "ofconsol.h".
1204  *
1205  * Revision 1.32 2009-10-28 14:38:17 joergr
1206  * Fixed minor issues in log output.
1207  *
1208  * Revision 1.31 2009-10-28 09:53:40 uli
1209  * Switched to logging mechanism provided by the "new" oflog module.
1210  *
1211  * Revision 1.30 2008-05-21 10:12:27 joergr
1212  * Fixed bug in c't scaling algorithm (expandPixel) which could cause a crash
1213  * (possible integer underflow/overflow).
1214  *
1215  * Revision 1.29 2008-05-20 15:26:45 joergr
1216  * Fixed small issue in bicubic image scaling algorithm (in clipping mode).
1217  *
1218  * Revision 1.28 2008-05-20 13:16:38 joergr
1219  * Fixed issue with signed pixel data in bicubic interpolation algorithm.
1220  * Use the pbmplus scaling algorithm as the second best fallback if the c't
1221  * algorithm cannot be used (e.g. up and down-scaling on different axes).
1222  * Replaced macro call by inline function (approx. same performance).
1223  *
1224  * Revision 1.27 2008-05-20 10:37:00 joergr
1225  * Added new bilinear and bicubic scaling algorithms for image magnification.
1226  * Now the c't scaling algorithm is used as a fallback if the preferred
1227  * algorithm with interpolation is not applicable.
1228  * Fixed bug in c't scaling algorithm (reducePixel) which could cause a crash.
1229  *
1230  * Revision 1.26 2006/08/15 16:30:11 meichel
1231  * Updated the code in module dcmimgle to correctly compile when
1232  * all standard C++ classes remain in namespace std.
1233  *
1234  * Revision 1.25 2005/12/08 16:48:09 meichel
1235  * Changed include path schema for all DCMTK header files
1236  *
1237  * Revision 1.24 2004/04/21 10:00:36 meichel
1238  * Minor modifications for compilation with gcc 3.4.0
1239  *
1240  * Revision 1.23 2004/01/05 14:52:20 joergr
1241  * Removed acknowledgements with e-mail addresses from CVS log.
1242  *
1243  * Revision 1.22 2003/12/23 15:53:22 joergr
1244  * Replaced post-increment/decrement operators by pre-increment/decrement
1245  * operators where appropriate (e.g. 'i++' by '++i').
1246  *
1247  * Revision 1.21 2003/12/09 10:25:06 joergr
1248  * Adapted type casts to new-style typecast operators defined in ofcast.h.
1249  * Removed leading underscore characters from preprocessor symbols (reserved
1250  * symbols). Updated copyright header.
1251  *
1252  * Revision 1.20 2002/12/09 13:32:56 joergr
1253  * Renamed parameter/local variable to avoid name clashes with global
1254  * declaration left and/or right (used for as iostream manipulators).
1255  *
1256  * Revision 1.19 2002/04/16 13:53:12 joergr
1257  * Added configurable support for C++ ANSI standard includes (e.g. streams).
1258  *
1259  * Revision 1.18 2001/06/01 15:49:51 meichel
1260  * Updated copyright header
1261  *
1262  * Revision 1.17 2000/05/03 09:46:29 joergr
1263  * Removed most informational and some warning messages from release built
1264  * (#ifndef DEBUG).
1265  *
1266  * Revision 1.16 2000/04/28 12:32:33 joergr
1267  * DebugLevel - global for the module - now derived from OFGlobal (MT-safe).
1268  *
1269  * Revision 1.15 2000/04/27 13:08:42 joergr
1270  * Dcmimgle library code now consistently uses ofConsole for error output.
1271  *
1272  * Revision 1.14 2000/03/08 16:24:24 meichel
1273  * Updated copyright header.
1274  *
1275  * Revision 1.13 2000/03/07 16:15:13 joergr
1276  * Added explicit type casts to make Sun CC 2.0.1 happy.
1277  *
1278  * Revision 1.12 2000/03/03 14:09:14 meichel
1279  * Implemented library support for redirecting error messages into memory
1280  * instead of printing them to stdout/stderr for GUI applications.
1281  *
1282  * Revision 1.11 1999/11/19 12:37:19 joergr
1283  * Fixed bug in scaling method "reducePixel" (reported by gcc 2.7.2.1).
1284  *
1285  * Revision 1.10 1999/09/17 13:07:20 joergr
1286  * Added/changed/completed DOC++ style comments in the header files.
1287  * Enhanced efficiency of some "for" loops.
1288  *
1289  * Revision 1.9 1999/08/25 16:41:55 joergr
1290  * Added new feature: Allow clipping region to be outside the image
1291  * (overlapping).
1292  *
1293  * Revision 1.8 1999/07/23 14:09:24 joergr
1294  * Added new interpolation algorithm for scaling.
1295  *
1296  * Revision 1.7 1999/04/28 14:55:05 joergr
1297  * Introduced new scheme for the debug level variable: now each level can be
1298  * set separately (there is no "include" relationship).
1299  *
1300  * Revision 1.6 1999/03/24 17:20:24 joergr
1301  * Added/Modified comments and formatting.
1302  *
1303  * Revision 1.5 1999/02/11 16:42:10 joergr
1304  * Removed inline declarations from several methods.
1305  *
1306  * Revision 1.4 1999/02/03 17:35:14 joergr
1307  * Moved global functions maxval() and determineRepresentation() to class
1308  * DicomImageClass (as static methods).
1309  *
1310  * Revision 1.3 1998/12/22 14:39:44 joergr
1311  * Added some preparation to enhance interpolated scaling (clipping and
1312  * scaling) in the future.
1313  *
1314  * Revision 1.2 1998/12/16 16:39:45 joergr
1315  * Implemented combined clipping and scaling for pixel replication and
1316  * suppression.
1317  *
1318  * Revision 1.1 1998/11/27 15:47:11 joergr
1319  * Added copyright message.
1320  * Combined clipping and scaling methods.
1321  *
1322  * Revision 1.4 1998/05/11 14:53:29 joergr
1323  * Added CVS/RCS header to each file.
1324  *
1325  *
1326  */


Generated on Thu Dec 20 2012 for OFFIS DCMTK Version 3.6.0 by Doxygen 1.8.2