📄 discalet.h
字号:
/* * * Copyright (C) 1996-2005, OFFIS * * This software and supporting documentation were developed by * * Kuratorium OFFIS e.V. * Healthcare Information and Communication Systems * Escherweg 2 * D-26121 Oldenburg, Germany * * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND * PERFORMANCE OF THE SOFTWARE IS WITH THE USER. * * Module: dcmimgle * * Author: Joerg Riesmeier * * Purpose: DicomScaleTemplates (Header) * * Last Update: $Author: meichel $ * Update Date: $Date: 2005/12/08 16:48:09 $ * CVS/RCS Revision: $Revision: 1.25 $ * Status: $State: Exp $ * * CVS/RCS Log at end of file * */#ifndef DISCALET_H#define DISCALET_H#include "dcmtk/config/osconfig.h"#include "dcmtk/dcmdata/dctypes.h"#include "dcmtk/ofstd/ofconsol.h"#include "dcmtk/ofstd/ofcast.h"#include "dcmtk/ofstd/ofstream.h"#include "dcmtk/dcmimgle/ditranst.h"#include "dcmtk/dcmimgle/dipxrept.h"#include "dcmtk/dcmimgle/diutils.h"/*---------------------* * macro definitions * *---------------------*/#define SCALE_FACTOR 4096#define HALFSCALE_FACTOR 2048/*--------------------* * helper functions * *--------------------*/// help function to set scaling valuesstatic inline void setScaleValues(Uint16 data[], const Uint16 min, const Uint16 max){ register Uint16 remainder = max % min; Uint16 step0 = max / min; Uint16 step1 = max / min; if (remainder > OFstatic_cast(Uint16, min / 2)) { remainder = min - remainder; ++step0; } else ++step1; const double count = OFstatic_cast(double, min) / (OFstatic_cast(double, remainder) + 1); register Uint16 i; register double c = count; for (i = 0; i < min; ++i) { if ((i >= OFstatic_cast(Uint16, c)) && (remainder > 0)) { --remainder; c += count; data[i] = step1; } else data[i] = step0; }}/*---------------------* * class declaration * *---------------------*//** Template class to scale images (on pixel data level). * with and without interpolation */template<class T>class DiScaleTemplate : public DiTransTemplate<T>{ public: /** constructor, scale clipping area. * ** @param planes number of planes (1 or 3) * @param columns width of source image * @param rows height of source image * @param left_pos left coordinate of clipping area * @param top_pos top coordinate of clipping area * @param src_cols width of clipping area * @param src_rows height of clipping area * @param dest_cols width of destination image (scaled image) * @param dest_rows height of destination image * @param frames number of frames * @param bits number of bits per plane/pixel */ DiScaleTemplate(const int planes, const Uint16 columns, /* resolution of source image */ const Uint16 rows, const signed long left_pos, /* origin of clipping area */ const signed long top_pos, const Uint16 src_cols, /* extension of clipping area */ const Uint16 src_rows, const Uint16 dest_cols, /* extension of destination image */ const Uint16 dest_rows, const Uint32 frames, /* number of frames */ const int bits = 0) : DiTransTemplate<T>(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits), Left(left_pos), Top(top_pos), Columns(columns), Rows(rows) { } /** constructor, scale whole image. * ** @param planes number of planes (1 or 3) * @param src_cols width of source image * @param src_rows height of source image * @param dest_cols width of destination image (scaled image) * @param dest_rows height of destination image * @param frames number of frames * @param bits number of bits per plane/pixel */ DiScaleTemplate(const int planes, const Uint16 src_cols, /* resolution of source image */ const Uint16 src_rows, const Uint16 dest_cols, /* resolution of destination image */ const Uint16 dest_rows, const Uint32 frames, /* number of frames */ const int bits = 0) : DiTransTemplate<T>(planes, src_cols, src_rows, dest_cols, dest_rows, frames, bits), Left(0), Top(0), Columns(src_cols), Rows(src_rows) { } /** destructor */ virtual ~DiScaleTemplate() { } /** choose scaling/clipping algorithm depending on specified parameters. * ** @param src array of pointers to source image pixels * @param dest array of pointers to destination image pixels * @param interpolate interpolation algorithm (0 = no interpolation, 1 = pbmplus algorithm, 2 = c't algorithm) * @param value value to be set outside the image boundaries (used for clipping, default: 0) */ void scaleData(const T *src[], // combined clipping and scaling UNTESTED for multi-frame images !! T *dest[], const int interpolate, const T value = 0) { if ((src != NULL) && (dest != NULL)) {#ifdef DEBUG if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_DebugMessages)) { ofConsole.lockCout() << "C/R: " << Columns << " " << Rows << endl << "L/T: " << Left << " " << Top << endl << "SX/Y: " << this->Src_X << " " << this->Src_Y << endl << "DX/Y: " << this->Dest_X << " " << this->Dest_Y << endl; ofConsole.unlockCout(); }#endif if ((Left + OFstatic_cast(signed long, this->Src_X) <= 0) || (Top + OFstatic_cast(signed long, this->Src_Y) <= 0) || (Left >= OFstatic_cast(signed long, Columns)) || (Top >= OFstatic_cast(signed long, Rows))) { // no image to be displayed#ifdef DEBUG if (DicomImageClass::checkDebugLevel(DicomImageClass::DL_Informationals)) { ofConsole.lockCerr() << "INFO: clipping area is fully outside the image boundaries !" << endl; ofConsole.unlockCerr(); }#endif fillPixel(dest, value); // ... fill bitmap } else if ((this->Src_X == this->Dest_X) && (this->Src_Y == this->Dest_Y)) // no scaling { if ((Left == 0) && (Top == 0) && (Columns == this->Src_X) && (Rows == this->Src_Y)) copyPixel(src, dest); // copying else if ((Left >= 0) && (OFstatic_cast(Uint16, Left + this->Src_X) <= Columns) && (Top >= 0) && (OFstatic_cast(Uint16, Top + this->Src_Y) <= Rows)) clipPixel(src, dest); // clipping else clipBorderPixel(src, dest, value); // clipping (with border) } else if ((interpolate == 1) && (this->Bits <= MAX_INTERPOLATION_BITS)) // interpolation (pbmplus) interpolatePixel(src, dest); else if ((interpolate == 2) && (this->Dest_X >= this->Src_X) && (this->Dest_Y >= this->Src_Y)) // interpolated expansion (c't) expandPixel(src, dest); else if ((interpolate == 2) && (this->Src_X >= this->Dest_X) && (this->Src_Y >= this->Dest_Y)) // interpolated reduction (c't) reducePixel(src, dest); else if ((this->Dest_X % this->Src_X == 0) && (this->Dest_Y % this->Src_Y == 0)) // replication replicatePixel(src, dest); else if ((this->Src_X % this->Dest_X == 0) && (this->Src_Y % this->Dest_Y == 0)) // supression suppressPixel(src, dest); else // general scaling scalePixel(src, dest); } } protected: /// left coordinate of clipping area const signed long Left; /// top coordinate of clipping area const signed long Top; /// width of source image const Uint16 Columns; /// height of source image const Uint16 Rows; private: /** clip image to specified area (only inside image boundaries). * This is an optimization of the more general method clipBorderPixel(). * ** @param src array of pointers to source image pixels * @param dest array of pointers to destination image pixels */ void clipPixel(const T *src[], T *dest[]) { const unsigned long x_feed = Columns - this->Src_X; const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - this->Src_Y) * OFstatic_cast(unsigned long, Columns); register Uint16 x; register Uint16 y; register const T *p; register T *q; for (int j = 0; j < this->Planes; ++j) { p = src[j] + OFstatic_cast(unsigned long, Top) * OFstatic_cast(unsigned long, Columns) + Left; q = dest[j]; for (unsigned long f = this->Frames; f != 0; --f) { for (y = this->Dest_Y; y != 0; --y) { for (x = this->Dest_X; x != 0; --x) *(q++) = *(p++); p += x_feed; } p += y_feed; } } } /** clip image to specified area and add a border if necessary. * NOT fully tested - UNTESTED for multi-frame and multi-plane images !! * ** @param src array of pointers to source image pixels * @param dest array of pointers to destination image pixels * @param value value to be set outside the image boundaries */ void clipBorderPixel(const T *src[], T *dest[], const T value) { const Uint16 s_left = (Left > 0) ? OFstatic_cast(Uint16, Left) : 0; const Uint16 s_top = (Top > 0) ? OFstatic_cast(Uint16, Top) : 0; const Uint16 d_left = (Left < 0 ? OFstatic_cast(Uint16, -Left) : 0); const Uint16 d_top = (Top < 0) ? OFstatic_cast(Uint16, -Top) : 0; const Uint16 d_right = (OFstatic_cast(unsigned long, this->Src_X) + OFstatic_cast(unsigned long, s_left) < OFstatic_cast(unsigned long, Columns) + OFstatic_cast(unsigned long, d_left)) ? (this->Src_X - 1) : (Columns + d_left - s_left - 1); const Uint16 d_bottom = (OFstatic_cast(unsigned long, this->Src_Y) + OFstatic_cast(unsigned long, s_top) < OFstatic_cast(unsigned long, Rows) + OFstatic_cast(unsigned long, d_top)) ? (this->Src_Y - 1) : (Rows + d_top - s_top - 1); const Uint16 x_count = d_right - d_left + 1; const Uint16 y_count = d_bottom - d_top + 1; const unsigned long s_start = OFstatic_cast(unsigned long, s_top) * OFstatic_cast(unsigned long, Columns) + s_left; const unsigned long x_feed = Columns - x_count; const unsigned long y_feed = OFstatic_cast(unsigned long, Rows - y_count) * Columns; const unsigned long t_feed = OFstatic_cast(unsigned long, d_top) * OFstatic_cast(unsigned long, this->Src_X); const unsigned long b_feed = OFstatic_cast(unsigned long, this->Src_Y - d_bottom - 1) * OFstatic_cast(unsigned long, this->Src_X); /* * The approach is to divide the destination image in up to four areas outside the source image * plus one area for the source image. The for and while loops are scanning linearly over the * destination image and setting the appropriate value depending on the current area. This is * different from most of the other algorithms in this toolkit where the source image is scanned * linearly. */ register Uint16 x; register Uint16 y; register unsigned long i; register const T *p; register T *q; for (int j = 0; j < this->Planes; ++j) { p = src[j] + s_start; q = dest[j]; for (unsigned long f = this->Frames; f != 0; --f) { for (i = t_feed; i != 0; --i) // top *(q++) = value; for (y = y_count; y != 0; --y) // middle part: { x = 0; while (x < d_left) // - left
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -