├── .gitignore ├── README.md ├── images ├── butler.pgm ├── empire.pgm ├── eye50.pgm ├── lowContrast.jpg ├── mad256.pgm ├── maddot.pgm ├── mandrill.jpg ├── mandrill256.pgm ├── mandrill_crop.png ├── mandrill_eye.jpg ├── mandrill_nose.jpg ├── mandrill_right_face.jpg ├── met.pgm ├── ramp.pgm ├── star.pgm ├── text.pgm └── text40.pgm ├── screenshots ├── blur_in.png ├── blur_out.png ├── contrast_in.png ├── contrast_out.png ├── correlation_in.png ├── correlation_out.png ├── interface.png ├── median_in.png └── median_out.png └── src ├── Blur.cpp ├── Blur.h ├── Clip.cpp ├── Clip.h ├── Contrast.cpp ├── Contrast.h ├── Convolve.cpp ├── Convolve.h ├── Correlation.cpp ├── Correlation.h ├── Dummy.cpp ├── Dummy.h ├── ErrDiffusion.cpp ├── ErrDiffusion.h ├── GLWidget.cpp ├── GLWidget.h ├── Gamma.cpp ├── Gamma.h ├── HistoMatch.cpp ├── HistoMatch.h ├── HistoStretch.cpp ├── HistoStretch.h ├── IP ├── linux │ └── header │ │ ├── Channel.h │ │ ├── ChannelPtr.h │ │ ├── ChannelPtr.tpp │ │ ├── IP.h │ │ ├── IPdefs.h │ │ ├── IPmmch.tpp │ │ ├── IPtoUI.h │ │ ├── Image.h │ │ └── ImagePtr.h ├── mac │ └── header │ │ ├── Channel.h │ │ ├── ChannelPtr.h │ │ ├── ChannelPtr.tpp │ │ ├── IP.h │ │ ├── IPdefs.h │ │ ├── IPmmch.tpp │ │ ├── IPtoUI.h │ │ ├── Image.h │ │ └── ImagePtr.h └── win │ ├── header │ ├── Channel.h │ ├── ChannelPtr.h │ ├── ChannelPtr.tpp │ ├── IP.h │ ├── IPdefs.h │ ├── IPmmch.tpp │ ├── IPtoUI.h │ ├── Image.h │ └── ImagePtr.h │ └── lib │ ├── IP.lib │ └── IP_d.lib ├── ImageFilter.cpp ├── ImageFilter.h ├── MainWindow.cpp ├── MainWindow.h ├── Median.cpp ├── Median.h ├── Quantize.cpp ├── Quantize.h ├── Sharpen.cpp ├── Sharpen.h ├── Threshold.cpp ├── Threshold.h ├── fshader_passthrough.glsl ├── fshader_passthrough_Mac.glsl ├── kernels ├── kernelBlur3x3.AF ├── kernelBlur7x7.AF ├── kernelEdgeX.AF ├── kernelEdgeY.AF ├── kernelLaplacian1.AF └── kernelLaplacian5.AF ├── main.cpp ├── ops_neighborhood ├── HW_blur.cpp ├── HW_convolve.cpp ├── HW_correlation.cpp ├── HW_errDiffusion.cpp ├── HW_median.cpp ├── HW_sharpen.cpp ├── fshader_blur1.glsl ├── fshader_blur1_Mac.glsl ├── fshader_blur2.glsl ├── fshader_blur2_Mac.glsl ├── fshader_convolve.glsl ├── fshader_convolve_Mac.glsl ├── fshader_correlation.glsl ├── fshader_correlation_Mac.glsl ├── fshader_myblur.glsl ├── fshader_myblur_Mac.glsl ├── fshader_sharpen.glsl └── fshader_sharpen_Mac.glsl ├── ops_point ├── HW_clip.cpp ├── HW_contrast.cpp ├── HW_gamma.cpp ├── HW_histoMatch.cpp ├── HW_histoStretch.cpp ├── HW_quantize.cpp ├── HW_threshold.cpp ├── fshader_clip.glsl ├── fshader_clip_Mac.glsl ├── fshader_contrast.glsl ├── fshader_contrast_Mac.glsl ├── fshader_gamma.glsl ├── fshader_gamma_Mac.glsl ├── fshader_histoStretch.glsl ├── fshader_histoStretch_Mac.glsl ├── fshader_quantize.glsl ├── fshader_quantize_Mac.glsl ├── fshader_threshold.glsl └── fshader_threshold_Mac.glsl ├── qcustomplot.cpp ├── qcustomplot.h ├── qip.pro ├── qip.qrc ├── vshader_passthrough.glsl └── vshader_passthrough_Mac.glsl /.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | Info.plist 3 | moc*.cpp 4 | *.build 5 | *.Debug 6 | *.Release 7 | release 8 | *.pro.user 9 | *.xcodeproj 10 | .DS_Store 11 | *.stash 12 | xcshareddata/ 13 | project.pbxproj 14 | project.xcworkspace/ 15 | qt_makeqmake.mak 16 | qt_preprocess.mak 17 | 18 | 19 | # C++ objects and libs 20 | 21 | *.slo 22 | *.lo 23 | *.o 24 | *.a 25 | *.la 26 | *.lai 27 | *.so 28 | *.dll 29 | *.dylib 30 | 31 | # Qt-es 32 | 33 | /.qmake.cache 34 | /.qmake.stash 35 | *.pro.user 36 | *.pro.user.* 37 | *.qbs.user 38 | *.qbs.user.* 39 | *.moc 40 | moc_*.cpp 41 | qrc_*.cpp 42 | ui_*.h 43 | Makefile* 44 | *build-* 45 | 46 | # QtCreator 47 | 48 | *.autosave 49 | 50 | #QtCtreator Qml 51 | *.qmlproject.user 52 | *.qmlproject.user.* 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image Processing Application 2 | Basic image processing application written in C++ and OpenGL with Qt on a starter program given by Professor [George Wolberg](http://www-cs.engr.ccny.cuny.edu/~wolberg/) 3 | 4 | ## Interface 5 | The application interface is implemented with Qt. 6 | Qt is a cross-platform application framework for developing application software. 7 | Qt libraries are used in this application to create windows, layouts, menus, buttons, widgets and etc. 8 | 9 | ![interface](/screenshots/interface.png) 10 | 11 | ## Image Filters 12 | - Point Operations 13 | * [x] Threshold 14 | * [x] Clip 15 | * [x] Contrast Enhancement 16 | * [x] Gamma Corretion 17 | * [x] Quantization 18 | * [x] Histogram Stretching 19 | * [x] Histogram Matching 20 | - Neighborhood Operations 21 | * [x] Error Diffusion 22 | * [x] Blur 23 | * [x] Sharpen 24 | * [x] Median Filter 25 | * [x] Convolution 26 | * [x] Correlation 27 | 28 | ## Compile & Run Application 29 | [Qt](https://www.qt.io/) must be installed. 30 | ``` 31 | cd src/ 32 | qmake qip.pro 33 | make 34 | ``` 35 | generates an executable file called 'qip', then run qip. 36 | 37 | ## Examples 38 | - **Contrast Enhancement** 39 | 40 | ![contrast input](/screenshots/contrast_in.png) 41 | ![contrast output](/screenshots/contrast_out.png) 42 | 43 | - **Blur** 44 | 45 | ![blur input](/screenshots/blur_in.png) 46 | ![blur output](/screenshots/blur_out.png) 47 | 48 | - **Median Filter** 49 | 50 | ![median input](/screenshots/median_in.png) 51 | ![median output](/screenshots/median_out.png) 52 | 53 | - **Correlation** 54 | 55 | ![correlation input](/screenshots/correlation_in.png) 56 | ![correlation output](/screenshots/correlation_out.png) 57 | -------------------------------------------------------------------------------- /images/butler.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/butler.pgm -------------------------------------------------------------------------------- /images/empire.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/empire.pgm -------------------------------------------------------------------------------- /images/eye50.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/eye50.pgm -------------------------------------------------------------------------------- /images/lowContrast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/lowContrast.jpg -------------------------------------------------------------------------------- /images/mad256.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mad256.pgm -------------------------------------------------------------------------------- /images/maddot.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/maddot.pgm -------------------------------------------------------------------------------- /images/mandrill.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mandrill.jpg -------------------------------------------------------------------------------- /images/mandrill256.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mandrill256.pgm -------------------------------------------------------------------------------- /images/mandrill_crop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mandrill_crop.png -------------------------------------------------------------------------------- /images/mandrill_eye.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mandrill_eye.jpg -------------------------------------------------------------------------------- /images/mandrill_nose.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mandrill_nose.jpg -------------------------------------------------------------------------------- /images/mandrill_right_face.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/mandrill_right_face.jpg -------------------------------------------------------------------------------- /images/met.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/met.pgm -------------------------------------------------------------------------------- /images/ramp.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/ramp.pgm -------------------------------------------------------------------------------- /images/star.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/star.pgm -------------------------------------------------------------------------------- /images/text.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/text.pgm -------------------------------------------------------------------------------- /images/text40.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/images/text40.pgm -------------------------------------------------------------------------------- /screenshots/blur_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/blur_in.png -------------------------------------------------------------------------------- /screenshots/blur_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/blur_out.png -------------------------------------------------------------------------------- /screenshots/contrast_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/contrast_in.png -------------------------------------------------------------------------------- /screenshots/contrast_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/contrast_out.png -------------------------------------------------------------------------------- /screenshots/correlation_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/correlation_in.png -------------------------------------------------------------------------------- /screenshots/correlation_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/correlation_out.png -------------------------------------------------------------------------------- /screenshots/interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/interface.png -------------------------------------------------------------------------------- /screenshots/median_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/median_in.png -------------------------------------------------------------------------------- /screenshots/median_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/screenshots/median_out.png -------------------------------------------------------------------------------- /src/Blur.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Blur.h - Blur widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef BLUR_H 11 | #define BLUR_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Blur : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Blur (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void blur (ImagePtr, int, int, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeFilterW (int); 29 | void changeFilterH (int); 30 | void setLock (int); 31 | void setMyBlur (int); 32 | 33 | private: 34 | // widgets 35 | QSlider* m_slider [2]; // Blur sliders 36 | QSpinBox* m_spinBox[2]; // Blur spin boxes 37 | QCheckBox* m_checkBox; // Blur check box 38 | QCheckBox* m_checkBox_myBlur; // myBlur check box 39 | QGroupBox* m_ctrlGrp; // groupbox for panel 40 | int m_width; // input image width 41 | int m_height; // input image height 42 | }; 43 | 44 | #endif // BLUR_H 45 | -------------------------------------------------------------------------------- /src/Clip.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Clip.cpp - Clip widget. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Clip.h" 12 | #include "ops_point/HW_clip.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | 16 | // uniform ID 17 | enum { THR1, THR2, SAMPLER }; 18 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | // Clip::Clip: 20 | // 21 | // Constructor. 22 | // 23 | Clip::Clip(QWidget *parent) : ImageFilter(parent) 24 | {} 25 | 26 | 27 | 28 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | // Clip::controlPanel: 30 | // 31 | // Create group box for control panel. 32 | // 33 | QGroupBox* 34 | Clip::controlPanel() 35 | { 36 | // init group box 37 | m_ctrlGrp = new QGroupBox("Clip"); 38 | 39 | // layout for assembling filter widget 40 | QGridLayout *layout = new QGridLayout; 41 | 42 | // alloc array of labels 43 | QLabel *label[2]; 44 | 45 | // create sliders and spinboxes 46 | for(int i=0; i<2; i++) { 47 | // create label[i] 48 | label[i] = new QLabel(m_ctrlGrp); 49 | if(!i) label[i]->setText("Thr1"); 50 | else label[i]->setText("Thr2"); 51 | 52 | // create slider and spinbox 53 | m_slider [i] = new QSlider(Qt::Horizontal, m_ctrlGrp); 54 | m_spinBox[i] = new QSpinBox(m_ctrlGrp); 55 | 56 | // init slider range and value 57 | m_slider [i]->setRange(0, MaxGray); 58 | m_slider [i]->setValue(i* MaxGray); 59 | 60 | // init spinbox range and value 61 | m_spinBox[i]->setRange(0, MaxGray); 62 | m_spinBox[i]->setValue(i* MaxGray); 63 | 64 | // assemble dialog 65 | layout->addWidget(label [i], i, 0); 66 | layout->addWidget(m_slider [i], i, 1); 67 | layout->addWidget(m_spinBox[i], i, 2); 68 | } 69 | 70 | // init signal/slot connections for Clip 71 | connect(m_slider [0], SIGNAL(valueChanged(int)), this, SLOT(changeThr1(int))); 72 | connect(m_spinBox[0], SIGNAL(valueChanged(int)), this, SLOT(changeThr1(int))); 73 | connect(m_slider [1], SIGNAL(valueChanged(int)), this, SLOT(changeThr2(int))); 74 | connect(m_spinBox[1], SIGNAL(valueChanged(int)), this, SLOT(changeThr2(int))); 75 | 76 | // assign layout to group box 77 | m_ctrlGrp->setLayout(layout); 78 | 79 | return(m_ctrlGrp); 80 | } 81 | 82 | 83 | 84 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 85 | // Clip::applyFilter: 86 | // 87 | // Run filter on the image, transforming I1 to I2. 88 | // Overrides ImageFilter::applyFilter(). 89 | // Return 1 for success, 0 for failure. 90 | // 91 | bool 92 | Clip::applyFilter(ImagePtr I1, bool gpuFlag, ImagePtr I2) 93 | { 94 | // error checking 95 | if(I1.isNull()) return 0; 96 | 97 | // collect parameters 98 | int thr1 = m_slider[0]->value(); 99 | int thr2 = m_slider[1]->value(); 100 | 101 | // apply filter 102 | if(!(gpuFlag && m_shaderFlag)) 103 | // apply CPU based filter 104 | clip(I1, thr1, thr2, I2); 105 | else 106 | g_mainWindowP->glw()->applyFilterGPU(m_nPasses); 107 | 108 | return 1; 109 | } 110 | 111 | 112 | 113 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 114 | // Clip::clip: 115 | // 116 | // Clip intensities of image I1. Output is in I2. 117 | // If inputt2: output = t2; 120 | // 121 | void 122 | Clip::clip(ImagePtr I1, int t1, int t2, ImagePtr I2) 123 | { 124 | HW_clip(I1, t1, t2, I2); 125 | } 126 | 127 | 128 | 129 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 130 | // Clip::changeThr1: 131 | // 132 | // Slot to process change in thr1 caused by moving the slider 133 | // 134 | void 135 | Clip::changeThr1(int val) 136 | { 137 | int thr2 = m_slider[1]->value(); 138 | if(val > thr2) val = thr2; 139 | 140 | m_slider [0]->blockSignals(true); 141 | m_slider [0]->setValue (val ); 142 | m_slider [0]->blockSignals(false); 143 | m_spinBox[0]->blockSignals(true); 144 | m_spinBox[0]->setValue (val ); 145 | m_spinBox[0]->blockSignals(false); 146 | 147 | // apply filter and display output 148 | g_mainWindowP->preview(); 149 | } 150 | 151 | 152 | 153 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 154 | // Clip::changeThr2: 155 | // 156 | // Slot to process change in thr2 caused by moving the slider 157 | // 158 | void 159 | Clip::changeThr2(int val) 160 | { 161 | int thr1 = m_slider[0]->value(); 162 | if(val < thr1) val = thr1; 163 | 164 | m_slider [1]->blockSignals(true); 165 | m_slider [1]->setValue (val ); 166 | m_slider [1]->blockSignals(false); 167 | m_spinBox[1]->blockSignals(true); 168 | m_spinBox[1]->setValue (val ); 169 | m_spinBox[1]->blockSignals(false); 170 | 171 | // apply filter and display output 172 | g_mainWindowP->preview(); 173 | } 174 | 175 | 176 | 177 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 178 | // Clip::reset: 179 | // 180 | // Reset parameters. 181 | // 182 | void 183 | Clip::reset() 184 | { 185 | for(int i=0; i<2; i++) { 186 | m_slider [i]->blockSignals(true); 187 | m_slider [i]->setValue(i*MaxGray); 188 | m_slider [i]->blockSignals(false); 189 | 190 | m_spinBox[i]->blockSignals(true); 191 | m_spinBox[i]->setValue(i*MaxGray); 192 | m_spinBox[i]->blockSignals(false); 193 | } 194 | 195 | // apply filter and display output 196 | g_mainWindowP->preview(); 197 | } 198 | 199 | 200 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 201 | // Clip::initShader: 202 | // 203 | // init shader program and parameters. 204 | // 205 | void 206 | Clip::initShader() 207 | { 208 | m_nPasses = 1; 209 | // initialize GL function resolution for current context 210 | initializeGLFunctions(); 211 | 212 | UniformMap uniforms; 213 | 214 | // init uniform hash table based on uniform variable names and location IDs 215 | uniforms["u_Thr1" ] = THR1; 216 | uniforms["u_Thr2" ] = THR2; 217 | uniforms["u_Sampler"] = SAMPLER; 218 | 219 | QString v_name = ":/vshader_passthrough"; 220 | QString f_name = ":/ops_point/fshader_clip"; 221 | 222 | #ifdef __APPLE__ 223 | v_name += "_Mac"; 224 | f_name += "_Mac"; 225 | #endif 226 | 227 | // compile shader, bind attribute vars, link shader, and initialize uniform var table 228 | g_mainWindowP->glw()->initShader(m_program[PASS1], 229 | v_name + ".glsl", 230 | f_name + ".glsl", 231 | uniforms, 232 | m_uniform[PASS1]); 233 | m_shaderFlag = true; 234 | } 235 | 236 | 237 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 238 | // Clip::gpuProgram: 239 | // 240 | // Active gpu program 241 | // 242 | void 243 | Clip::gpuProgram(int pass) 244 | { 245 | glUseProgram(m_program[pass].programId()); 246 | glUniform1f (m_uniform[pass][THR1], (GLfloat) m_slider[0]->value()/MXGRAY); 247 | glUniform1f (m_uniform[pass][THR2], (GLfloat) m_slider[1]->value()/MXGRAY); 248 | glUniform1i (m_uniform[pass][SAMPLER], 0); 249 | } 250 | -------------------------------------------------------------------------------- /src/Clip.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Clip.h - Clip widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef CLIP_H 11 | #define CLIP_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Clip : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Clip (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void clip (ImagePtr, int, int, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeThr1 (int); 29 | void changeThr2 (int); 30 | 31 | private: 32 | // widgets 33 | QSlider* m_slider [2]; // clip sliders 34 | QSpinBox* m_spinBox[2]; // clip spin boxes 35 | QGroupBox* m_ctrlGrp; // groupbox for panel 36 | }; 37 | 38 | #endif // CLIP_H 39 | -------------------------------------------------------------------------------- /src/Contrast.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Contrast.h - Contrast widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef CONTRAST_H 11 | #define CONTRAST_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Contrast : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Contrast (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void contrast (ImagePtr, double, double, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeBrightnessI(int); 29 | void changeContrastI (int); 30 | 31 | void changeBrightnessD(double); 32 | void changeContrastD (double); 33 | 34 | private: 35 | // widgets 36 | QSlider* m_slider [2]; // brightness/contrast sliders 37 | QDoubleSpinBox* m_spinBox[2]; // brightness/contrast spin boxes 38 | QGroupBox* m_ctrlGrp; // groupbox for panel 39 | }; 40 | 41 | #endif // CONTRAST_H 42 | -------------------------------------------------------------------------------- /src/Convolve.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Convolve.cpp - Convolve widget. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Convolve.h" 12 | #include "ops_neighborhood/HW_convolve.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | enum { WSIZE, HSIZE, STEPX, STEPY, KERNEL, SAMPLER }; 16 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | // Convolve::Convolve: 18 | // 19 | // Constructor. 20 | // 21 | Convolve::Convolve(QWidget *parent) : ImageFilter(parent) 22 | { 23 | m_kernel = NULL; 24 | } 25 | 26 | 27 | 28 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | // Convolve::controlPanel: 30 | // 31 | // Create group box for control panel. 32 | // 33 | QGroupBox* 34 | Convolve::controlPanel() 35 | { 36 | // init group box 37 | m_ctrlGrp = new QGroupBox("Convolve"); 38 | 39 | // layout for assembling filter widget 40 | QVBoxLayout *vbox = new QVBoxLayout; 41 | 42 | // create file pushbutton 43 | m_button = new QPushButton("File"); 44 | 45 | // create text edit widget 46 | m_values = new QTextEdit(); 47 | m_values->setReadOnly(1); 48 | 49 | // assemble dialog 50 | vbox->addWidget(m_button); 51 | vbox->addWidget(m_values); 52 | m_ctrlGrp->setLayout(vbox); 53 | 54 | // init signal/slot connections 55 | connect(m_button, SIGNAL(clicked()), this, SLOT(load())); 56 | 57 | return(m_ctrlGrp); 58 | } 59 | 60 | 61 | 62 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 | // Convolve::applyFilter: 64 | // 65 | // Run filter on the image, transforming I1 to I2. 66 | // Overrides ImageFilter::applyFilter(). 67 | // Return 1 for success, 0 for failure. 68 | // 69 | bool 70 | Convolve::applyFilter(ImagePtr I1, bool gpuFlag, ImagePtr I2) 71 | { 72 | // error checking 73 | if(I1.isNull()) return 0; 74 | if(m_kernel.isNull()) return 0; 75 | m_width = I1->width(); 76 | m_height = I1->height(); 77 | // convolve image 78 | if(!(gpuFlag && m_shaderFlag)) 79 | convolve(I1, m_kernel, I2); 80 | else g_mainWindowP->glw()->applyFilterGPU(m_nPasses); 81 | 82 | return 1; 83 | } 84 | 85 | 86 | 87 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 88 | // Convolve::convolve: 89 | // 90 | // Convolve image I1 with convolution filter in kernel. 91 | // Output is in I2. 92 | // 93 | void 94 | Convolve::convolve(ImagePtr I1, ImagePtr kernel, ImagePtr I2) 95 | { 96 | HW_convolve(I1, kernel, I2); 97 | } 98 | 99 | 100 | 101 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 102 | // Convolve::load: 103 | // 104 | // Slot to load filter kernel from file. 105 | // 106 | int 107 | Convolve::load() 108 | { 109 | QFileDialog dialog(this); 110 | 111 | // open the last known working directory 112 | if(!m_currentDir.isEmpty()) 113 | dialog.setDirectory(m_currentDir); 114 | 115 | // display existing files and directories 116 | dialog.setFileMode(QFileDialog::ExistingFile); 117 | 118 | // invoke native file browser to select file 119 | m_file = dialog.getOpenFileName(this, 120 | "Open File", m_currentDir, 121 | "Images (*.AF);;All files (*)"); 122 | 123 | // verify that file selection was made 124 | if(m_file.isNull()) return 0; 125 | 126 | // save current directory 127 | QFileInfo f(m_file); 128 | m_currentDir = f.absolutePath(); 129 | 130 | // read kernel 131 | m_kernel = IP_readImage(qPrintable(m_file)); 132 | 133 | // init vars 134 | int w = m_kernel->width (); 135 | int h = m_kernel->height(); 136 | 137 | // update button with filename (without path) 138 | m_button->setText(f.fileName()); 139 | m_button->update(); 140 | 141 | // declarations 142 | int type; 143 | ChannelPtr p; 144 | QString s; 145 | 146 | // get pointer to kernel values 147 | IP_getChannel(m_kernel, 0, p, type); 148 | 149 | // display kernel values 150 | m_values->clear(); // clear text edit field (kernel values) 151 | for(int y=0; yappend(s); // append string to text edit widget 156 | } 157 | 158 | // apply filter to source image and display result 159 | g_mainWindowP->preview(); 160 | 161 | return 1; 162 | } 163 | 164 | 165 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 166 | // Convolve::initShader: 167 | // 168 | // init shader program and parameters. 169 | // 170 | void 171 | Convolve::initShader() 172 | { 173 | m_nPasses = 1; 174 | 175 | // initialize GL function resolution for current context 176 | initializeGLFunctions(); 177 | 178 | UniformMap uniforms; 179 | 180 | // init uniform hash table based on uniform variable names and location IDs 181 | uniforms["u_SizeW" ] = WSIZE; 182 | uniforms["u_SizeH" ] = HSIZE; 183 | uniforms["u_StepX" ] = STEPX; 184 | uniforms["u_StepY" ] = STEPY; 185 | uniforms["u_Kernel" ] = KERNEL; 186 | uniforms["u_Sampler"] = SAMPLER; 187 | 188 | QString v_name = ":/vshader_passthrough"; 189 | QString f_name = ":/ops_neighborhood/fshader_convolve"; 190 | 191 | #ifdef __APPLE__ 192 | v_name += "_Mac"; 193 | f_name += "_Mac"; 194 | #endif 195 | 196 | // compile shader, bind attribute vars, link shader, and initialize uniform var table 197 | g_mainWindowP->glw()->initShader(m_program[PASS1], 198 | v_name + ".glsl", 199 | f_name + ".glsl", 200 | uniforms, 201 | m_uniform[PASS1]); 202 | 203 | m_shaderFlag = true; 204 | } 205 | 206 | 207 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 208 | // Convolve::gpuProgram: 209 | // 210 | // Active gpu program 211 | // 212 | void 213 | Convolve::gpuProgram(int pass) 214 | { 215 | int w = m_kernel->width(); 216 | int h = m_kernel->height(); 217 | int kernelSize = w*h; 218 | 219 | int type; 220 | float* kernel = new float[kernelSize]; 221 | ChannelPtr kernelPtr; 222 | IP_getChannel(m_kernel, 0, kernelPtr, type); 223 | 224 | for(int i = 0; i < kernelSize; i++) { 225 | kernel[i] = *kernelPtr++; 226 | } 227 | 228 | glUseProgram(m_program[pass].programId()); 229 | glUniform1i (m_uniform[pass][WSIZE], w); 230 | glUniform1i (m_uniform[pass][HSIZE], h); 231 | glUniform1f (m_uniform[pass][STEPX], (GLfloat) 1.0f / m_width); 232 | glUniform1f (m_uniform[pass][STEPY], (GLfloat) 1.0f / m_height); 233 | glUniform1fv(m_uniform[pass][KERNEL], kernelSize, kernel); 234 | glUniform1i (m_uniform[pass][SAMPLER], 0); 235 | } 236 | -------------------------------------------------------------------------------- /src/Convolve.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Convolve.h - Convolve widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef CONVOLVE_H 11 | #define CONVOLVE_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Convolve : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Convolve (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void convolve (ImagePtr, ImagePtr, ImagePtr); 23 | void initShader(); 24 | void gpuProgram(int pass); // use GPU program to apply filter 25 | 26 | protected slots: 27 | int load (); 28 | 29 | private: 30 | // widgets 31 | QPushButton* m_button; // Convolve pushbutton 32 | QTextEdit* m_values; // text field for kernel values 33 | QGroupBox* m_ctrlGrp; // groupbox for panel 34 | 35 | // variables 36 | QString m_file; 37 | QString m_currentDir; 38 | ImagePtr m_kernel; 39 | int m_width; // input image width 40 | int m_height; // input image height 41 | }; 42 | 43 | #endif // CONVOLVE_H 44 | -------------------------------------------------------------------------------- /src/Correlation.h: -------------------------------------------------------------------------------- 1 | #ifndef CORRELATION_H 2 | #define CORRELATION_H 3 | 4 | #include "ImageFilter.h" 5 | 6 | class Correlation : public ImageFilter { 7 | Q_OBJECT 8 | 9 | public: 10 | Correlation(QWidget *parent = 0); // constructor 11 | QGroupBox* controlPanel(); // create control panel 12 | bool applyFilter(ImagePtr, bool, ImagePtr); // apply filter to input 13 | void correlate(ImagePtr, ImagePtr, ImagePtr); 14 | void initShader(); 15 | void gpuProgram(int pass); // use GPU program to apply filter 16 | 17 | protected slots: 18 | int load (); 19 | void match (); 20 | 21 | private: 22 | // widgets 23 | QPushButton* m_button; // Correlation pushbutton 24 | QLabel* m_label; 25 | QLabel* m_label_template; 26 | QGroupBox* m_ctrlGrp; // groupbox for panel 27 | 28 | // variables 29 | QString m_file; 30 | QString m_currentDir; 31 | ImagePtr m_template; 32 | int m_width; // input image width 33 | int m_height; // input image height 34 | }; 35 | 36 | #endif // CORRELATION_H 37 | -------------------------------------------------------------------------------- /src/Dummy.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Dummy.cpp - Dummy control panel 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Dummy.h" 12 | 13 | extern MainWindow *g_mainWindowP; 14 | 15 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | // Dummy::Dummy: 17 | // 18 | // Constructor. 19 | // 20 | Dummy::Dummy(QWidget *parent) : ImageFilter(parent) 21 | {} 22 | 23 | 24 | 25 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | // Dummy::createPanel: 27 | // 28 | // Create group box for control panel. 29 | // 30 | QGroupBox* 31 | Dummy::controlPanel() 32 | { 33 | // init group box 34 | m_ctrlGrp = new QGroupBox(""); 35 | return(m_ctrlGrp); 36 | } 37 | 38 | 39 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 40 | // Dummy::initShader: 41 | // 42 | // init shader program and parameters. 43 | // 44 | void 45 | Dummy::initShader() {} 46 | 47 | 48 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 | // Dummy::gpuProgram: 50 | // 51 | // Active gpu program 52 | // 53 | void 54 | Dummy::gpuProgram(int) {} 55 | -------------------------------------------------------------------------------- /src/Dummy.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Dummy.h - Header for dummy control panel 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef DUMMY_H 11 | #define DUMMY_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | 16 | ////////////////////////////////////////////////////////////////////////// 17 | /// 18 | /// \class Dummy 19 | /// \brief Blank Panel widget . 20 | /// 21 | ////////////////////////////////////////////////////////////////////////// 22 | 23 | class Dummy : public ImageFilter { 24 | Q_OBJECT 25 | 26 | public: 27 | Dummy (QWidget *parent = 0); // constructor 28 | QGroupBox* controlPanel(); // create control panel 29 | void initShader(); 30 | void gpuProgram(int pass); // use GPU program to apply filter 31 | 32 | private: 33 | // widgets and groupbox 34 | QGroupBox* m_ctrlGrp; // groupbox for panel 35 | }; 36 | 37 | 38 | #endif // DUMMY_H 39 | -------------------------------------------------------------------------------- /src/ErrDiffusion.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // ErrDuffusion.h - Error Diffusion widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef ERRDIFFUSION_H 11 | #define ERRDIFFUSION_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | 16 | class ErrDiffusion : public ImageFilter { 17 | Q_OBJECT 18 | 19 | public: 20 | ErrDiffusion (QWidget *parent = 0); // constructor 21 | QGroupBox* controlPanel (); // create control panel 22 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 23 | void reset (); // reset parameters 24 | void errDiffusion (ImagePtr, int, bool, double, ImagePtr); 25 | void initShader(); 26 | void gpuProgram(int pass); // use GPU program to apply filter 27 | 28 | protected slots: 29 | void changeMethod (int); 30 | void changeSerpentine(int); 31 | void changeGammaI (int); 32 | void changeGammaD (double); 33 | 34 | private: 35 | // widgets 36 | QComboBox* m_comboBox; // ErrDuffusion comboBox 37 | QSlider* m_slider; // ErrDuffusion slider 38 | QDoubleSpinBox* m_spinBox; // ErrDuffusion spin box 39 | QCheckBox* m_checkBox; // ErrDuffusion checkbox 40 | QGroupBox* m_ctrlGrp; // Groupbox for panel 41 | }; 42 | 43 | #endif // ERRDIFFUSION_H 44 | -------------------------------------------------------------------------------- /src/GLWidget.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // 3 | // Copyright (C) 2015 by George Wolberg 4 | // 5 | // GLWidget.h - Header file for openGL display. 6 | // 7 | // Written by: George Wolberg, 2015 8 | // ====================================================================== 9 | 10 | #ifndef GLWIDGET_H 11 | #define GLWIDGET_H 12 | 13 | #define MXPROGRAMS 32 14 | #define MXUNIFORMS 32 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | typedef QVector2D vec2; 23 | typedef QVector3D vec3; 24 | 25 | enum { 26 | ATTRIB_VERTEX, 27 | ATTRIB_TEXCOORD 28 | }; 29 | 30 | typedef std::map UniformMap; 31 | 32 | // ---------------------------------------------------------------------- 33 | // standard include files 34 | // 35 | class GLWidget : public QGLWidget, protected QGLFunctions { 36 | 37 | public: 38 | GLWidget(QWidget *parent = 0); 39 | void setViewport(int w, int h, int ww, int hh); 40 | void setInTexture(QImage &); 41 | void setOutTexture(QImage &); 42 | void allocateTextureFBO(int w, int h); 43 | void setTemplateTexture(QImage &); 44 | void setCorrOutTexture(QImage &image); 45 | void initShader(QGLShaderProgram &, QString, QString, UniformMap &, int *); 46 | void applyFilterGPU(int); 47 | void setDstImage(int); 48 | 49 | protected: 50 | 51 | void initializeGL(); // init GL state 52 | void resizeGL(int, int); // resize GL widget 53 | void paintGL(); // render GL scene 54 | void initVertices(); 55 | void initBuffers(); 56 | void initShaders(); 57 | 58 | private: 59 | int m_winW; // window width 60 | int m_winH; // window height 61 | int m_imageW; // input image width 62 | int m_imageH; // input image height 63 | std::vector m_points; // vector of 2D points (XY) 64 | int m_numPoints; 65 | std::vector m_texCoord; // vector of 2D texture coordinates (s,t) 66 | GLuint m_vertexBuffer; // handle to vertex buffer 67 | GLuint m_texCoordBuffer; // handle to texture coordinate buffer 68 | GLuint m_inTexture; // texture unit for dispalying input 69 | GLuint m_outTexture; // texture unit for dispalying output 70 | GLuint m_TemplateTexture; 71 | GLuint m_fbo[2]; // handle to frame buffer object 72 | GLuint m_texture_fbo[2]; // texture unit for render to texture 73 | QGLShaderProgram m_program; // GLSL programs 74 | GLint m_uniform[MXUNIFORMS]; // uniform vars for each program 75 | 76 | bool m_imageFlag; // true if an image is uploaded to GPU 77 | QMatrix4x4 m_projection; // 4x4 projection matrix 78 | 79 | }; 80 | 81 | 82 | 83 | #endif // GLWIDGET_H 84 | -------------------------------------------------------------------------------- /src/Gamma.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Gamma.cpp - Gamma correction widget. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Gamma.h" 12 | #include "ops_point/HW_gamma.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | // uniform ID 16 | enum { GAMMA_VALUE, SAMPLER }; 17 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | // Gamma::Gamma: 19 | // 20 | // Constructor. 21 | // 22 | Gamma::Gamma(QWidget *parent) : ImageFilter(parent) 23 | {} 24 | 25 | 26 | 27 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | // Gamma::controlPanel: 29 | // 30 | // Create group box for control panel. 31 | // 32 | QGroupBox* 33 | Gamma::controlPanel() 34 | { 35 | // init group box 36 | m_ctrlGrp = new QGroupBox("Gamma Correction"); 37 | 38 | // create label 39 | QLabel *label = new QLabel("Gamma"); 40 | 41 | // create slider 42 | m_slider = new QSlider(Qt::Horizontal, m_ctrlGrp); 43 | m_slider->setRange(1, 100); 44 | m_slider->setValue(10); 45 | m_slider->setTickPosition(QSlider::TicksBelow); 46 | m_slider->setTickInterval(25); 47 | 48 | // create spinbox 49 | m_spinBox = new QDoubleSpinBox(m_ctrlGrp); 50 | m_spinBox->setRange(0.1, 10.); 51 | m_spinBox->setValue (1.0); 52 | m_spinBox->setSingleStep(0.1); 53 | m_spinBox->setDecimals (2); 54 | 55 | // init signal/slot connections for Gamma 56 | connect(m_slider, SIGNAL(valueChanged( int )), this, SLOT(changeGammaI( int ))); 57 | connect(m_spinBox, SIGNAL(valueChanged(double)), this, SLOT(changeGammaD(double))); 58 | 59 | // assemble dialog 60 | QGridLayout *layout = new QGridLayout; 61 | layout->addWidget(label , 0, 0); 62 | layout->addWidget(m_slider , 0, 1); 63 | layout->addWidget(m_spinBox, 0, 2); 64 | 65 | // assign layout to group box 66 | m_ctrlGrp->setLayout(layout); 67 | 68 | return(m_ctrlGrp); 69 | } 70 | 71 | 72 | 73 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 74 | // Gamma::applyFilter: 75 | // 76 | // Run filter on the image, transforming I1 to I2. 77 | // Overrides ImageFilter::applyFilter(). 78 | // Return 1 for success, 0 for failure. 79 | // 80 | bool 81 | Gamma::applyFilter(ImagePtr I1, bool gpuFlag, ImagePtr I2) 82 | { 83 | // error checking 84 | if(I1.isNull()) return 0; 85 | 86 | // get gamma value 87 | double gamma = m_slider->value() * 0.1; 88 | 89 | // error checking 90 | if(gamma < 0.1 || gamma > 10.0) return 0; 91 | 92 | // apply gamma correction 93 | if(!(gpuFlag && m_shaderFlag)) 94 | // apply CPU based filter 95 | gammaCorrect(I1, gamma, I2); 96 | else 97 | g_mainWindowP->glw()->applyFilterGPU(m_nPasses); 98 | 99 | return 1; 100 | } 101 | 102 | 103 | 104 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | // Gamma::gammaCorrect: 106 | // 107 | // Gamma correct image I1. Output is in I2. 108 | // 109 | void 110 | Gamma::gammaCorrect(ImagePtr I1, double gamma, ImagePtr I2) 111 | { 112 | HW_gammaCorrect(I1, gamma, I2); 113 | } 114 | 115 | 116 | 117 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 118 | // Gamma::changeGammaI: 119 | // 120 | // Slot to process change in gamma value caused by moving the slider (int) 121 | // 122 | void 123 | Gamma::changeGammaI(int gamma) 124 | { 125 | // set spinbox 126 | m_spinBox->setValue(gamma*0.1); 127 | 128 | // apply filter and display output 129 | g_mainWindowP->preview(); 130 | } 131 | 132 | 133 | 134 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 135 | // Gamma::changeGammaD: 136 | // 137 | // Slot to process change in gamma value caused by moving the spinbox (double) 138 | // 139 | void 140 | Gamma::changeGammaD(double gamma) 141 | { 142 | // round gamma to the nearest int 143 | double g = gamma * 10; 144 | int val = (g >= 0) ? (int)(g+.5) : -(int)(.5-g); 145 | 146 | // set slider 147 | m_slider->setValue(val); 148 | 149 | // apply filter and display output 150 | g_mainWindowP->preview(); 151 | } 152 | 153 | 154 | 155 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 156 | // Gamma::reset: 157 | // 158 | // Reset parameters. 159 | // 160 | void 161 | Gamma::reset() 162 | { 163 | m_slider ->blockSignals(true); 164 | m_slider ->setValue (10); 165 | m_slider ->blockSignals(false); 166 | m_spinBox->blockSignals(true); 167 | m_spinBox->setValue (10); 168 | m_spinBox->blockSignals(false); 169 | 170 | // apply filter and display output 171 | g_mainWindowP->preview(); 172 | } 173 | 174 | 175 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 176 | // Gamma::initShader: 177 | // 178 | // init shader program and parameters. 179 | // 180 | void 181 | Gamma::initShader() 182 | { 183 | m_nPasses = 1; 184 | // initialize GL function resolution for current context 185 | initializeGLFunctions(); 186 | 187 | UniformMap uniforms; 188 | 189 | // init uniform hash table based on uniform variable names and location IDs 190 | uniforms["u_gamma" ] = GAMMA_VALUE; 191 | uniforms["u_Sampler"] = SAMPLER; 192 | 193 | QString v_name = ":/vshader_passthrough"; 194 | QString f_name = ":/ops_point/fshader_gamma"; 195 | 196 | #ifdef __APPLE__ 197 | v_name += "_Mac"; 198 | f_name += "_Mac"; 199 | #endif 200 | 201 | // compile shader, bind attribute vars, link shader, and initialize uniform var table 202 | g_mainWindowP->glw()->initShader(m_program[PASS1], 203 | v_name + ".glsl", 204 | f_name + ".glsl", 205 | uniforms, 206 | m_uniform[PASS1]); 207 | m_shaderFlag = true; 208 | } 209 | 210 | 211 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 212 | // Gamma::gpuProgram: 213 | // 214 | // Active gpu program 215 | // 216 | void 217 | Gamma::gpuProgram(int pass) 218 | { 219 | glUseProgram(m_program[pass].programId()); 220 | glUniform1f (m_uniform[pass][GAMMA_VALUE], (GLfloat) 1.0f/(m_slider->value()*0.1f)); 221 | glUniform1i (m_uniform[pass][SAMPLER], 0); 222 | } -------------------------------------------------------------------------------- /src/Gamma.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Gamma.h - Gamma widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef GAMMA_H 11 | #define GAMMA_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Gamma : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Gamma (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void gammaCorrect (ImagePtr, double, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeGammaI( int ); 29 | void changeGammaD(double); 30 | 31 | private: 32 | // widgets 33 | QSlider* m_slider; // gamma slider 34 | QDoubleSpinBox* m_spinBox; // gamma spin box 35 | QGroupBox* m_ctrlGrp; // groupbox for panel 36 | }; 37 | 38 | #endif // GAMMA_H 39 | -------------------------------------------------------------------------------- /src/HistoMatch.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // HistoMatch.cpp - Histogram Match widget. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "HistoMatch.h" 12 | #include "ops_point/HW_histoMatch.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | bool initLut(ImagePtr, int); 16 | 17 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | // HistoMatch::HistoMatch: 19 | // 20 | // Constructor. 21 | // 22 | HistoMatch::HistoMatch(QWidget *parent) : ImageFilter(parent) 23 | {} 24 | 25 | 26 | 27 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | // HistoMatch::controlPanel: 29 | // 30 | // Create group box for control panel. 31 | // 32 | QGroupBox* 33 | HistoMatch::controlPanel() 34 | { 35 | // init group box 36 | m_ctrlGrp = new QGroupBox("HistoMatch"); 37 | 38 | // create label 39 | QLabel *label = new QLabel("Exponent"); 40 | 41 | // create slider 42 | m_slider = new QSlider(Qt::Horizontal, m_ctrlGrp); 43 | m_slider->setRange(-10, 10); 44 | m_slider->setValue(0); 45 | m_slider->setTickPosition(QSlider::TicksBelow); 46 | m_slider->setTickInterval(2); 47 | 48 | // create spinbox 49 | m_spinBox = new QSpinBox(m_ctrlGrp); 50 | m_spinBox->setRange(-10, 10); 51 | m_spinBox->setValue(0); 52 | 53 | // create lut for storing target histogram 54 | m_lut = IP_allocImage(MXGRAY, 1, INTCH_TYPE); 55 | 56 | // init signal/slot connections for slider and spinbox 57 | connect(m_slider , SIGNAL(valueChanged(int)), this, SLOT(changeExp(int))); 58 | connect(m_spinBox, SIGNAL(valueChanged(int)), this, SLOT(changeExp(int))); 59 | 60 | // assemble dialog 61 | QGridLayout *layout = new QGridLayout; 62 | layout->addWidget(label , 0, 0); 63 | layout->addWidget(m_slider , 0, 1); 64 | layout->addWidget(m_spinBox, 0, 2); 65 | 66 | // assign layout to group box 67 | m_ctrlGrp->setLayout(layout); 68 | 69 | return(m_ctrlGrp); 70 | } 71 | 72 | 73 | 74 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 | // HistoMatch::applyFilter: 76 | // 77 | // Run filter on the image, transforming I1 to I2. 78 | // Overrides ImageFilter::applyFilter(). 79 | // Return 1 for success, 0 for failure. 80 | // 81 | bool 82 | HistoMatch::applyFilter(ImagePtr I1, bool /*gpuFlag*/, ImagePtr I2) 83 | { 84 | // error checking 85 | if(I1.isNull()) return 0; 86 | 87 | // get exponent 88 | int exp = m_slider->value(); 89 | 90 | // apply filter 91 | initLut(I1, m_lut, exp); // init lut with target histogram 92 | histoMatch(I1, m_lut, I2); // histogram matching based on target histogram 93 | 94 | return 1; 95 | } 96 | 97 | 98 | 99 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 100 | // HistoMatch::initLut: 101 | // 102 | // Apply histogram matching to I1. Output is in I2. 103 | // 104 | bool 105 | HistoMatch::initLut(ImagePtr I, ImagePtr Ilut, int exp) 106 | { 107 | // error checking 108 | if( I.isNull()) return 0; 109 | if(Ilut.isNull()) return 0; 110 | 111 | int w = I->width (); 112 | int h = I->height(); 113 | int total = w * h; 114 | int Havg = (float) total / MXGRAY; 115 | 116 | // get pointer lut data 117 | int type; 118 | ChannelPtr lut; 119 | IP_getChannel(Ilut, 0, lut, type); 120 | 121 | // load lut with i^exp 122 | if(exp == 0) { 123 | for(int i=0; i 0) { 126 | for(int i=0; iblockSignals(true); 161 | m_slider ->setValue (exp); 162 | m_slider ->blockSignals(false); 163 | m_spinBox->blockSignals(true); 164 | m_spinBox->setValue (exp); 165 | m_spinBox->blockSignals(false); 166 | 167 | // apply filter to source image and display result 168 | g_mainWindowP->preview(); 169 | } 170 | 171 | 172 | 173 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 174 | // HistoMatch::reset: 175 | // 176 | // Reset parameters. 177 | // 178 | void 179 | HistoMatch::reset() 180 | { 181 | m_slider ->blockSignals(true); 182 | m_slider ->setValue (0); 183 | m_slider ->blockSignals(false); 184 | m_spinBox->blockSignals(true); 185 | m_spinBox->setValue (0); 186 | m_spinBox->blockSignals(false); 187 | 188 | // apply filter to source image and display result 189 | g_mainWindowP->preview(); 190 | } 191 | 192 | 193 | 194 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 195 | // HistoMatch::initShader: 196 | // 197 | // init shader program and parameters. 198 | // 199 | void 200 | HistoMatch::initShader() { 201 | 202 | m_shaderFlag = false; 203 | } 204 | 205 | 206 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 207 | // HistoMatch::gpuProgram: 208 | // 209 | // Active gpu program 210 | // 211 | void 212 | HistoMatch::gpuProgram(int) { 213 | 214 | } 215 | -------------------------------------------------------------------------------- /src/HistoMatch.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // HistoMatch.h - Histogram Match widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef HISTOMATCH_H 11 | #define HISTOMATCH_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class HistoMatch : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | HistoMatch (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void histoMatch (ImagePtr, ImagePtr, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeExp (int); 29 | 30 | private: 31 | // widgets 32 | QSlider* m_slider ; // HistoMatch slider 33 | QSpinBox* m_spinBox; // HistoMatch spin box 34 | QGroupBox* m_ctrlGrp; // groupbox for panel 35 | 36 | // lookup table 37 | ImagePtr m_lut; // target histogram 38 | 39 | // function to init lookup table 40 | bool initLut (ImagePtr, ImagePtr, int); 41 | }; 42 | 43 | #endif // HISTOMATCH_H 44 | -------------------------------------------------------------------------------- /src/HistoStretch.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // HistoStretch.h - Histogram Stretch widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef HISTOSTRETCH_H 11 | #define HISTOSTRETCH_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class HistoStretch : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | HistoStretch (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void histoStretch (ImagePtr, int, int, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeThr1 (int); 29 | void changeThr2 (int); 30 | void setThrFlag1 (int); 31 | void setThrFlag2 (int); 32 | 33 | private: 34 | // widgets 35 | QSlider* m_slider [2]; // HistoStretch sliders 36 | QSpinBox* m_spinBox[2]; // HistoStretch spin boxes 37 | QCheckBox* m_thr1; // min histogram threshold control 38 | QCheckBox* m_thr2; // max histogram threshold control 39 | QGroupBox* m_ctrlGrp; // groupbox for panel 40 | 41 | // state variables 42 | int m_thrFlag1; // flag for finding min histogram value 43 | int m_thrFlag2; // flag for finding max histogram value 44 | }; 45 | 46 | #endif // HISTOSTRETCH_H 47 | -------------------------------------------------------------------------------- /src/IP/linux/header/Channel.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Channel.h - Channel class. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file Channel.h 11 | //! \brief Channel class. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef CHANNEL_H 15 | #define CHANNEL_H 16 | 17 | #include "IPdefs.h" 18 | 19 | namespace IP { 20 | 21 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | // Channel class declaration 23 | //! \brief Channel class. 24 | //! \details The Channel class handles image channel data of various 25 | //! types. 26 | // 27 | class Channel { 28 | public: 29 | // constructors 30 | Channel(); // default constructor 31 | Channel(const Channel &); // copy constructor 32 | Channel(int); // construct to specified # of bytes 33 | 34 | // destructor 35 | ~Channel(); 36 | 37 | // get methods 38 | const void *buf() const; // buffer pointer 39 | void *buf(); // buffer pointer 40 | 41 | // resize channel buffer 42 | void resize(int); // resize to specified # of bytes 43 | 44 | // free channel 45 | void free(); 46 | 47 | private: 48 | void *m_buf; // channel buffer pointer 49 | }; 50 | 51 | 52 | 53 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | // Channel::Channel: 55 | // 56 | // Default constructor. A null pointer is assigned to the channel. 57 | //! \brief Default constructor. 58 | //! \details Assign a null pointer to the channel. 59 | // 60 | inline 61 | Channel::Channel() 62 | : m_buf(0) 63 | {} 64 | 65 | 66 | 67 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | // Channel::Channel: 69 | // 70 | // Size constructor. Allocate specified number of bytes to channel. 71 | //! \brief Size constructor. 72 | //! \details Allocate specified number of bytes to channel. 73 | // 74 | inline 75 | Channel::Channel(int size) 76 | { 77 | m_buf = new uchar[size]; 78 | } 79 | 80 | 81 | 82 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 | // Channel::~Channel: 84 | // 85 | // Destructor function. Free channel memory and set channel pointer to null. 86 | //! \brief Destructor. 87 | //! \details Free channel memory and set channel pointer to null. 88 | // 89 | inline 90 | Channel::~Channel() 91 | { 92 | if (m_buf) delete [] (uchar *) m_buf; 93 | } 94 | 95 | 96 | 97 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 98 | // Channel::buf: 99 | // 100 | // Channel memory pointer. 101 | //! \brief Channel memory pointer. 102 | //! \details Return channel memory pointer. 103 | //! \return Pointer to data of type void (const version). 104 | // 105 | inline const void * 106 | Channel::buf() const 107 | { 108 | return m_buf; 109 | } 110 | 111 | 112 | 113 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 114 | // Channel::buf: 115 | // 116 | // Channel pointer. 117 | //! \brief Channel memory pointer. 118 | //! \details Return channel memory pointer. 119 | //! \return Pointer to data of type void. 120 | // 121 | inline void * 122 | Channel::buf() 123 | { 124 | return m_buf; 125 | } 126 | 127 | 128 | 129 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 130 | // Channel::resize: 131 | // 132 | // Resize channel buffer to have size bytes. 133 | //! \brief Resize channel buffer. 134 | //! \details Resize channel buffer to \a size bytes. Reset channel pointer. 135 | // 136 | inline void 137 | Channel::resize(int size) 138 | { 139 | m_buf = new uchar[size]; 140 | } 141 | 142 | 143 | 144 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 145 | // Channel::free: 146 | // 147 | // Free channel buffer. 148 | //! \brief Free channel buffer. 149 | //! \details Free channel memory and reset channel pointer to null. 150 | // 151 | inline void 152 | Channel::free() { 153 | if(m_buf) { 154 | delete [] (uchar*) m_buf; 155 | m_buf = 0; 156 | } 157 | } 158 | 159 | } // namespace IP 160 | 161 | #endif // CHANNEL_H 162 | -------------------------------------------------------------------------------- /src/IP/linux/header/ChannelPtr.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // ChannelPtr.h - Channel pointer class. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file ChannelPtr.h 11 | //! \brief ChannelPtr class. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef CHANNELPTR_H 15 | #define CHANNELPTR_H 16 | 17 | #include "Channel.h" 18 | 19 | namespace IP { 20 | 21 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | // ChannelPtr class declaration 23 | //! \brief ChannelPtr class. 24 | //! \details A smart pointer to the Channel class. 25 | // 26 | template 27 | class ChannelPtr { 28 | public: 29 | // constructors 30 | ChannelPtr(); // default constructor 31 | ChannelPtr(const ChannelPtr &); // copy constructor 32 | ChannelPtr(Channel *c); // construct from channel ptr 33 | 34 | // destructor 35 | ~ChannelPtr(); 36 | 37 | // get a pointer to the channel buffer 38 | const T *buf() const; 39 | T *buf(); 40 | 41 | // overloaded operators 42 | ChannelPtr &operator=(const ChannelPtr &); // assignment 43 | T &operator* () const; // value-at 44 | T &operator[](int) const; // index into buffer 45 | ChannelPtr &operator++(); // prefix increment 46 | ChannelPtr operator++(int); // postfix increment 47 | ChannelPtr &operator--(); // prefix decrement 48 | ChannelPtr operator--(int); // postfix decrement 49 | ChannelPtr &operator+=(int); // addition 50 | ChannelPtr &operator-=(int); // subtraction 51 | 52 | private: 53 | T *m_buf; // channel buffer ptr 54 | }; 55 | 56 | } // namespace IP 57 | 58 | #include "ChannelPtr.tpp" 59 | 60 | #endif // CHANNELPTR_H 61 | -------------------------------------------------------------------------------- /src/IP/linux/header/IP.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IP.h - Header for IP*.cpp files 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \mainpage Image Processing Package 11 | //! \author George Wolberg 12 | //! \date 2016 13 | //! \par References: 14 | //! This code is part of the 15 | //! IMPROC Image Processing Software Package\n 16 | //! Copyright © 2016 by George Wolberg 17 | 18 | //! \file IP.h 19 | //! \brief Image Processing Package main header file. 20 | //! \author George Wolberg and Gene Yu, 2016 21 | 22 | #ifndef IP_H 23 | #define IP_H 24 | 25 | #include "IPdefs.h" 26 | #include "Channel.h" 27 | #include "ChannelPtr.h" 28 | #include "Image.h" 29 | #include "ImagePtr.h" 30 | #include 31 | 32 | namespace IP { 33 | 34 | // ---------------------------------------------------------------------- 35 | // system variables (set/fixed at start of session) 36 | // 37 | extern int MaxGray; 38 | extern int Verbose; 39 | extern int SIZEOF[]; 40 | 41 | extern int NULL_TYPE[]; 42 | extern int BW_TYPE[]; 43 | extern int BWA_TYPE[]; 44 | extern int RGB_TYPE[]; 45 | extern int RGBA_TYPE[]; 46 | extern int HSV_TYPE[]; 47 | extern int YIQ_TYPE[]; 48 | extern int LUT_TYPE[]; 49 | extern int MAT_TYPE[]; 50 | extern int FFT_TYPE[]; 51 | 52 | extern int UCHARCH_TYPE[]; 53 | extern int SHORTCH_TYPE[]; 54 | extern int INTCH_TYPE[]; 55 | extern int LONGCH_TYPE[]; 56 | extern int FLOATCH_TYPE[]; 57 | extern int DOUBLECH_TYPE[]; 58 | 59 | extern int INT2_TYPE[]; 60 | extern int FLOAT2_TYPE[]; 61 | extern int INT3_TYPE[]; 62 | extern int FLOAT3_TYPE[]; 63 | extern int INT4_TYPE[]; 64 | extern int FLOAT4_TYPE[]; 65 | 66 | extern int *CHTYPE_CH[]; 67 | extern int *CHTYPE_IMAGE[]; 68 | extern char *CHTYPE_NAME[]; 69 | extern char CHTYPE_LTR[]; 70 | 71 | extern uchar BITMASK[]; 72 | 73 | 74 | 75 | // ---------------------------------------------------------------------- 76 | // remaining global variables (may change during session) 77 | // 78 | 79 | extern int AbsVal; 80 | extern int BorderVal; 81 | extern double CubicConvA; 82 | extern int HistoFit; 83 | extern int ImagePadLen; 84 | extern int ImagePadMtd; 85 | extern double PlotScl; 86 | extern int SavePixmap; 87 | extern int Serpentine; 88 | extern int JpgQuality; 89 | extern int SwapBytes; 90 | 91 | 92 | // IPcastimg.cpp - type casting routines for images 93 | extern void IP_castImage (ImagePtr, int, ImagePtr); 94 | extern void IP_initAlphaChannel(ImagePtr, int); 95 | 96 | // IPcastmem.cpp - type casting routines for memory blocks 97 | extern void IP_castMemory (void*, int, int, void*, int, int, int); 98 | 99 | // IPcolorconv.cpp - conversion between color representations 100 | extern void IP_RGBtoYIQ1 (int, int, int, int&, int&, int&); 101 | extern void IP_YIQtoRGB1 (int, int, int, int&, int&, int&); 102 | extern void IP_RGBtoHSV1 (int, int, int, int&, int&, int&); 103 | extern void IP_HSVtoRGB1 (int, int, int, int&, int&, int&); 104 | extern void IP_clipRGB (int&, int&, int&); 105 | 106 | // IPhisto.cpp - histogram evaluation 107 | extern void IP_histogram (ImagePtr, int, int*, int, double&, double&); 108 | 109 | // IPinit.cpp - initialize global IP data structures 110 | extern void IP_init (void); 111 | 112 | // IPio.cpp - image input/output 113 | extern ImagePtr IP_readImage (const char*); 114 | extern bool IP_readImageIntoI (const char*, ImagePtr); 115 | extern bool IP_readImageDimensions(const char*, int&, int&); 116 | extern bool IP_saveImage (ImagePtr, const char*, const char*); 117 | 118 | // IPmipmap.cpp - mipmap routines 119 | extern int IP_mipmap (Image, Image&); 120 | 121 | // IPmmch.cpp - channel memory management 122 | #include "IPmmch.tpp" 123 | template 124 | bool IP_getChannel (ImagePtr, int, ChannelPtr&, int &); 125 | template 126 | void IP_copyFromRow (ChannelPtr, int, int, ChannelPtr); 127 | template 128 | void IP_copyFromRow (ImagePtr, int, int, ChannelPtr); 129 | template 130 | void IP_copyToRow (ChannelPtr, ImagePtr , int, int); 131 | template 132 | void IP_copyToRow (ChannelPtr, ChannelPtr, int, int); 133 | 134 | extern void IP_copyChannel (ImagePtr, int, ImagePtr, int ); 135 | extern void IP_copyChannelEnd (ImagePtr, int, ImagePtr); 136 | extern void IP_castChannel (ImagePtr, int, ImagePtr, int, int); 137 | extern void IP_castChannels (ImagePtr, int*,ImagePtr); 138 | extern void IP_castChannelsEq (ImagePtr, int, ImagePtr); 139 | extern void IP_castChannelsMin(ImagePtr, int, ImagePtr); 140 | extern void IP_castChannelsMax(ImagePtr, int, ImagePtr); 141 | extern void IP_clearChannel (ImagePtr, int, ImagePtr); 142 | extern int IP_checkDimensions(ImagePtr, ImagePtr); 143 | 144 | // IPmmimg.cpp 145 | extern Image *IP_allocImage (int, int, int*); 146 | extern Image *IP_allocImage_I (ImagePtr); 147 | extern void IP_allocImageInI(ImagePtr, int, int, int*); 148 | extern void IP_copyImage (ImagePtr, ImagePtr); 149 | extern void IP_copyHeader (ImagePtr, int, ImagePtr); 150 | extern void IP_copyHeader2 (ImagePtr, ImagePtr, int, ImagePtr); 151 | extern void IP_copyImageBuffer(ImagePtr, ImagePtr); 152 | 153 | 154 | // IPutil.cpp 155 | extern void IP_interleave (ImagePtr, ImagePtr); 156 | extern void IP_interleave4 (ImagePtr, int, int, int, int, ImagePtr); 157 | extern void IP_uninterleave (ImagePtr, ImagePtr); 158 | extern void IP_normalizeDimensions(ImagePtr, ImagePtr); 159 | extern void IP_crop (ImagePtr, int, int, int, int, ImagePtr); 160 | extern void IP_shift (ImagePtr, int, int, ImagePtr); 161 | extern void IP_pad (ImagePtr, int*, int, ImagePtr); 162 | extern void IP_pad1D (ChannelPtr, int, int, int, int, 163 | ChannelPtr&); 164 | extern void IP_fpad1D (ChannelPtr, int, int, int, int, 165 | ChannelPtr&); 166 | extern void IP_clearImage (ImagePtr); 167 | extern void IP_setImage (ImagePtr, double*); 168 | extern void IP_minmaxImage (ImagePtr, double&, double&); 169 | extern void IP_minmaxChannel(ImagePtr, int, double&, double&); 170 | extern void IP_RGBdecouple (ImagePtr, ImagePtr &, bool decouple=true); 171 | extern void IP_RGBcouple (ImagePtr, ImagePtr, ImagePtr); 172 | extern void IP_bailout (const char*, ...); 173 | extern void IP_clip (ImagePtr, double, double, ImagePtr); 174 | extern void IP_embedRange (ImagePtr I1, double t1, double t2, ImagePtr I2); 175 | extern void IP_scaleRange (ImagePtr I1, double t1, double t2, ImagePtr I2); 176 | // IPtoUI.cpp 177 | extern void IP_printfErr(const char *fmt, ...); 178 | 179 | } // namespace IP 180 | 181 | #endif // IP_H 182 | -------------------------------------------------------------------------------- /src/IP/linux/header/IPdefs.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IPdefs.h - Header for IP symbolic constants (#defines) and globals. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file IPdefs.h 11 | //! \brief Header for IP symbolic constants (#defines) and globals. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef IPDEFS_H 15 | #define IPDEFS_H 16 | 17 | // ---------------------------------------------------------------------- 18 | // standard include files 19 | // 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace IP { 31 | 32 | // ---------------------------------------------------------------------- 33 | // datatype typedefs 34 | // 35 | // comment out uchar typedef because it is already defined in Qt library 36 | // typedef unsigned char uchar; 37 | 38 | 39 | 40 | // ---------------------------------------------------------------------- 41 | // math definitions 42 | // 43 | #define PI 3.1415926535897931160E0 44 | #define PI2 6.2831853071795862320E0 45 | #define PI_2 1.5707963267948965580E0 46 | #define DEGtoRAD 0.0174532927777777777E0 47 | #define RADtoDEG 57.295778666661658617E0 48 | #define NEG_INF -9999999 49 | 50 | 51 | 52 | // ---------------------------------------------------------------------- 53 | // miscellaneous definitions 54 | // 55 | #define LSB 0x0001 56 | #define MXBLUR 256 57 | #define MXCH 8192 58 | #define MXCHANNEL 16 59 | #define MXGRAY 256 60 | #define MXHALFTONE 10 61 | #define MXRES 4096 62 | #define MXSTRLEN 1024 63 | #define MXWINDOWS 16 64 | 65 | 66 | 67 | // ---------------------------------------------------------------------- 68 | // channel sizes 69 | // 70 | #define UCHAR_SZ sizeof(uchar) 71 | #define SHORT_SZ sizeof(short) 72 | #define INT_SZ sizeof(int) 73 | #define LONG_SZ sizeof(long) 74 | #define FLOAT_SZ sizeof(float) 75 | #define DOUBLE_SZ sizeof(double) 76 | 77 | 78 | 79 | // ---------------------------------------------------------------------- 80 | // pixel sizes 81 | // 82 | #define BW_PXLSZ UCHAR_SZ 83 | #define BWA_PXLSZ (2*UCHAR_SZ) 84 | #define RGB_PXLSZ (3*UCHAR_SZ) 85 | #define RGBA_PXLSZ (4*UCHAR_SZ) 86 | #define HSV_PXLSZ (3*SHORT_SZ) 87 | #define YIQ_PXLSZ (3*SHORT_SZ) 88 | 89 | 90 | 91 | // ---------------------------------------------------------------------- 92 | // useful macros 93 | // Note: ROUND rounds arg to nearest integer 94 | // Note: FLOOR rounds arg to nearest integer towards -infinity 95 | // Note: CEILING rounds arg to nearest integer towards +infinity 96 | // 97 | #define ABS(A) ((A) >= 0 ? (A) : -(A)) 98 | #define SGN(A) ((A) > 0 ? 1 : ((A) < 0 ? -1 : 0 )) 99 | #define ROUND(A) ((A) >= 0 ? (int)((A)+.5) : -(int)(.5-(A))) 100 | #define FLOOR(A) ((A)==(int)(A) ? (int)(A) : (A)>0 ? (int)(A):(int)(A)-1) 101 | #define CEILING(A) ((A)==(int)(A) ? (int)(A) : (A)>0 ? (int)(A)+1:(int)(A)) 102 | #define CLIP(A,L,H) ((A)<=(L) ? (L) : (A)<=(H) ? (A) : (H)) 103 | #define MAX(A,B) ((A) > (B) ? (A) : (B)) 104 | #define MIN(A,B) ((A) < (B) ? (A) : (B)) 105 | #define SWAP(A,B) { double temp=(A); (A) = (B); (B) = temp; } 106 | #define SWAP_INT(A,B) { (A) ^= (B); (B) ^= (A); (A) ^= (B); } 107 | 108 | #define NEWIMAGE IP_allocImage(0, 0, NULL_TYPE) 109 | #define IP_copyImageHeader(I1, I2) IP_copyHeader(I1, 1, I2) 110 | #define IP_copyImageHeaderOnly(I1, I2) IP_copyHeader(I1, 0, I2) 111 | #define IP_copyImageHeader2(I1, I2, I3) IP_copyHeader2(I1, I2, 1, I3) 112 | #define IP_copyImageHeaderOnly2(I1, I2, I3) IP_copyHeader2(I1, I2, 0, I3) 113 | 114 | 115 | 116 | // ---------------------------------------------------------------------- 117 | // type casting macro: 118 | // cast total objects in p1 (of type t1) into p2 (with type t2) 119 | // with strides s1 and s2, respectively 120 | // 121 | #define MEM_CAST(p1, t1, s1, p2, t2, s2, total)\ 122 | {\ 123 | t1 *src;\ 124 | t2 *dst;\ 125 | int i;\ 126 | src = (t1 *) p1;\ 127 | dst = (t2 *) p2;\ 128 | for(i=0; i 33 | inline bool 34 | IP_getChannel(ImagePtr I, int ch, ChannelPtr &ptr, int &type) 35 | { 36 | if(ch<0 || ch>MXCHANNEL) { 37 | fprintf(stderr, "IP_getChannel: Illegal channel %d\n", ch); 38 | return false; 39 | } 40 | if(ch>=I->maxChannel()) { 41 | return false; 42 | } 43 | 44 | ptr = I[ch]; 45 | type = I->channelType(ch); 46 | return true; 47 | } 48 | 49 | 50 | 51 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 52 | // IP_copyFromRow: 53 | // 54 | // Copy a row of an image channel to an output channel. 55 | //! \brief Copy a row of an image channel to an output channel. 56 | //! \param[in] p - Input channel pointer. 57 | //! \param[in] row - Row index. 58 | //! \param[in] w - Row width. 59 | //! \param[out] q - Output channel pointer. 60 | // 61 | template 62 | inline void 63 | IP_copyFromRow(ChannelPtr p, int row, int w, ChannelPtr q) 64 | { 65 | p += row * w; 66 | for(int i=0; i(p[i]); 68 | } 69 | 70 | 71 | 72 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | // IP_copyFromRow: 74 | // 75 | // Copy a row of an image to a channel (See IPfft.cpp). 76 | //! \brief Copy a row of an image to a channel (See IPfft.cpp). 77 | //! \param[in] I - Input image. 78 | //! \param[in] ch - Input channel index. 79 | //! \param[in] row - Input row index. 80 | //! \param[out] p - Output channel. 81 | // 82 | template 83 | inline void 84 | IP_copyFromRow(ImagePtr I, int ch, int row, ChannelPtr p) 85 | { 86 | int w = I->width(); 87 | int type = I->channelType(ch); 88 | 89 | switch(type) { 90 | case UCHAR_TYPE: 91 | { 92 | ChannelPtr q; 93 | IP_getChannel(I, ch, q, type); 94 | IP_copyFromRow(q, row, w, p); 95 | break; 96 | } 97 | case SHORT_TYPE: 98 | { 99 | ChannelPtr q; 100 | IP_getChannel(I, ch, q, type); 101 | IP_copyFromRow(q, row, w, p); 102 | break; 103 | } 104 | case INT_TYPE: 105 | { 106 | ChannelPtr q; 107 | IP_getChannel(I, ch, q, type); 108 | IP_copyFromRow(q, row, w, p); 109 | break; 110 | } 111 | case LONG_TYPE: 112 | { 113 | ChannelPtr q; 114 | IP_getChannel(I, ch, q, type); 115 | IP_copyFromRow(q, row, w, p); 116 | break; 117 | } 118 | case FLOAT_TYPE: 119 | { 120 | ChannelPtr q; 121 | IP_getChannel(I, ch, q, type); 122 | IP_copyFromRow(q, row, w, p); 123 | break; 124 | } 125 | case DOUBLE_TYPE: 126 | { 127 | ChannelPtr q; 128 | IP_getChannel(I, ch, q, type); 129 | IP_copyFromRow(q, row, w, p); 130 | break; 131 | } 132 | } 133 | } 134 | 135 | 136 | 137 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 138 | // IP_copyToRow: 139 | // 140 | // Copy a channel to a row of an image channel. 141 | //! \brief Copy a channel to a row of an image channel. 142 | //! \param[in] p - Input channel pointer. 143 | //! \param[out] q - Output channel pointer. 144 | //! \param[in] row - Row index. 145 | //! \param[in] w - Row width. 146 | // 147 | template 148 | inline void 149 | IP_copyToRow(ChannelPtr p, ChannelPtr q, int row, int w) 150 | { 151 | q += row * w; 152 | for(int i=0; i(p[i]); 154 | } 155 | 156 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 157 | // IP_copyToRow: 158 | // 159 | // Copy a channel's data into a row of an image (See IPfft.cpp). 160 | //! \brief Copy a channel's data into a row of an image (See IPfft.cpp). 161 | //! \param[in] p - Input channel. 162 | //! \param[out] I - Output image. 163 | //! \param[in] ch - Output channel index. 164 | //! \param[in] row - Output row index. 165 | // 166 | template 167 | inline void 168 | IP_copyToRow(ChannelPtr p, ImagePtr I, int ch, int row) 169 | { 170 | int w = I->width(); 171 | int type = I->channelType(ch); 172 | 173 | switch(type) { 174 | case UCHAR_TYPE: 175 | { 176 | ChannelPtr q; 177 | IP_getChannel(I, ch, q, type); 178 | IP_copyToRow(p, q, row, w); 179 | break; 180 | } 181 | case SHORT_TYPE: 182 | { 183 | ChannelPtr q; 184 | IP_getChannel(I, ch, q, type); 185 | IP_copyToRow(p, q, row, w); 186 | break; 187 | } 188 | case INT_TYPE: 189 | { 190 | ChannelPtr q; 191 | IP_getChannel(I, ch, q, type); 192 | IP_copyToRow(p, q, row, w); 193 | break; 194 | } 195 | case LONG_TYPE: 196 | { 197 | ChannelPtr q; 198 | IP_getChannel(I, ch, q, type); 199 | IP_copyToRow(p, q, row, w); 200 | break; 201 | } 202 | case FLOAT_TYPE: 203 | { 204 | ChannelPtr q; 205 | IP_getChannel(I, ch, q, type); 206 | IP_copyToRow(p, q, row, w); 207 | break; 208 | } 209 | case DOUBLE_TYPE: 210 | { 211 | ChannelPtr q; 212 | IP_getChannel(I, ch, q, type); 213 | IP_copyToRow(p, q, row, w); 214 | } 215 | } 216 | } 217 | //@} 218 | -------------------------------------------------------------------------------- /src/IP/linux/header/IPtoUI.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IPtoUI.h - Header for IPtoUI.cpp file 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \mainpage Image Processing Package 11 | //! \author George Wolberg 12 | //! \date 2016 13 | //! \par References: 14 | //! This code is part of the 15 | //! IMPROC Image Processing Software Package\n 16 | //! Copyright © 2016 by George Wolberg 17 | 18 | //! \file IPtoUI.h 19 | //! \brief Image Processing Package header file for IPtoUI.cpp 20 | //! \author George Wolberg, 2016 21 | 22 | #ifndef IPTOUI_H 23 | #define IPTOUI_H 24 | 25 | namespace IP { 26 | 27 | extern void IP_QImageToIP(const QImage&, ImagePtr &); 28 | extern void IP_IPtoQImage(const ImagePtr&, QImage &); 29 | 30 | } // namespace IP 31 | 32 | #endif // IPTOUI_H 33 | -------------------------------------------------------------------------------- /src/IP/mac/header/Channel.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Channel.h - Channel class. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file Channel.h 11 | //! \brief Channel class. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef CHANNEL_H 15 | #define CHANNEL_H 16 | 17 | #include "IPdefs.h" 18 | 19 | namespace IP { 20 | 21 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | // Channel class declaration 23 | //! \brief Channel class. 24 | //! \details The Channel class handles image channel data of various 25 | //! types. 26 | // 27 | class Channel { 28 | public: 29 | // constructors 30 | Channel(); // default constructor 31 | Channel(const Channel &); // copy constructor 32 | Channel(int); // construct to specified # of bytes 33 | 34 | // destructor 35 | ~Channel(); 36 | 37 | // get methods 38 | const void *buf() const; // buffer pointer 39 | void *buf(); // buffer pointer 40 | 41 | // resize channel buffer 42 | void resize(int); // resize to specified # of bytes 43 | 44 | // free channel 45 | void free(); 46 | 47 | private: 48 | void *m_buf; // channel buffer pointer 49 | }; 50 | 51 | 52 | 53 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | // Channel::Channel: 55 | // 56 | // Default constructor. A null pointer is assigned to the channel. 57 | //! \brief Default constructor. 58 | //! \details Assign a null pointer to the channel. 59 | // 60 | inline 61 | Channel::Channel() 62 | : m_buf(0) 63 | {} 64 | 65 | 66 | 67 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | // Channel::Channel: 69 | // 70 | // Size constructor. Allocate specified number of bytes to channel. 71 | //! \brief Size constructor. 72 | //! \details Allocate specified number of bytes to channel. 73 | // 74 | inline 75 | Channel::Channel(int size) 76 | { 77 | m_buf = new uchar[size]; 78 | } 79 | 80 | 81 | 82 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 | // Channel::~Channel: 84 | // 85 | // Destructor function. Free channel memory and set channel pointer to null. 86 | //! \brief Destructor. 87 | //! \details Free channel memory and set channel pointer to null. 88 | // 89 | inline 90 | Channel::~Channel() 91 | { 92 | if (m_buf) delete [] (uchar *) m_buf; 93 | } 94 | 95 | 96 | 97 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 98 | // Channel::buf: 99 | // 100 | // Channel memory pointer. 101 | //! \brief Channel memory pointer. 102 | //! \details Return channel memory pointer. 103 | //! \return Pointer to data of type void (const version). 104 | // 105 | inline const void * 106 | Channel::buf() const 107 | { 108 | return m_buf; 109 | } 110 | 111 | 112 | 113 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 114 | // Channel::buf: 115 | // 116 | // Channel pointer. 117 | //! \brief Channel memory pointer. 118 | //! \details Return channel memory pointer. 119 | //! \return Pointer to data of type void. 120 | // 121 | inline void * 122 | Channel::buf() 123 | { 124 | return m_buf; 125 | } 126 | 127 | 128 | 129 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 130 | // Channel::resize: 131 | // 132 | // Resize channel buffer to have size bytes. 133 | //! \brief Resize channel buffer. 134 | //! \details Resize channel buffer to \a size bytes. Reset channel pointer. 135 | // 136 | inline void 137 | Channel::resize(int size) 138 | { 139 | m_buf = new uchar[size]; 140 | } 141 | 142 | 143 | 144 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 145 | // Channel::free: 146 | // 147 | // Free channel buffer. 148 | //! \brief Free channel buffer. 149 | //! \details Free channel memory and reset channel pointer to null. 150 | // 151 | inline void 152 | Channel::free() { 153 | if(m_buf) { 154 | delete [] (uchar*) m_buf; 155 | m_buf = 0; 156 | } 157 | } 158 | 159 | } // namespace IP 160 | 161 | #endif // CHANNEL_H 162 | -------------------------------------------------------------------------------- /src/IP/mac/header/ChannelPtr.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // ChannelPtr.h - Channel pointer class. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file ChannelPtr.h 11 | //! \brief ChannelPtr class. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef CHANNELPTR_H 15 | #define CHANNELPTR_H 16 | 17 | #include "Channel.h" 18 | 19 | namespace IP { 20 | 21 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | // ChannelPtr class declaration 23 | //! \brief ChannelPtr class. 24 | //! \details A smart pointer to the Channel class. 25 | // 26 | template 27 | class ChannelPtr { 28 | public: 29 | // constructors 30 | ChannelPtr(); // default constructor 31 | ChannelPtr(const ChannelPtr &); // copy constructor 32 | ChannelPtr(Channel *c); // construct from channel ptr 33 | 34 | // destructor 35 | ~ChannelPtr(); 36 | 37 | // get a pointer to the channel buffer 38 | const T *buf() const; 39 | T *buf(); 40 | 41 | // overloaded operators 42 | ChannelPtr &operator=(const ChannelPtr &); // assignment 43 | T &operator* () const; // value-at 44 | T &operator[](int) const; // index into buffer 45 | ChannelPtr &operator++(); // prefix increment 46 | ChannelPtr operator++(int); // postfix increment 47 | ChannelPtr &operator--(); // prefix decrement 48 | ChannelPtr operator--(int); // postfix decrement 49 | ChannelPtr &operator+=(int); // addition 50 | ChannelPtr &operator-=(int); // subtraction 51 | 52 | private: 53 | T *m_buf; // channel buffer ptr 54 | }; 55 | 56 | } // namespace IP 57 | 58 | #include "ChannelPtr.tpp" 59 | 60 | #endif // CHANNELPTR_H 61 | -------------------------------------------------------------------------------- /src/IP/mac/header/IP.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IP.h - Header for IP*.cpp files 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \mainpage Image Processing Package 11 | //! \author George Wolberg 12 | //! \date 2016 13 | //! \par References: 14 | //! This code is part of the 15 | //! IMPROC Image Processing Software Package\n 16 | //! Copyright © 2016 by George Wolberg 17 | 18 | //! \file IP.h 19 | //! \brief Image Processing Package main header file. 20 | //! \author George Wolberg and Gene Yu, 2016 21 | 22 | #ifndef IP_H 23 | #define IP_H 24 | 25 | #include "IPdefs.h" 26 | #include "Channel.h" 27 | #include "ChannelPtr.h" 28 | #include "Image.h" 29 | #include "ImagePtr.h" 30 | #include 31 | 32 | namespace IP { 33 | 34 | // ---------------------------------------------------------------------- 35 | // system variables (set/fixed at start of session) 36 | // 37 | extern int MaxGray; 38 | extern int Verbose; 39 | extern int SIZEOF[]; 40 | 41 | extern int NULL_TYPE[]; 42 | extern int BW_TYPE[]; 43 | extern int BWA_TYPE[]; 44 | extern int RGB_TYPE[]; 45 | extern int RGBA_TYPE[]; 46 | extern int HSV_TYPE[]; 47 | extern int YIQ_TYPE[]; 48 | extern int LUT_TYPE[]; 49 | extern int MAT_TYPE[]; 50 | extern int FFT_TYPE[]; 51 | 52 | extern int UCHARCH_TYPE[]; 53 | extern int SHORTCH_TYPE[]; 54 | extern int INTCH_TYPE[]; 55 | extern int LONGCH_TYPE[]; 56 | extern int FLOATCH_TYPE[]; 57 | extern int DOUBLECH_TYPE[]; 58 | 59 | extern int INT2_TYPE[]; 60 | extern int FLOAT2_TYPE[]; 61 | extern int INT3_TYPE[]; 62 | extern int FLOAT3_TYPE[]; 63 | extern int INT4_TYPE[]; 64 | extern int FLOAT4_TYPE[]; 65 | 66 | extern int *CHTYPE_CH[]; 67 | extern int *CHTYPE_IMAGE[]; 68 | extern char *CHTYPE_NAME[]; 69 | extern char CHTYPE_LTR[]; 70 | 71 | extern uchar BITMASK[]; 72 | 73 | 74 | 75 | // ---------------------------------------------------------------------- 76 | // remaining global variables (may change during session) 77 | // 78 | 79 | extern int AbsVal; 80 | extern int BorderVal; 81 | extern double CubicConvA; 82 | extern int HistoFit; 83 | extern int ImagePadLen; 84 | extern int ImagePadMtd; 85 | extern double PlotScl; 86 | extern int SavePixmap; 87 | extern int Serpentine; 88 | extern int JpgQuality; 89 | extern int SwapBytes; 90 | 91 | 92 | // IPcastimg.cpp - type casting routines for images 93 | extern void IP_castImage (ImagePtr, int, ImagePtr); 94 | extern void IP_initAlphaChannel(ImagePtr, int); 95 | 96 | // IPcastmem.cpp - type casting routines for memory blocks 97 | extern void IP_castMemory (void*, int, int, void*, int, int, int); 98 | 99 | // IPcolorconv.cpp - conversion between color representations 100 | extern void IP_RGBtoYIQ1 (int, int, int, int&, int&, int&); 101 | extern void IP_YIQtoRGB1 (int, int, int, int&, int&, int&); 102 | extern void IP_RGBtoHSV1 (int, int, int, int&, int&, int&); 103 | extern void IP_HSVtoRGB1 (int, int, int, int&, int&, int&); 104 | extern void IP_clipRGB (int&, int&, int&); 105 | 106 | // IPhisto.cpp - histogram evaluation 107 | extern void IP_histogram (ImagePtr, int, int*, int, double&, double&); 108 | 109 | // IPinit.cpp - initialize global IP data structures 110 | extern void IP_init (void); 111 | 112 | // IPio.cpp - image input/output 113 | extern ImagePtr IP_readImage (const char*); 114 | extern bool IP_readImageIntoI (const char*, ImagePtr); 115 | extern bool IP_readImageDimensions(const char*, int&, int&); 116 | extern bool IP_saveImage (ImagePtr, const char*, const char*); 117 | 118 | // IPmipmap.cpp - mipmap routines 119 | extern int IP_mipmap (Image, Image&); 120 | 121 | // IPmmch.cpp - channel memory management 122 | #include "IPmmch.tpp" 123 | template 124 | bool IP_getChannel (ImagePtr, int, ChannelPtr&, int &); 125 | template 126 | void IP_copyFromRow (ChannelPtr, int, int, ChannelPtr); 127 | template 128 | void IP_copyFromRow (ImagePtr, int, int, ChannelPtr); 129 | template 130 | void IP_copyToRow (ChannelPtr, ImagePtr , int, int); 131 | template 132 | void IP_copyToRow (ChannelPtr, ChannelPtr, int, int); 133 | 134 | extern void IP_copyChannel (ImagePtr, int, ImagePtr, int ); 135 | extern void IP_copyChannelEnd (ImagePtr, int, ImagePtr); 136 | extern void IP_castChannel (ImagePtr, int, ImagePtr, int, int); 137 | extern void IP_castChannels (ImagePtr, int*,ImagePtr); 138 | extern void IP_castChannelsEq (ImagePtr, int, ImagePtr); 139 | extern void IP_castChannelsMin(ImagePtr, int, ImagePtr); 140 | extern void IP_castChannelsMax(ImagePtr, int, ImagePtr); 141 | extern void IP_clearChannel (ImagePtr, int, ImagePtr); 142 | extern int IP_checkDimensions(ImagePtr, ImagePtr); 143 | 144 | // IPmmimg.cpp 145 | extern Image *IP_allocImage (int, int, int*); 146 | extern Image *IP_allocImage_I (ImagePtr); 147 | extern void IP_allocImageInI(ImagePtr, int, int, int*); 148 | extern void IP_copyImage (ImagePtr, ImagePtr); 149 | extern void IP_copyHeader (ImagePtr, int, ImagePtr); 150 | extern void IP_copyHeader2 (ImagePtr, ImagePtr, int, ImagePtr); 151 | extern void IP_copyImageBuffer(ImagePtr, ImagePtr); 152 | 153 | 154 | // IPutil.cpp 155 | extern void IP_interleave (ImagePtr, ImagePtr); 156 | extern void IP_interleave4 (ImagePtr, int, int, int, int, ImagePtr); 157 | extern void IP_uninterleave (ImagePtr, ImagePtr); 158 | extern void IP_normalizeDimensions(ImagePtr, ImagePtr); 159 | extern void IP_crop (ImagePtr, int, int, int, int, ImagePtr); 160 | extern void IP_shift (ImagePtr, int, int, ImagePtr); 161 | extern void IP_pad (ImagePtr, int*, int, ImagePtr); 162 | extern void IP_pad1D (ChannelPtr, int, int, int, int, 163 | ChannelPtr&); 164 | extern void IP_fpad1D (ChannelPtr, int, int, int, int, 165 | ChannelPtr&); 166 | extern void IP_clearImage (ImagePtr); 167 | extern void IP_setImage (ImagePtr, double*); 168 | extern void IP_minmaxImage (ImagePtr, double&, double&); 169 | extern void IP_minmaxChannel(ImagePtr, int, double&, double&); 170 | extern void IP_RGBdecouple (ImagePtr, ImagePtr &, bool decouple=true); 171 | extern void IP_RGBcouple (ImagePtr, ImagePtr, ImagePtr); 172 | extern void IP_bailout (const char*, ...); 173 | extern void IP_clip (ImagePtr, double, double, ImagePtr); 174 | extern void IP_embedRange (ImagePtr I1, double t1, double t2, ImagePtr I2); 175 | extern void IP_scaleRange (ImagePtr I1, double t1, double t2, ImagePtr I2); 176 | // IPtoUI.cpp 177 | extern void IP_printfErr(const char *fmt, ...); 178 | 179 | } // namespace IP 180 | 181 | #endif // IP_H 182 | -------------------------------------------------------------------------------- /src/IP/mac/header/IPdefs.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IPdefs.h - Header for IP symbolic constants (#defines) and globals. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file IPdefs.h 11 | //! \brief Header for IP symbolic constants (#defines) and globals. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef IPDEFS_H 15 | #define IPDEFS_H 16 | 17 | // ---------------------------------------------------------------------- 18 | // standard include files 19 | // 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace IP { 31 | 32 | // ---------------------------------------------------------------------- 33 | // datatype typedefs 34 | // 35 | // comment out uchar typedef because it is already defined in Qt library 36 | // typedef unsigned char uchar; 37 | 38 | 39 | 40 | // ---------------------------------------------------------------------- 41 | // math definitions 42 | // 43 | #define PI 3.1415926535897931160E0 44 | #define PI2 6.2831853071795862320E0 45 | #define PI_2 1.5707963267948965580E0 46 | #define DEGtoRAD 0.0174532927777777777E0 47 | #define RADtoDEG 57.295778666661658617E0 48 | #define NEG_INF -9999999 49 | 50 | 51 | 52 | // ---------------------------------------------------------------------- 53 | // miscellaneous definitions 54 | // 55 | #define LSB 0x0001 56 | #define MXBLUR 256 57 | #define MXCH 8192 58 | #define MXCHANNEL 16 59 | #define MXGRAY 256 60 | #define MXHALFTONE 10 61 | #define MXRES 4096 62 | #define MXSTRLEN 1024 63 | #define MXWINDOWS 16 64 | 65 | 66 | 67 | // ---------------------------------------------------------------------- 68 | // channel sizes 69 | // 70 | #define UCHAR_SZ sizeof(uchar) 71 | #define SHORT_SZ sizeof(short) 72 | #define INT_SZ sizeof(int) 73 | #define LONG_SZ sizeof(long) 74 | #define FLOAT_SZ sizeof(float) 75 | #define DOUBLE_SZ sizeof(double) 76 | 77 | 78 | 79 | // ---------------------------------------------------------------------- 80 | // pixel sizes 81 | // 82 | #define BW_PXLSZ UCHAR_SZ 83 | #define BWA_PXLSZ (2*UCHAR_SZ) 84 | #define RGB_PXLSZ (3*UCHAR_SZ) 85 | #define RGBA_PXLSZ (4*UCHAR_SZ) 86 | #define HSV_PXLSZ (3*SHORT_SZ) 87 | #define YIQ_PXLSZ (3*SHORT_SZ) 88 | 89 | 90 | 91 | // ---------------------------------------------------------------------- 92 | // useful macros 93 | // Note: ROUND rounds arg to nearest integer 94 | // Note: FLOOR rounds arg to nearest integer towards -infinity 95 | // Note: CEILING rounds arg to nearest integer towards +infinity 96 | // 97 | #define ABS(A) ((A) >= 0 ? (A) : -(A)) 98 | #define SGN(A) ((A) > 0 ? 1 : ((A) < 0 ? -1 : 0 )) 99 | #define ROUND(A) ((A) >= 0 ? (int)((A)+.5) : -(int)(.5-(A))) 100 | #define FLOOR(A) ((A)==(int)(A) ? (int)(A) : (A)>0 ? (int)(A):(int)(A)-1) 101 | #define CEILING(A) ((A)==(int)(A) ? (int)(A) : (A)>0 ? (int)(A)+1:(int)(A)) 102 | #define CLIP(A,L,H) ((A)<=(L) ? (L) : (A)<=(H) ? (A) : (H)) 103 | #define MAX(A,B) ((A) > (B) ? (A) : (B)) 104 | #define MIN(A,B) ((A) < (B) ? (A) : (B)) 105 | #define SWAP(A,B) { double temp=(A); (A) = (B); (B) = temp; } 106 | #define SWAP_INT(A,B) { (A) ^= (B); (B) ^= (A); (A) ^= (B); } 107 | 108 | #define NEWIMAGE IP_allocImage(0, 0, NULL_TYPE) 109 | #define IP_copyImageHeader(I1, I2) IP_copyHeader(I1, 1, I2) 110 | #define IP_copyImageHeaderOnly(I1, I2) IP_copyHeader(I1, 0, I2) 111 | #define IP_copyImageHeader2(I1, I2, I3) IP_copyHeader2(I1, I2, 1, I3) 112 | #define IP_copyImageHeaderOnly2(I1, I2, I3) IP_copyHeader2(I1, I2, 0, I3) 113 | 114 | 115 | 116 | // ---------------------------------------------------------------------- 117 | // type casting macro: 118 | // cast total objects in p1 (of type t1) into p2 (with type t2) 119 | // with strides s1 and s2, respectively 120 | // 121 | #define MEM_CAST(p1, t1, s1, p2, t2, s2, total)\ 122 | {\ 123 | t1 *src;\ 124 | t2 *dst;\ 125 | int i;\ 126 | src = (t1 *) p1;\ 127 | dst = (t2 *) p2;\ 128 | for(i=0; i 33 | inline bool 34 | IP_getChannel(ImagePtr I, int ch, ChannelPtr &ptr, int &type) 35 | { 36 | if(ch<0 || ch>MXCHANNEL) { 37 | fprintf(stderr, "IP_getChannel: Illegal channel %d\n", ch); 38 | return false; 39 | } 40 | if(ch>=I->maxChannel()) { 41 | return false; 42 | } 43 | 44 | ptr = I[ch]; 45 | type = I->channelType(ch); 46 | return true; 47 | } 48 | 49 | 50 | 51 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 52 | // IP_copyFromRow: 53 | // 54 | // Copy a row of an image channel to an output channel. 55 | //! \brief Copy a row of an image channel to an output channel. 56 | //! \param[in] p - Input channel pointer. 57 | //! \param[in] row - Row index. 58 | //! \param[in] w - Row width. 59 | //! \param[out] q - Output channel pointer. 60 | // 61 | template 62 | inline void 63 | IP_copyFromRow(ChannelPtr p, int row, int w, ChannelPtr q) 64 | { 65 | p += row * w; 66 | for(int i=0; i(p[i]); 68 | } 69 | 70 | 71 | 72 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | // IP_copyFromRow: 74 | // 75 | // Copy a row of an image to a channel (See IPfft.cpp). 76 | //! \brief Copy a row of an image to a channel (See IPfft.cpp). 77 | //! \param[in] I - Input image. 78 | //! \param[in] ch - Input channel index. 79 | //! \param[in] row - Input row index. 80 | //! \param[out] p - Output channel. 81 | // 82 | template 83 | inline void 84 | IP_copyFromRow(ImagePtr I, int ch, int row, ChannelPtr p) 85 | { 86 | int w = I->width(); 87 | int type = I->channelType(ch); 88 | 89 | switch(type) { 90 | case UCHAR_TYPE: 91 | { 92 | ChannelPtr q; 93 | IP_getChannel(I, ch, q, type); 94 | IP_copyFromRow(q, row, w, p); 95 | break; 96 | } 97 | case SHORT_TYPE: 98 | { 99 | ChannelPtr q; 100 | IP_getChannel(I, ch, q, type); 101 | IP_copyFromRow(q, row, w, p); 102 | break; 103 | } 104 | case INT_TYPE: 105 | { 106 | ChannelPtr q; 107 | IP_getChannel(I, ch, q, type); 108 | IP_copyFromRow(q, row, w, p); 109 | break; 110 | } 111 | case LONG_TYPE: 112 | { 113 | ChannelPtr q; 114 | IP_getChannel(I, ch, q, type); 115 | IP_copyFromRow(q, row, w, p); 116 | break; 117 | } 118 | case FLOAT_TYPE: 119 | { 120 | ChannelPtr q; 121 | IP_getChannel(I, ch, q, type); 122 | IP_copyFromRow(q, row, w, p); 123 | break; 124 | } 125 | case DOUBLE_TYPE: 126 | { 127 | ChannelPtr q; 128 | IP_getChannel(I, ch, q, type); 129 | IP_copyFromRow(q, row, w, p); 130 | break; 131 | } 132 | } 133 | } 134 | 135 | 136 | 137 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 138 | // IP_copyToRow: 139 | // 140 | // Copy a channel to a row of an image channel. 141 | //! \brief Copy a channel to a row of an image channel. 142 | //! \param[in] p - Input channel pointer. 143 | //! \param[out] q - Output channel pointer. 144 | //! \param[in] row - Row index. 145 | //! \param[in] w - Row width. 146 | // 147 | template 148 | inline void 149 | IP_copyToRow(ChannelPtr p, ChannelPtr q, int row, int w) 150 | { 151 | q += row * w; 152 | for(int i=0; i(p[i]); 154 | } 155 | 156 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 157 | // IP_copyToRow: 158 | // 159 | // Copy a channel's data into a row of an image (See IPfft.cpp). 160 | //! \brief Copy a channel's data into a row of an image (See IPfft.cpp). 161 | //! \param[in] p - Input channel. 162 | //! \param[out] I - Output image. 163 | //! \param[in] ch - Output channel index. 164 | //! \param[in] row - Output row index. 165 | // 166 | template 167 | inline void 168 | IP_copyToRow(ChannelPtr p, ImagePtr I, int ch, int row) 169 | { 170 | int w = I->width(); 171 | int type = I->channelType(ch); 172 | 173 | switch(type) { 174 | case UCHAR_TYPE: 175 | { 176 | ChannelPtr q; 177 | IP_getChannel(I, ch, q, type); 178 | IP_copyToRow(p, q, row, w); 179 | break; 180 | } 181 | case SHORT_TYPE: 182 | { 183 | ChannelPtr q; 184 | IP_getChannel(I, ch, q, type); 185 | IP_copyToRow(p, q, row, w); 186 | break; 187 | } 188 | case INT_TYPE: 189 | { 190 | ChannelPtr q; 191 | IP_getChannel(I, ch, q, type); 192 | IP_copyToRow(p, q, row, w); 193 | break; 194 | } 195 | case LONG_TYPE: 196 | { 197 | ChannelPtr q; 198 | IP_getChannel(I, ch, q, type); 199 | IP_copyToRow(p, q, row, w); 200 | break; 201 | } 202 | case FLOAT_TYPE: 203 | { 204 | ChannelPtr q; 205 | IP_getChannel(I, ch, q, type); 206 | IP_copyToRow(p, q, row, w); 207 | break; 208 | } 209 | case DOUBLE_TYPE: 210 | { 211 | ChannelPtr q; 212 | IP_getChannel(I, ch, q, type); 213 | IP_copyToRow(p, q, row, w); 214 | } 215 | } 216 | } 217 | //@} 218 | -------------------------------------------------------------------------------- /src/IP/mac/header/IPtoUI.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IPtoUI.h - Header for IPtoUI.cpp file 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \mainpage Image Processing Package 11 | //! \author George Wolberg 12 | //! \date 2016 13 | //! \par References: 14 | //! This code is part of the 15 | //! IMPROC Image Processing Software Package\n 16 | //! Copyright © 2016 by George Wolberg 17 | 18 | //! \file IPtoUI.h 19 | //! \brief Image Processing Package header file for IPtoUI.cpp 20 | //! \author George Wolberg, 2016 21 | 22 | #ifndef IPTOUI_H 23 | #define IPTOUI_H 24 | 25 | namespace IP { 26 | 27 | extern void IP_QImageToIP(const QImage&, ImagePtr &); 28 | extern void IP_IPtoQImage(const ImagePtr&, QImage &); 29 | 30 | } // namespace IP 31 | 32 | #endif // IPTOUI_H 33 | -------------------------------------------------------------------------------- /src/IP/win/header/Channel.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Channel.h - Channel class. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file Channel.h 11 | //! \brief Channel class. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef CHANNEL_H 15 | #define CHANNEL_H 16 | 17 | #include "IPdefs.h" 18 | 19 | namespace IP { 20 | 21 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | // Channel class declaration 23 | //! \brief Channel class. 24 | //! \details The Channel class handles image channel data of various 25 | //! types. 26 | // 27 | class Channel { 28 | public: 29 | // constructors 30 | Channel(); // default constructor 31 | Channel(const Channel &); // copy constructor 32 | Channel(int); // construct to specified # of bytes 33 | 34 | // destructor 35 | ~Channel(); 36 | 37 | // get methods 38 | const void *buf() const; // buffer pointer 39 | void *buf(); // buffer pointer 40 | 41 | // resize channel buffer 42 | void resize(int); // resize to specified # of bytes 43 | 44 | // free channel 45 | void free(); 46 | 47 | private: 48 | void *m_buf; // channel buffer pointer 49 | }; 50 | 51 | 52 | 53 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | // Channel::Channel: 55 | // 56 | // Default constructor. A null pointer is assigned to the channel. 57 | //! \brief Default constructor. 58 | //! \details Assign a null pointer to the channel. 59 | // 60 | inline 61 | Channel::Channel() 62 | : m_buf(0) 63 | {} 64 | 65 | 66 | 67 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | // Channel::Channel: 69 | // 70 | // Size constructor. Allocate specified number of bytes to channel. 71 | //! \brief Size constructor. 72 | //! \details Allocate specified number of bytes to channel. 73 | // 74 | inline 75 | Channel::Channel(int size) 76 | { 77 | m_buf = new uchar[size]; 78 | } 79 | 80 | 81 | 82 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 | // Channel::~Channel: 84 | // 85 | // Destructor function. Free channel memory and set channel pointer to null. 86 | //! \brief Destructor. 87 | //! \details Free channel memory and set channel pointer to null. 88 | // 89 | inline 90 | Channel::~Channel() 91 | { 92 | if (m_buf) delete [] (uchar *) m_buf; 93 | } 94 | 95 | 96 | 97 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 98 | // Channel::buf: 99 | // 100 | // Channel memory pointer. 101 | //! \brief Channel memory pointer. 102 | //! \details Return channel memory pointer. 103 | //! \return Pointer to data of type void (const version). 104 | // 105 | inline const void * 106 | Channel::buf() const 107 | { 108 | return m_buf; 109 | } 110 | 111 | 112 | 113 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 114 | // Channel::buf: 115 | // 116 | // Channel pointer. 117 | //! \brief Channel memory pointer. 118 | //! \details Return channel memory pointer. 119 | //! \return Pointer to data of type void. 120 | // 121 | inline void * 122 | Channel::buf() 123 | { 124 | return m_buf; 125 | } 126 | 127 | 128 | 129 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 130 | // Channel::resize: 131 | // 132 | // Resize channel buffer to have size bytes. 133 | //! \brief Resize channel buffer. 134 | //! \details Resize channel buffer to \a size bytes. Reset channel pointer. 135 | // 136 | inline void 137 | Channel::resize(int size) 138 | { 139 | m_buf = new uchar[size]; 140 | } 141 | 142 | 143 | 144 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 145 | // Channel::free: 146 | // 147 | // Free channel buffer. 148 | //! \brief Free channel buffer. 149 | //! \details Free channel memory and reset channel pointer to null. 150 | // 151 | inline void 152 | Channel::free() { 153 | if(m_buf) { 154 | delete [] (uchar*) m_buf; 155 | m_buf = 0; 156 | } 157 | } 158 | 159 | } // namespace IP 160 | 161 | #endif // CHANNEL_H 162 | -------------------------------------------------------------------------------- /src/IP/win/header/ChannelPtr.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // ChannelPtr.h - Channel pointer class. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file ChannelPtr.h 11 | //! \brief ChannelPtr class. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef CHANNELPTR_H 15 | #define CHANNELPTR_H 16 | 17 | #include "Channel.h" 18 | 19 | namespace IP { 20 | 21 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | // ChannelPtr class declaration 23 | //! \brief ChannelPtr class. 24 | //! \details A smart pointer to the Channel class. 25 | // 26 | template 27 | class ChannelPtr { 28 | public: 29 | // constructors 30 | ChannelPtr(); // default constructor 31 | ChannelPtr(const ChannelPtr &); // copy constructor 32 | ChannelPtr(Channel *c); // construct from channel ptr 33 | 34 | // destructor 35 | ~ChannelPtr(); 36 | 37 | // get a pointer to the channel buffer 38 | const T *buf() const; 39 | T *buf(); 40 | 41 | // overloaded operators 42 | ChannelPtr &operator=(const ChannelPtr &); // assignment 43 | T &operator* () const; // value-at 44 | T &operator[](int) const; // index into buffer 45 | ChannelPtr &operator++(); // prefix increment 46 | ChannelPtr operator++(int); // postfix increment 47 | ChannelPtr &operator--(); // prefix decrement 48 | ChannelPtr operator--(int); // postfix decrement 49 | ChannelPtr &operator+=(int); // addition 50 | ChannelPtr &operator-=(int); // subtraction 51 | 52 | private: 53 | T *m_buf; // channel buffer ptr 54 | }; 55 | 56 | } // namespace IP 57 | 58 | #include "ChannelPtr.tpp" 59 | 60 | #endif // CHANNELPTR_H 61 | -------------------------------------------------------------------------------- /src/IP/win/header/IP.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IP.h - Header for IP*.cpp files 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \mainpage Image Processing Package 11 | //! \author George Wolberg 12 | //! \date 2016 13 | //! \par References: 14 | //! This code is part of the 15 | //! IMPROC Image Processing Software Package\n 16 | //! Copyright © 2016 by George Wolberg 17 | 18 | //! \file IP.h 19 | //! \brief Image Processing Package main header file. 20 | //! \author George Wolberg and Gene Yu, 2016 21 | 22 | #ifndef IP_H 23 | #define IP_H 24 | 25 | #include "IPdefs.h" 26 | #include "Channel.h" 27 | #include "ChannelPtr.h" 28 | #include "Image.h" 29 | #include "ImagePtr.h" 30 | #include 31 | 32 | namespace IP { 33 | 34 | // ---------------------------------------------------------------------- 35 | // system variables (set/fixed at start of session) 36 | // 37 | extern int MaxGray; 38 | extern int Verbose; 39 | extern int SIZEOF[]; 40 | 41 | extern int NULL_TYPE[]; 42 | extern int BW_TYPE[]; 43 | extern int BWA_TYPE[]; 44 | extern int RGB_TYPE[]; 45 | extern int RGBA_TYPE[]; 46 | extern int HSV_TYPE[]; 47 | extern int YIQ_TYPE[]; 48 | extern int LUT_TYPE[]; 49 | extern int MAT_TYPE[]; 50 | extern int FFT_TYPE[]; 51 | 52 | extern int UCHARCH_TYPE[]; 53 | extern int SHORTCH_TYPE[]; 54 | extern int INTCH_TYPE[]; 55 | extern int LONGCH_TYPE[]; 56 | extern int FLOATCH_TYPE[]; 57 | extern int DOUBLECH_TYPE[]; 58 | 59 | extern int INT2_TYPE[]; 60 | extern int FLOAT2_TYPE[]; 61 | extern int INT3_TYPE[]; 62 | extern int FLOAT3_TYPE[]; 63 | extern int INT4_TYPE[]; 64 | extern int FLOAT4_TYPE[]; 65 | 66 | extern int *CHTYPE_CH[]; 67 | extern int *CHTYPE_IMAGE[]; 68 | extern char *CHTYPE_NAME[]; 69 | extern char CHTYPE_LTR[]; 70 | 71 | extern uchar BITMASK[]; 72 | 73 | 74 | 75 | // ---------------------------------------------------------------------- 76 | // remaining global variables (may change during session) 77 | // 78 | 79 | extern int AbsVal; 80 | extern int BorderVal; 81 | extern double CubicConvA; 82 | extern int HistoFit; 83 | extern int ImagePadLen; 84 | extern int ImagePadMtd; 85 | extern double PlotScl; 86 | extern int SavePixmap; 87 | extern int Serpentine; 88 | extern int JpgQuality; 89 | extern int SwapBytes; 90 | 91 | 92 | // IPcastimg.cpp - type casting routines for images 93 | extern void IP_castImage (ImagePtr, int, ImagePtr); 94 | extern void IP_initAlphaChannel(ImagePtr, int); 95 | 96 | // IPcastmem.cpp - type casting routines for memory blocks 97 | extern void IP_castMemory (void*, int, int, void*, int, int, int); 98 | 99 | // IPcolorconv.cpp - conversion between color representations 100 | extern void IP_RGBtoYIQ1 (int, int, int, int&, int&, int&); 101 | extern void IP_YIQtoRGB1 (int, int, int, int&, int&, int&); 102 | extern void IP_RGBtoHSV1 (int, int, int, int&, int&, int&); 103 | extern void IP_HSVtoRGB1 (int, int, int, int&, int&, int&); 104 | extern void IP_clipRGB (int&, int&, int&); 105 | 106 | // IPhisto.cpp - histogram evaluation 107 | extern void IP_histogram (ImagePtr, int, int*, int, double&, double&); 108 | 109 | // IPinit.cpp - initialize global IP data structures 110 | extern void IP_init (void); 111 | 112 | // IPio.cpp - image input/output 113 | extern ImagePtr IP_readImage (const char*); 114 | extern bool IP_readImageIntoI (const char*, ImagePtr); 115 | extern bool IP_readImageDimensions(const char*, int&, int&); 116 | extern bool IP_saveImage (ImagePtr, const char*, const char*); 117 | 118 | // IPmipmap.cpp - mipmap routines 119 | extern int IP_mipmap (Image, Image&); 120 | 121 | // IPmmch.cpp - channel memory management 122 | #include "IPmmch.tpp" 123 | template 124 | bool IP_getChannel (ImagePtr, int, ChannelPtr&, int &); 125 | template 126 | void IP_copyFromRow (ChannelPtr, int, int, ChannelPtr); 127 | template 128 | void IP_copyFromRow (ImagePtr, int, int, ChannelPtr); 129 | template 130 | void IP_copyToRow (ChannelPtr, ImagePtr , int, int); 131 | template 132 | void IP_copyToRow (ChannelPtr, ChannelPtr, int, int); 133 | 134 | extern void IP_copyChannel (ImagePtr, int, ImagePtr, int ); 135 | extern void IP_copyChannelEnd (ImagePtr, int, ImagePtr); 136 | extern void IP_castChannel (ImagePtr, int, ImagePtr, int, int); 137 | extern void IP_castChannels (ImagePtr, int*,ImagePtr); 138 | extern void IP_castChannelsEq (ImagePtr, int, ImagePtr); 139 | extern void IP_castChannelsMin(ImagePtr, int, ImagePtr); 140 | extern void IP_castChannelsMax(ImagePtr, int, ImagePtr); 141 | extern void IP_clearChannel (ImagePtr, int, ImagePtr); 142 | extern int IP_checkDimensions(ImagePtr, ImagePtr); 143 | 144 | // IPmmimg.cpp 145 | extern Image *IP_allocImage (int, int, int*); 146 | extern Image *IP_allocImage_I (ImagePtr); 147 | extern void IP_allocImageInI(ImagePtr, int, int, int*); 148 | extern void IP_copyImage (ImagePtr, ImagePtr); 149 | extern void IP_copyHeader (ImagePtr, int, ImagePtr); 150 | extern void IP_copyHeader2 (ImagePtr, ImagePtr, int, ImagePtr); 151 | extern void IP_copyImageBuffer(ImagePtr, ImagePtr); 152 | 153 | 154 | // IPutil.cpp 155 | extern void IP_interleave (ImagePtr, ImagePtr); 156 | extern void IP_interleave4 (ImagePtr, int, int, int, int, ImagePtr); 157 | extern void IP_uninterleave (ImagePtr, ImagePtr); 158 | extern void IP_normalizeDimensions(ImagePtr, ImagePtr); 159 | extern void IP_crop (ImagePtr, int, int, int, int, ImagePtr); 160 | extern void IP_shift (ImagePtr, int, int, ImagePtr); 161 | extern void IP_pad (ImagePtr, int*, int, ImagePtr); 162 | extern void IP_pad1D (ChannelPtr, int, int, int, int, 163 | ChannelPtr&); 164 | extern void IP_fpad1D (ChannelPtr, int, int, int, int, 165 | ChannelPtr&); 166 | extern void IP_clearImage (ImagePtr); 167 | extern void IP_setImage (ImagePtr, double*); 168 | extern void IP_minmaxImage (ImagePtr, double&, double&); 169 | extern void IP_minmaxChannel(ImagePtr, int, double&, double&); 170 | extern void IP_RGBdecouple (ImagePtr, ImagePtr &, bool decouple=true); 171 | extern void IP_RGBcouple (ImagePtr, ImagePtr, ImagePtr); 172 | extern void IP_bailout (const char*, ...); 173 | extern void IP_clip (ImagePtr, double, double, ImagePtr); 174 | extern void IP_embedRange (ImagePtr I1, double t1, double t2, ImagePtr I2); 175 | extern void IP_scaleRange (ImagePtr I1, double t1, double t2, ImagePtr I2); 176 | // IPtoUI.cpp 177 | extern void IP_printfErr(const char *fmt, ...); 178 | 179 | } // namespace IP 180 | 181 | #endif // IP_H 182 | -------------------------------------------------------------------------------- /src/IP/win/header/IPdefs.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IPdefs.h - Header for IP symbolic constants (#defines) and globals. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \file IPdefs.h 11 | //! \brief Header for IP symbolic constants (#defines) and globals. 12 | //! \author George Wolberg, 2016 13 | 14 | #ifndef IPDEFS_H 15 | #define IPDEFS_H 16 | 17 | // ---------------------------------------------------------------------- 18 | // standard include files 19 | // 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace IP { 31 | 32 | // ---------------------------------------------------------------------- 33 | // datatype typedefs 34 | // 35 | // comment out uchar typedef because it is already defined in Qt library 36 | // typedef unsigned char uchar; 37 | 38 | 39 | 40 | // ---------------------------------------------------------------------- 41 | // math definitions 42 | // 43 | #define PI 3.1415926535897931160E0 44 | #define PI2 6.2831853071795862320E0 45 | #define PI_2 1.5707963267948965580E0 46 | #define DEGtoRAD 0.0174532927777777777E0 47 | #define RADtoDEG 57.295778666661658617E0 48 | #define NEG_INF -9999999 49 | 50 | 51 | 52 | // ---------------------------------------------------------------------- 53 | // miscellaneous definitions 54 | // 55 | #define LSB 0x0001 56 | #define MXBLUR 256 57 | #define MXCH 8192 58 | #define MXCHANNEL 16 59 | #define MXGRAY 256 60 | #define MXHALFTONE 10 61 | #define MXRES 4096 62 | #define MXSTRLEN 1024 63 | #define MXWINDOWS 16 64 | 65 | 66 | 67 | // ---------------------------------------------------------------------- 68 | // channel sizes 69 | // 70 | #define UCHAR_SZ sizeof(uchar) 71 | #define SHORT_SZ sizeof(short) 72 | #define INT_SZ sizeof(int) 73 | #define LONG_SZ sizeof(long) 74 | #define FLOAT_SZ sizeof(float) 75 | #define DOUBLE_SZ sizeof(double) 76 | 77 | 78 | 79 | // ---------------------------------------------------------------------- 80 | // pixel sizes 81 | // 82 | #define BW_PXLSZ UCHAR_SZ 83 | #define BWA_PXLSZ (2*UCHAR_SZ) 84 | #define RGB_PXLSZ (3*UCHAR_SZ) 85 | #define RGBA_PXLSZ (4*UCHAR_SZ) 86 | #define HSV_PXLSZ (3*SHORT_SZ) 87 | #define YIQ_PXLSZ (3*SHORT_SZ) 88 | 89 | 90 | 91 | // ---------------------------------------------------------------------- 92 | // useful macros 93 | // Note: ROUND rounds arg to nearest integer 94 | // Note: FLOOR rounds arg to nearest integer towards -infinity 95 | // Note: CEILING rounds arg to nearest integer towards +infinity 96 | // 97 | #define ABS(A) ((A) >= 0 ? (A) : -(A)) 98 | #define SGN(A) ((A) > 0 ? 1 : ((A) < 0 ? -1 : 0 )) 99 | #define ROUND(A) ((A) >= 0 ? (int)((A)+.5) : -(int)(.5-(A))) 100 | #define FLOOR(A) ((A)==(int)(A) ? (int)(A) : (A)>0 ? (int)(A):(int)(A)-1) 101 | #define CEILING(A) ((A)==(int)(A) ? (int)(A) : (A)>0 ? (int)(A)+1:(int)(A)) 102 | #define CLIP(A,L,H) ((A)<=(L) ? (L) : (A)<=(H) ? (A) : (H)) 103 | #define MAX(A,B) ((A) > (B) ? (A) : (B)) 104 | #define MIN(A,B) ((A) < (B) ? (A) : (B)) 105 | #define SWAP(A,B) { double temp=(A); (A) = (B); (B) = temp; } 106 | #define SWAP_INT(A,B) { (A) ^= (B); (B) ^= (A); (A) ^= (B); } 107 | 108 | #define NEWIMAGE IP_allocImage(0, 0, NULL_TYPE) 109 | #define IP_copyImageHeader(I1, I2) IP_copyHeader(I1, 1, I2) 110 | #define IP_copyImageHeaderOnly(I1, I2) IP_copyHeader(I1, 0, I2) 111 | #define IP_copyImageHeader2(I1, I2, I3) IP_copyHeader2(I1, I2, 1, I3) 112 | #define IP_copyImageHeaderOnly2(I1, I2, I3) IP_copyHeader2(I1, I2, 0, I3) 113 | 114 | 115 | 116 | // ---------------------------------------------------------------------- 117 | // type casting macro: 118 | // cast total objects in p1 (of type t1) into p2 (with type t2) 119 | // with strides s1 and s2, respectively 120 | // 121 | #define MEM_CAST(p1, t1, s1, p2, t2, s2, total)\ 122 | {\ 123 | t1 *src;\ 124 | t2 *dst;\ 125 | int i;\ 126 | src = (t1 *) p1;\ 127 | dst = (t2 *) p2;\ 128 | for(i=0; i 33 | inline bool 34 | IP_getChannel(ImagePtr I, int ch, ChannelPtr &ptr, int &type) 35 | { 36 | if(ch<0 || ch>MXCHANNEL) { 37 | fprintf(stderr, "IP_getChannel: Illegal channel %d\n", ch); 38 | return false; 39 | } 40 | if(ch>=I->maxChannel()) { 41 | return false; 42 | } 43 | 44 | ptr = I[ch]; 45 | type = I->channelType(ch); 46 | return true; 47 | } 48 | 49 | 50 | 51 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 52 | // IP_copyFromRow: 53 | // 54 | // Copy a row of an image channel to an output channel. 55 | //! \brief Copy a row of an image channel to an output channel. 56 | //! \param[in] p - Input channel pointer. 57 | //! \param[in] row - Row index. 58 | //! \param[in] w - Row width. 59 | //! \param[out] q - Output channel pointer. 60 | // 61 | template 62 | inline void 63 | IP_copyFromRow(ChannelPtr p, int row, int w, ChannelPtr q) 64 | { 65 | p += row * w; 66 | for(int i=0; i(p[i]); 68 | } 69 | 70 | 71 | 72 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | // IP_copyFromRow: 74 | // 75 | // Copy a row of an image to a channel (See IPfft.cpp). 76 | //! \brief Copy a row of an image to a channel (See IPfft.cpp). 77 | //! \param[in] I - Input image. 78 | //! \param[in] ch - Input channel index. 79 | //! \param[in] row - Input row index. 80 | //! \param[out] p - Output channel. 81 | // 82 | template 83 | inline void 84 | IP_copyFromRow(ImagePtr I, int ch, int row, ChannelPtr p) 85 | { 86 | int w = I->width(); 87 | int type = I->channelType(ch); 88 | 89 | switch(type) { 90 | case UCHAR_TYPE: 91 | { 92 | ChannelPtr q; 93 | IP_getChannel(I, ch, q, type); 94 | IP_copyFromRow(q, row, w, p); 95 | break; 96 | } 97 | case SHORT_TYPE: 98 | { 99 | ChannelPtr q; 100 | IP_getChannel(I, ch, q, type); 101 | IP_copyFromRow(q, row, w, p); 102 | break; 103 | } 104 | case INT_TYPE: 105 | { 106 | ChannelPtr q; 107 | IP_getChannel(I, ch, q, type); 108 | IP_copyFromRow(q, row, w, p); 109 | break; 110 | } 111 | case LONG_TYPE: 112 | { 113 | ChannelPtr q; 114 | IP_getChannel(I, ch, q, type); 115 | IP_copyFromRow(q, row, w, p); 116 | break; 117 | } 118 | case FLOAT_TYPE: 119 | { 120 | ChannelPtr q; 121 | IP_getChannel(I, ch, q, type); 122 | IP_copyFromRow(q, row, w, p); 123 | break; 124 | } 125 | case DOUBLE_TYPE: 126 | { 127 | ChannelPtr q; 128 | IP_getChannel(I, ch, q, type); 129 | IP_copyFromRow(q, row, w, p); 130 | break; 131 | } 132 | } 133 | } 134 | 135 | 136 | 137 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 138 | // IP_copyToRow: 139 | // 140 | // Copy a channel to a row of an image channel. 141 | //! \brief Copy a channel to a row of an image channel. 142 | //! \param[in] p - Input channel pointer. 143 | //! \param[out] q - Output channel pointer. 144 | //! \param[in] row - Row index. 145 | //! \param[in] w - Row width. 146 | // 147 | template 148 | inline void 149 | IP_copyToRow(ChannelPtr p, ChannelPtr q, int row, int w) 150 | { 151 | q += row * w; 152 | for(int i=0; i(p[i]); 154 | } 155 | 156 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 157 | // IP_copyToRow: 158 | // 159 | // Copy a channel's data into a row of an image (See IPfft.cpp). 160 | //! \brief Copy a channel's data into a row of an image (See IPfft.cpp). 161 | //! \param[in] p - Input channel. 162 | //! \param[out] I - Output image. 163 | //! \param[in] ch - Output channel index. 164 | //! \param[in] row - Output row index. 165 | // 166 | template 167 | inline void 168 | IP_copyToRow(ChannelPtr p, ImagePtr I, int ch, int row) 169 | { 170 | int w = I->width(); 171 | int type = I->channelType(ch); 172 | 173 | switch(type) { 174 | case UCHAR_TYPE: 175 | { 176 | ChannelPtr q; 177 | IP_getChannel(I, ch, q, type); 178 | IP_copyToRow(p, q, row, w); 179 | break; 180 | } 181 | case SHORT_TYPE: 182 | { 183 | ChannelPtr q; 184 | IP_getChannel(I, ch, q, type); 185 | IP_copyToRow(p, q, row, w); 186 | break; 187 | } 188 | case INT_TYPE: 189 | { 190 | ChannelPtr q; 191 | IP_getChannel(I, ch, q, type); 192 | IP_copyToRow(p, q, row, w); 193 | break; 194 | } 195 | case LONG_TYPE: 196 | { 197 | ChannelPtr q; 198 | IP_getChannel(I, ch, q, type); 199 | IP_copyToRow(p, q, row, w); 200 | break; 201 | } 202 | case FLOAT_TYPE: 203 | { 204 | ChannelPtr q; 205 | IP_getChannel(I, ch, q, type); 206 | IP_copyToRow(p, q, row, w); 207 | break; 208 | } 209 | case DOUBLE_TYPE: 210 | { 211 | ChannelPtr q; 212 | IP_getChannel(I, ch, q, type); 213 | IP_copyToRow(p, q, row, w); 214 | } 215 | } 216 | } 217 | //@} 218 | -------------------------------------------------------------------------------- /src/IP/win/header/IPtoUI.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // IPtoUI.h - Header for IPtoUI.cpp file 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | //! \mainpage Image Processing Package 11 | //! \author George Wolberg 12 | //! \date 2016 13 | //! \par References: 14 | //! This code is part of the 15 | //! IMPROC Image Processing Software Package\n 16 | //! Copyright © 2016 by George Wolberg 17 | 18 | //! \file IPtoUI.h 19 | //! \brief Image Processing Package header file for IPtoUI.cpp 20 | //! \author George Wolberg, 2016 21 | 22 | #ifndef IPTOUI_H 23 | #define IPTOUI_H 24 | 25 | namespace IP { 26 | 27 | extern void IP_QImageToIP(const QImage&, ImagePtr &); 28 | extern void IP_IPtoQImage(const ImagePtr&, QImage &); 29 | 30 | } // namespace IP 31 | 32 | #endif // IPTOUI_H 33 | -------------------------------------------------------------------------------- /src/IP/win/lib/IP.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/src/IP/win/lib/IP.lib -------------------------------------------------------------------------------- /src/IP/win/lib/IP_d.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephanlin/image-processing-application/ccab2e3300005b564e28956a1fc1ad47357cc5ec/src/IP/win/lib/IP_d.lib -------------------------------------------------------------------------------- /src/ImageFilter.cpp: -------------------------------------------------------------------------------- 1 | // =============================================================== 2 | // Computer Graphics Homework Solutions 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // ImageFilter.cpp - ImageFilter class. Base class of homework solutions. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // =============================================================== 9 | 10 | #include "ImageFilter.h" 11 | 12 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13 | // HW::HW: 14 | // 15 | // HW constructor. 16 | // This is base class for homework solutions that will replace 17 | // the control panel, reset function, and add homework solution. 18 | // 19 | ImageFilter::ImageFilter(QWidget *parent) 20 | : QWidget(parent), m_shaderFlag(false) 21 | {} 22 | 23 | 24 | 25 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | // ImageFilter::controlPanel: 27 | // 28 | // Create a control panel of widgets for homework solution. 29 | // 30 | QGroupBox* 31 | ImageFilter::controlPanel() 32 | { 33 | return NULL; 34 | } 35 | 36 | 37 | 38 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | // ImageFilter::applyFilter: 40 | // 41 | // Run filter on the image, transforming I1 to I2. 42 | // Return 1 for success, 0 for failure. 43 | // 44 | bool 45 | ImageFilter::applyFilter(ImagePtr, bool, ImagePtr) 46 | { 47 | return true; 48 | } 49 | 50 | 51 | 52 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | // ImageFilter::reset: 54 | // 55 | // Reset parameters in control panel. 56 | // 57 | void 58 | ImageFilter::reset() {} 59 | 60 | 61 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 62 | // ImageFilter::initShader: 63 | // 64 | // init shader program and parameters. 65 | // 66 | void 67 | ImageFilter::initShader() {} 68 | 69 | 70 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 71 | // ImageFilter::gpuProgram: 72 | // 73 | // Active gpu program 74 | // 75 | void 76 | ImageFilter::gpuProgram(int) {} 77 | -------------------------------------------------------------------------------- /src/ImageFilter.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // Computer Graphics Homework Solutions 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // ImageFilter.h - Header file for ImageFilter class. Base class of homework solutions. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef IMAGEFILTER_H 11 | #define IMAGEFILTER_H 12 | 13 | #include 14 | #include "GLWidget.h" 15 | #include "IP.h" 16 | using namespace IP; 17 | 18 | enum { PASS1, PASS2, ONEPASS }; 19 | // ---------------------------------------------------------------------- 20 | // standard include files 21 | // 22 | class ImageFilter : public QWidget, protected QGLFunctions { 23 | 24 | public: 25 | ImageFilter(QWidget *parent = 0); 26 | virtual QGroupBox* controlPanel (); // create control panel 27 | virtual bool applyFilter (ImagePtr, bool, ImagePtr); // filter input image -> make output 28 | virtual void reset (); // reset parameters 29 | virtual void initShader (); 30 | virtual void gpuProgram (int pass); // use GPU program to apply filter 31 | bool gpuImplemented() { return m_shaderFlag;} 32 | int gpuPasses () { return m_nPasses;} 33 | 34 | protected: 35 | bool m_shaderFlag; // true if the shaders are initialized 36 | QGLShaderProgram m_program[MXPROGRAMS]; // GLSL programs 37 | GLint m_uniform[MXPROGRAMS][MXUNIFORMS]; // uniform vars for each program 38 | int m_nPasses; // number of GPU passes 39 | }; 40 | 41 | #endif // IMAGEFILTER_H 42 | -------------------------------------------------------------------------------- /src/MainWindow.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // Computer Graphics Homework Solutions 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // MainWindow.h - Header file for MainWindow class 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef MAINWINDOW_H 11 | #define MAINWINDOW_H 12 | 13 | // ---------------------------------------------------------------------- 14 | // standard include files 15 | // 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "IP.h" 30 | #include "IPtoUI.h" 31 | #include "ImageFilter.h" 32 | #include "qcustomplot.h" 33 | #include "GLWidget.h" 34 | 35 | #define MAXFILTERS 50 36 | enum { 37 | DUMMY, THRESHOLD, CLIP, QUANTIZE, GAMMA, CONTRAST, HISTOSTRETCH, HISTOMATCH, 38 | ERRDIFFUSION, BLUR, SHARPEN, MEDIAN, CONVOLVE, CORRELATION 39 | }; 40 | using namespace IP; 41 | 42 | class MainWindow : public QMainWindow { 43 | Q_OBJECT 44 | 45 | public: 46 | // constructor 47 | MainWindow (QWidget *parent = 0); 48 | ImagePtr imageSrc () const; 49 | ImagePtr imageDst () const; 50 | ImagePtr imageIn () const; 51 | void setImageDst (ImagePtr I) { 52 | if(m_radioMode[1]->isChecked()) 53 | IP_castImage(I, BW_IMAGE, I); 54 | m_imageDst = I; 55 | } 56 | QCustomPlot* histogram () 57 | {return m_histogram;} 58 | GLWidget* glw () 59 | {return m_glw;} 60 | void preview (); 61 | bool gpuFlag () 62 | { return m_checkboxGPU->checkState() == Qt::Checked; } 63 | bool timeFlag () 64 | { return m_checkboxTime->checkState() == Qt::Checked; } 65 | void gpuProgram (int pass) 66 | { m_imageFilter[m_code]->gpuProgram(pass); } 67 | int gpuPasses () 68 | { return m_imageFilter[m_code]->gpuPasses(); } 69 | ImageFilter* imageFilter(int i) 70 | { return m_imageFilter[i]; } 71 | bool isInput () 72 | { return m_radioDisplay[0]->isChecked();} 73 | int glFrameW() { return m_glwFrameW; } 74 | int glFrameH() { return m_glwFrameH; } 75 | 76 | public slots: 77 | void open (); 78 | void save (); 79 | void displayIn (); 80 | void displayOut (); 81 | void modeRGB (); 82 | void modeGray (); 83 | void reset (); 84 | void quit (); 85 | void time (); 86 | void execute (QAction*); 87 | 88 | 89 | protected slots: 90 | void setHisto (int); 91 | void setTime (int); 92 | void setGPU (int); 93 | void resizeEvent (QResizeEvent*); 94 | 95 | 96 | protected: 97 | void createActions (); 98 | void createMenus (); 99 | void createWidgets (); 100 | QGroupBox* createGroupPanel(); 101 | QFrame* createGroupDisplay (); 102 | QGroupBox* createDisplayButtons(); 103 | QGroupBox* createModeButtons (); 104 | QGroupBox* createOptionButtons (); 105 | QHBoxLayout* createExitButtons (); 106 | void displayHistogram(ImagePtr); 107 | void display (int); 108 | void mode (int); 109 | 110 | 111 | private: 112 | // menus 113 | QMenu* m_menuFile; 114 | QMenu* m_menuPtOps; 115 | QMenu* m_menuNbrOps; 116 | 117 | // point ops actions 118 | QAction* m_actionOpen; 119 | QAction* m_actionSave; 120 | QAction* m_actionQuit; 121 | QAction* m_actionThreshold ; 122 | QAction* m_actionClip ; 123 | QAction* m_actionQuantize ; 124 | QAction* m_actionGamma ; 125 | QAction* m_actionContrast ; 126 | QAction* m_actionHistoStretch; 127 | QAction* m_actionHistoMatch ; 128 | 129 | // neighborhood ops actions 130 | QAction* m_actionErrDiffusion; 131 | QAction* m_actionBlur ; 132 | QAction* m_actionSharpen ; 133 | QAction* m_actionMedian ; 134 | QAction* m_actionConvolve ; 135 | QAction* m_actionCorrelation ; 136 | 137 | 138 | // homework objects 139 | ImageFilter* m_imageFilter[MAXFILTERS]; 140 | 141 | // widgets for control panel groupbox 142 | QGroupBox* m_groupBoxPanels; // group box for control panel 143 | QStackedWidget* m_stackWidgetPanels; // stacked widget for control panels 144 | 145 | // widgets for image display groupbox 146 | QFrame* m_glwFrame; // pointer to frame that holds glwidget 147 | QRadioButton* m_radioDisplay[2]; // radio buttons for input/output 148 | QRadioButton* m_radioMode [2]; // radio buttons for RGB/Gray modes 149 | QCheckBox* m_checkboxHisto; // checkbox: histogram display 150 | QCheckBox* m_checkboxTime; // checkbox: compute timings 151 | QCheckBox* m_checkboxGPU; // checkbox: GPU acceleration 152 | QLabel* m_labelTime; // label for timing 153 | QWidget* m_extension; // extension widget for histogram 154 | QCustomPlot* m_histogram; // histogram plot 155 | 156 | int m_width; // image width 157 | int m_height; // image height 158 | int m_code; // code (index) of triggered action 159 | QString m_file; // input image filename 160 | QString m_currentDir; // input image directory 161 | ImagePtr m_imageIn; // input image (raw) 162 | ImagePtr m_imageSrc; // input image (processed) 163 | ImagePtr m_imageDst; // output image 164 | 165 | // histogram variables 166 | int m_histoColor; // histo color id: 0=RGB,1=R,2=G,3=B,4=gray 167 | double m_histoXmin[4]; // xmin for all histogram channels 168 | double m_histoXmax[4]; // xmax for all histogram channels 169 | double m_histoYmin[4]; // ymin for all histogram channels 170 | double m_histoYmax[4]; // ymax for all histogram channels 171 | GLWidget *m_glw; 172 | int m_glwFrameW; 173 | int m_glwFrameH; 174 | }; 175 | 176 | 177 | 178 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 179 | // MainWindow::imageSrc: 180 | // 181 | // Source image. 182 | // 183 | inline ImagePtr 184 | MainWindow::imageSrc() const 185 | { 186 | return m_imageSrc; 187 | } 188 | 189 | 190 | 191 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 192 | // MainWindow::imageDst: 193 | // 194 | // Destination image. 195 | // 196 | inline ImagePtr 197 | MainWindow::imageDst() const 198 | { 199 | return m_imageDst; 200 | } 201 | 202 | 203 | 204 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 205 | // MainWindow::imageIn: 206 | // 207 | // Input image. 208 | // 209 | inline ImagePtr 210 | MainWindow::imageIn() const 211 | { 212 | return m_imageIn; 213 | } 214 | 215 | #endif // MAINWINDOW_H 216 | -------------------------------------------------------------------------------- /src/Median.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Median.cpp - Median widget. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Median.h" 12 | #include "ops_neighborhood/HW_median.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | enum { WSIZE, STEPX, STEPY, SAMPLER }; 16 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | // Median::Median: 18 | // 19 | // Constructor. 20 | // 21 | Median::Median(QWidget *parent) : ImageFilter(parent) 22 | {} 23 | 24 | 25 | 26 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | // Median::controlPanel: 28 | // 29 | // Create group box for control panel. 30 | // 31 | QGroupBox* 32 | Median::controlPanel() 33 | { 34 | // init group box 35 | m_ctrlGrp = new QGroupBox("Median"); 36 | 37 | // layout for assembling filter widget 38 | QGridLayout *layout = new QGridLayout; 39 | 40 | // alloc array of labels 41 | QLabel *label[2]; 42 | 43 | // create sliders and spinboxes 44 | for(int i=0; i<2; i++) { 45 | // create label[i] 46 | label[i] = new QLabel(m_ctrlGrp); 47 | if(!i) label[i]->setText("Filter size"); 48 | else label[i]->setText("Iterations"); 49 | 50 | if(!i) { 51 | // create slider 52 | m_slider [i] = new QSlider(Qt::Horizontal, m_ctrlGrp); 53 | m_slider [i]->setRange(3, 9); 54 | m_slider [i]->setValue(3); 55 | m_slider [i]->setSingleStep(2); 56 | m_slider [i]->setTickInterval(1); 57 | m_slider [i]->setTickPosition(QSlider::TicksBelow); 58 | 59 | // create spinbox 60 | m_spinBox[i] = new QSpinBox(m_ctrlGrp); 61 | m_spinBox[i]->setRange(3, 9); 62 | m_spinBox[i]->setValue(3); 63 | m_spinBox[i]->setSingleStep(2); 64 | } else { 65 | // create slider 66 | m_slider [i] = new QSlider(Qt::Horizontal, m_ctrlGrp); 67 | m_slider [i]->setRange(1, 20); 68 | m_slider [i]->setValue(1); 69 | m_slider [i]->setSingleStep(1); 70 | m_slider [i]->setTickInterval(2); 71 | m_slider [i]->setTickPosition(QSlider::TicksBelow); 72 | 73 | // create spinbox 74 | m_spinBox[i] = new QSpinBox(m_ctrlGrp); 75 | m_spinBox[i]->setRange(1, 20); 76 | m_spinBox[i]->setValue(1); 77 | m_spinBox[i]->setSingleStep(1); 78 | } 79 | 80 | // assemble dialog 81 | layout->addWidget(label [i], i, 0); 82 | layout->addWidget(m_slider [i], i, 1); 83 | layout->addWidget(m_spinBox[i], i, 2); 84 | } 85 | 86 | // init signal/slot connections 87 | connect(m_slider [0], SIGNAL(valueChanged(int)), this, SLOT(changeSize(int))); 88 | connect(m_spinBox[0], SIGNAL(valueChanged(int)), this, SLOT(changeSize(int))); 89 | connect(m_slider [1], SIGNAL(valueChanged(int)), this, SLOT(changeItrs(int))); 90 | connect(m_spinBox[1], SIGNAL(valueChanged(int)), this, SLOT(changeItrs(int))); 91 | 92 | // assign layout to group box 93 | m_ctrlGrp->setLayout(layout); 94 | 95 | return(m_ctrlGrp); 96 | } 97 | 98 | 99 | 100 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 | // Median::applyFilter: 102 | // 103 | // Run filter on the image, transforming I1 to I2. 104 | // Overrides ImageFilter::applyFilter(). 105 | // Return 1 for success, 0 for failure. 106 | // 107 | bool 108 | Median::applyFilter(ImagePtr I1, bool gpuFlag, ImagePtr I2) 109 | { 110 | // error checking 111 | if(I1.isNull()) return 0; 112 | 113 | // collect parameters 114 | int size = m_slider[0]->value(); // filter size 115 | int itrs = m_slider[1]->value(); // iterations 116 | m_width = I1->width(); 117 | m_height = I1->height(); 118 | // apply median filter 119 | if(!(gpuFlag && m_shaderFlag)) 120 | if(itrs == 1) { 121 | median(I1, size, I2); 122 | } else { 123 | IP_copyImage(I1, I2); 124 | for(int i=0; iglw()->applyFilterGPU(m_nPasses); 128 | 129 | 130 | return 1; 131 | } 132 | 133 | 134 | 135 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 136 | // Median::median: 137 | // 138 | // Apply median filter on image I1. Median filter has size sz x sz. 139 | // Output is in I2. 140 | // 141 | void 142 | Median::median(ImagePtr I1, int sz, ImagePtr I2) 143 | { 144 | HW_median(I1, sz, I2); 145 | } 146 | 147 | 148 | 149 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 150 | // Median::changeSize: 151 | // 152 | // Slot to process change in median filter size caused by moving the slider. 153 | // 154 | void 155 | Median::changeSize(int value) 156 | { 157 | m_slider [0]->blockSignals(true); 158 | m_slider [0]->setValue (value); 159 | m_slider [0]->blockSignals(false); 160 | m_spinBox[0]->blockSignals(true); 161 | m_spinBox[0]->setValue (value); 162 | m_spinBox[0]->blockSignals(false); 163 | 164 | // apply filter to source image and display result 165 | g_mainWindowP->preview(); 166 | } 167 | 168 | 169 | 170 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 171 | // Median::changeItrs: 172 | // 173 | // Slot to process change in iterations caused by moving the slider. 174 | // 175 | void 176 | Median::changeItrs(int value) 177 | { 178 | m_slider [1]->blockSignals(true); 179 | m_slider [1]->setValue (value); 180 | m_slider [1]->blockSignals(false); 181 | m_spinBox[1]->blockSignals(true); 182 | m_spinBox[1]->setValue (value); 183 | m_spinBox[1]->blockSignals(false); 184 | 185 | // apply filter to source image and display result 186 | g_mainWindowP->preview(); 187 | } 188 | 189 | 190 | 191 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 192 | // Median::reset: 193 | // 194 | // Reset parameters. 195 | // 196 | void 197 | Median::reset() 198 | { 199 | m_slider[0]->setValue(3); 200 | m_slider[1]->setValue(1); 201 | 202 | // apply filter to source image and display result 203 | g_mainWindowP->preview(); 204 | } 205 | 206 | 207 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 208 | // Median::initShader: 209 | // 210 | // init shader program and parameters. 211 | // 212 | void 213 | Median::initShader() 214 | { 215 | 216 | m_shaderFlag = false; 217 | } 218 | 219 | 220 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 221 | // Median::gpuProgram: 222 | // 223 | // Active gpu program 224 | // 225 | void 226 | Median::gpuProgram(int pass) 227 | { 228 | 229 | } 230 | -------------------------------------------------------------------------------- /src/Median.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Median.h - Median widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef MEDIAN_H 11 | #define MEDIAN_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Median : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Median (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void median (ImagePtr, int, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeSize (int); 29 | void changeItrs (int); 30 | 31 | private: 32 | // widgets 33 | QSlider* m_slider [2]; // Median sliders 34 | QSpinBox* m_spinBox[2]; // Median spin boxes 35 | QGroupBox* m_ctrlGrp; // groupbox for panel 36 | int m_width; // input image width 37 | int m_height; // input image height 38 | }; 39 | 40 | #endif // MEDIAN_H 41 | -------------------------------------------------------------------------------- /src/Quantize.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Quantize.cpp - Quantize class 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Quantize.h" 12 | #include "ops_point/HW_quantize.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | enum { LEVELS, DITHER, SAMPLER }; 16 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | // Quantize::Quantize: 18 | // 19 | // Constructor. 20 | // 21 | Quantize::Quantize(QWidget *parent) : ImageFilter(parent) 22 | {} 23 | 24 | 25 | 26 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | // Quantize::controlPanel: 28 | // 29 | // Create group box for control panel. 30 | // 31 | QGroupBox* 32 | Quantize::controlPanel() 33 | { 34 | // init group box 35 | m_ctrlGrp = new QGroupBox("Quantize"); 36 | 37 | // create label 38 | QLabel *label = new QLabel("Levels"); 39 | 40 | // create slider 41 | m_slider = new QSlider(Qt::Horizontal, m_ctrlGrp); 42 | m_slider->setRange(2, MXGRAY>>1); 43 | m_slider->setValue(MXGRAY>>6); 44 | m_slider->setTickPosition(QSlider::TicksBelow); 45 | m_slider->setTickInterval(25); 46 | 47 | // create spinbox 48 | m_spinBox = new QSpinBox(m_ctrlGrp); 49 | m_spinBox->setRange(2, MXGRAY>>1); 50 | m_spinBox->setValue(MXGRAY>>6); 51 | 52 | // create checkbox 53 | m_checkBox = new QCheckBox("Dither Signal"); 54 | m_checkBox-> setCheckState( Qt::Unchecked ); 55 | 56 | // init signal/slot connections for Quantize 57 | connect(m_slider , SIGNAL(valueChanged(int)), this, SLOT(changeLevels(int))); 58 | connect(m_spinBox , SIGNAL(valueChanged(int)), this, SLOT(changeLevels(int))); 59 | connect(m_checkBox, SIGNAL(stateChanged(int)), this, SLOT(ditherSignal(int))); 60 | 61 | // assemble dialog 62 | QGridLayout *layout = new QGridLayout; 63 | layout->addWidget( label , 0, 0); 64 | layout->addWidget(m_slider , 0, 1); 65 | layout->addWidget(m_spinBox, 0, 2); 66 | layout->addWidget(m_checkBox,1, 0, 1, 3, Qt::AlignLeft); 67 | 68 | // assign layout to group box 69 | m_ctrlGrp->setLayout(layout); 70 | 71 | return(m_ctrlGrp); 72 | } 73 | 74 | 75 | 76 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 77 | // Quantize::applyFilter: 78 | // 79 | // Run filter on the image, transforming I1 to I2. 80 | // Overrides ImageFilter::applyFilter(). 81 | // Return 1 for success, 0 for failure. 82 | // 83 | bool 84 | Quantize::applyFilter(ImagePtr I1, bool gpuFlag, ImagePtr I2) 85 | { 86 | // error checking 87 | if(I1.isNull()) return 0; 88 | 89 | // get threshold value 90 | int levels = m_slider->value(); 91 | 92 | // error checking 93 | if(levels < 2 || levels > MXGRAY) return 0; 94 | 95 | // get dither flag 96 | bool dither = 0; 97 | if(m_checkBox->checkState() == Qt::Checked) 98 | dither = 1; 99 | 100 | // apply filter 101 | if(!(gpuFlag && m_shaderFlag)) 102 | // apply CPU based filter 103 | quantize(I1, levels, dither, I2); 104 | else 105 | g_mainWindowP->glw()->applyFilterGPU(m_nPasses); 106 | return 1; 107 | } 108 | 109 | 110 | 111 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 112 | // Quantize::quantize: 113 | // 114 | // Quantize I1 to specified number of levels. Apply dither if flag is set. 115 | // Output is in I2. 116 | // 117 | void 118 | Quantize::quantize(ImagePtr I1, int levels, bool dither, ImagePtr I2) 119 | { 120 | HW_quantize(I1, levels, dither, I2); 121 | } 122 | 123 | 124 | 125 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 126 | // Quantize::changeLevels: 127 | // 128 | // Slot to process change in levels caused by moving the slider. 129 | // 130 | void 131 | Quantize::changeLevels(int levels) 132 | { 133 | // set slider and spinbox to same value 134 | m_slider ->blockSignals(true); 135 | m_slider ->setValue (levels); 136 | m_slider ->blockSignals(false); 137 | m_spinBox->blockSignals(true); 138 | m_spinBox->setValue (levels); 139 | m_spinBox->blockSignals(false); 140 | 141 | // apply filter and display output 142 | g_mainWindowP->preview(); 143 | } 144 | 145 | 146 | 147 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 148 | // Quantize::ditherSignal: 149 | // 150 | // Slot to process the checkbox that enables/disables the use of a 151 | // dither signal prior to quantization. 152 | // 153 | void 154 | Quantize::ditherSignal(int flag) 155 | { 156 | int checkState = m_checkBox->checkState(); 157 | 158 | if(flag && checkState != Qt::Checked) 159 | m_checkBox->setCheckState (Qt::Checked); 160 | else if(!flag && checkState == Qt::Checked) 161 | m_checkBox->setCheckState (Qt::Unchecked); 162 | 163 | // apply filter and display output 164 | g_mainWindowP->preview(); 165 | } 166 | 167 | 168 | 169 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 170 | // Quantize::reset: 171 | // 172 | // Reset parameters. 173 | // 174 | void 175 | Quantize::reset() 176 | { 177 | // reset parameters 178 | int levels = MXGRAY>>6; 179 | m_slider ->blockSignals(true); 180 | m_slider ->setValue (levels); 181 | m_slider ->blockSignals(false); 182 | m_spinBox->blockSignals(true); 183 | m_spinBox->setValue (levels); 184 | m_spinBox->blockSignals(false); 185 | m_checkBox->setCheckState(Qt::Unchecked); 186 | 187 | // apply filter and display output 188 | g_mainWindowP->preview(); 189 | } 190 | 191 | 192 | 193 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194 | // Quantize::initShader: 195 | // 196 | // init shader program and parameters. 197 | // 198 | void 199 | Quantize::initShader() 200 | { 201 | 202 | m_nPasses = 1; 203 | // initialize GL function resolution for current context 204 | initializeGLFunctions(); 205 | 206 | UniformMap uniforms; 207 | 208 | // init uniform hash table based on uniform variable names and location IDs 209 | uniforms["u_Levels" ] = LEVELS; 210 | uniforms["u_Dither" ] = DITHER; 211 | uniforms["u_Sampler"] = SAMPLER; 212 | 213 | QString v_name = ":/vshader_passthrough"; 214 | QString f_name = ":/ops_point/fshader_quantize"; 215 | 216 | #ifdef __APPLE__ 217 | v_name += "_Mac"; 218 | f_name += "_Mac"; 219 | #endif 220 | 221 | // compile shader, bind attribute vars, link shader, and initialize uniform var table 222 | g_mainWindowP->glw()->initShader(m_program[PASS1], 223 | v_name + ".glsl", 224 | f_name + ".glsl", 225 | uniforms, 226 | m_uniform[PASS1]); 227 | m_shaderFlag = true; 228 | } 229 | 230 | 231 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 232 | // Quantize::gpuProgram: 233 | // 234 | // Active gpu program 235 | // 236 | void 237 | Quantize::gpuProgram(int pass) 238 | { 239 | glUseProgram(m_program[pass].programId()); 240 | glUniform1f (m_uniform[pass][LEVELS], m_slider->value()); 241 | glUniform1i (m_uniform[pass][DITHER], m_checkBox->checkState() == Qt::Checked); 242 | glUniform1i (m_uniform[pass][SAMPLER], 0); 243 | } -------------------------------------------------------------------------------- /src/Quantize.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Quantize.h - Quantize widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef QUANTIZE_H 11 | #define QUANTIZE_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | 16 | class Quantize : public ImageFilter { 17 | Q_OBJECT 18 | 19 | public: 20 | Quantize (QWidget *parent = 0); // constructor 21 | QGroupBox* controlPanel (); // create control panel 22 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 23 | void reset (); // reset parameters 24 | void quantize (ImagePtr, int, bool, ImagePtr); 25 | void initShader(); 26 | void gpuProgram(int pass); // use GPU program to apply filter 27 | 28 | protected slots: 29 | void changeLevels (int); 30 | void ditherSignal (int); 31 | 32 | private: 33 | // widgets 34 | QSlider* m_slider ; // Quantize slider 35 | QSpinBox* m_spinBox; // Quantize spin box 36 | QCheckBox* m_checkBox; // Quantize checkbox 37 | QGroupBox* m_ctrlGrp; // Groupbox for panel 38 | }; 39 | 40 | #endif // QUANTIZE_H 41 | -------------------------------------------------------------------------------- /src/Sharpen.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Sharpen.h - Sharpen widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef SHARPEN_H 11 | #define SHARPEN_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | class Sharpen : public ImageFilter { 16 | Q_OBJECT 17 | 18 | public: 19 | Sharpen (QWidget *parent = 0); // constructor 20 | QGroupBox* controlPanel (); // create control panel 21 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 22 | void reset (); // reset parameters 23 | void sharpen (ImagePtr, int, double, ImagePtr); 24 | void initShader(); 25 | void gpuProgram(int pass); // use GPU program to apply filter 26 | 27 | protected slots: 28 | void changeSize (int); 29 | void changeFactor (int); 30 | 31 | private: 32 | // widgets 33 | QSlider* m_slider [2]; // Blur sliders 34 | QSpinBox* m_spinBox[2]; // Blur spin boxes 35 | QGroupBox* m_ctrlGrp; // groupbox for panel 36 | int m_width; // input image width 37 | int m_height; // input image height 38 | }; 39 | 40 | #endif // SHARPEN_H 41 | -------------------------------------------------------------------------------- /src/Threshold.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Threshold.cpp - Threshold class 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | #include "Threshold.h" 12 | #include "ops_point/HW_threshold.cpp" 13 | 14 | extern MainWindow *g_mainWindowP; 15 | 16 | 17 | // uniform ID 18 | enum { THR, SAMPLER }; 19 | 20 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | // Threshold::Threshold: 22 | // 23 | // Constructor. 24 | // 25 | Threshold::Threshold(QWidget *parent) : ImageFilter(parent) 26 | {} 27 | 28 | 29 | 30 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 31 | // Threshold::controlPanel: 32 | // 33 | // Create group box for control panel. 34 | // 35 | QGroupBox* 36 | Threshold::controlPanel() 37 | { 38 | // init group box 39 | m_ctrlGrp = new QGroupBox("Threshold"); 40 | 41 | // create label 42 | QLabel *label = new QLabel("Thr"); 43 | 44 | // create slider 45 | m_slider = new QSlider(Qt::Horizontal, m_ctrlGrp); 46 | m_slider->setRange(1, MXGRAY); 47 | m_slider->setValue(MXGRAY>>1); 48 | m_slider->setTickPosition(QSlider::TicksBelow); 49 | m_slider->setTickInterval(25); 50 | 51 | // create spinbox 52 | m_spinBox = new QSpinBox(m_ctrlGrp); 53 | m_spinBox->setRange(1, MXGRAY); 54 | m_spinBox->setValue(MXGRAY>>1); 55 | 56 | // init signal/slot connections for Threshold 57 | connect(m_slider , SIGNAL(valueChanged(int)), this, SLOT(changeThr(int))); 58 | connect(m_spinBox, SIGNAL(valueChanged(int)), this, SLOT(changeThr(int))); 59 | 60 | // assemble dialog 61 | QGridLayout *layout = new QGridLayout; 62 | layout->addWidget( label , 0, 0); 63 | layout->addWidget(m_slider , 0, 1); 64 | layout->addWidget(m_spinBox, 0, 2); 65 | 66 | // assign layout to group box 67 | m_ctrlGrp->setLayout(layout); 68 | 69 | return(m_ctrlGrp); 70 | } 71 | 72 | 73 | 74 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 | // Threshold::applyFilter: 76 | // 77 | // Run filter on the image, transforming I1 to I2. 78 | // Overrides ImageFilter::applyFilter(). 79 | // Return 1 for success, 0 for failure. 80 | // 81 | bool 82 | Threshold::applyFilter(ImagePtr I1, bool gpuFlag, ImagePtr I2) 83 | { 84 | // error checking 85 | if(I1.isNull()) return 0; 86 | 87 | // get threshold value 88 | int thr = m_slider->value(); 89 | 90 | // error checking 91 | if(thr < 0 || thr > MXGRAY) return 0; 92 | 93 | if(!(gpuFlag && m_shaderFlag)) 94 | // apply CPU based filter 95 | threshold(I1, thr, I2); 96 | else 97 | g_mainWindowP->glw()->applyFilterGPU(m_nPasses); 98 | 99 | return 1; 100 | } 101 | 102 | 103 | 104 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | // Threshold::threshold: 106 | // 107 | // Threshold I1 using threshold thr. Output is in I2. 108 | // val= thr: MaxGray (255) 109 | // 110 | void 111 | Threshold::threshold(ImagePtr I1, int thr, ImagePtr I2) 112 | { 113 | HW_threshold(I1, thr, I2); 114 | } 115 | 116 | 117 | 118 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 119 | // Threshold::changeThr: 120 | // 121 | // Slot to process change in thr caused by moving the slider. 122 | // 123 | void 124 | Threshold::changeThr(int thr) 125 | { 126 | // set slider and spinbox to same value 127 | m_slider ->blockSignals(true); 128 | m_slider ->setValue (thr ); 129 | m_slider ->blockSignals(false); 130 | m_spinBox->blockSignals(true); 131 | m_spinBox->setValue (thr ); 132 | m_spinBox->blockSignals(false); 133 | 134 | // apply filter and display output 135 | g_mainWindowP->preview(); 136 | } 137 | 138 | 139 | 140 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 141 | // Threshold::reset: 142 | // 143 | // Reset parameters. 144 | // 145 | void 146 | Threshold::reset() 147 | { 148 | // reset parameters 149 | int thr = MXGRAY>>1; 150 | m_slider ->blockSignals(true); 151 | m_slider ->setValue (thr); 152 | m_slider ->blockSignals(false); 153 | m_spinBox->blockSignals(true); 154 | m_spinBox->setValue (thr); 155 | m_spinBox->blockSignals(false); 156 | 157 | // apply filter and display output 158 | g_mainWindowP->preview(); 159 | } 160 | 161 | 162 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 163 | // Threshold::initShader: 164 | // 165 | // init shader program and parameters. 166 | // 167 | void 168 | Threshold::initShader() 169 | { 170 | m_nPasses = 1; 171 | // initialize GL function resolution for current context 172 | initializeGLFunctions(); 173 | 174 | UniformMap uniforms; 175 | 176 | // init uniform hash table based on uniform variable names and location IDs 177 | uniforms["u_thr" ] = THR; 178 | uniforms["u_Sampler"] = SAMPLER; 179 | 180 | QString v_name = ":/vshader_passthrough"; 181 | QString f_name = ":/ops_point/fshader_threshold"; 182 | 183 | #ifdef __APPLE__ 184 | v_name += "_Mac"; 185 | f_name += "_Mac"; 186 | #endif 187 | 188 | // compile shader, bind attribute vars, link shader, and initialize uniform var table 189 | g_mainWindowP->glw()->initShader(m_program[PASS1], 190 | v_name + ".glsl", 191 | f_name + ".glsl", 192 | uniforms, 193 | m_uniform[PASS1]); 194 | m_shaderFlag = true; 195 | 196 | } 197 | 198 | 199 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 200 | // Threshold::gpuProgram: 201 | // 202 | // Active Threshold gpu program 203 | // 204 | void 205 | Threshold::gpuProgram(int pass) 206 | { 207 | glUseProgram(m_program[pass].programId()); 208 | glUniform1f (m_uniform[pass][THR], (GLfloat) m_slider->value()/MXGRAY); 209 | glUniform1i (m_uniform[pass][SAMPLER], 0); 210 | } 211 | -------------------------------------------------------------------------------- /src/Threshold.h: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // IMPROC: Image Processing Software Package 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // Threshold.h - Threshold widget 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #ifndef THRESHOLD_H 11 | #define THRESHOLD_H 12 | 13 | #include "ImageFilter.h" 14 | 15 | 16 | class Threshold : public ImageFilter { 17 | Q_OBJECT 18 | 19 | public: 20 | Threshold (QWidget *parent = 0); // constructor 21 | QGroupBox* controlPanel (); // create control panel 22 | bool applyFilter (ImagePtr, bool, ImagePtr); // apply filter to input 23 | void reset (); // reset parameters 24 | void threshold (ImagePtr, int, ImagePtr); 25 | void initShader (); 26 | void gpuProgram (int pass); // use GPU program to apply filter 27 | 28 | 29 | 30 | 31 | protected slots: 32 | void changeThr (int); 33 | 34 | private: 35 | // widgets 36 | QSlider* m_slider ; // Threshold slider 37 | QSpinBox* m_spinBox; // Threshold spinbox 38 | QGroupBox* m_ctrlGrp; // Groupbox for panel 39 | 40 | }; 41 | 42 | #endif // THRESHOLD_H 43 | -------------------------------------------------------------------------------- /src/fshader_passthrough.glsl: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | 4 | in vec2 v_TexCoord; // varying variable for passing texture coordinate from vertex shader 5 | uniform sampler2D u_Sampler; // uniform variable for the texture image 6 | 7 | void main() { 8 | gl_FragColor = texture2D(u_Sampler, v_TexCoord); 9 | } 10 | -------------------------------------------------------------------------------- /src/fshader_passthrough_Mac.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | 4 | varying vec2 v_TexCoord; // varying variable for passing texture coordinate from vertex shader 5 | uniform sampler2D u_Sampler; // uniform variable for the texture image 6 | 7 | void main() { 8 | gl_FragColor = texture2D(u_Sampler, v_TexCoord); 9 | } 10 | -------------------------------------------------------------------------------- /src/kernels/kernelBlur3x3.AF: -------------------------------------------------------------------------------- 1 | IMPROC 3 3 AF 2 | .111 .111 .111 3 | .111 .111 .111 4 | .111 .111 .111 5 | -------------------------------------------------------------------------------- /src/kernels/kernelBlur7x7.AF: -------------------------------------------------------------------------------- 1 | IMPROC 7 7 AF 2 | .02 .02 .02 .02 .02 .02 .02 3 | .02 .02 .02 .02 .02 .02 .02 4 | .02 .02 .02 .02 .02 .02 .02 5 | .02 .02 .02 .02 .02 .02 .02 6 | .02 .02 .02 .02 .02 .02 .02 7 | .02 .02 .02 .02 .02 .02 .02 8 | .02 .02 .02 .02 .02 .02 .02 9 | -------------------------------------------------------------------------------- /src/kernels/kernelEdgeX.AF: -------------------------------------------------------------------------------- 1 | IMPROC 3 3 AF 2 | -5 0 5 3 | -5 0 5 4 | -5 0 5 5 | -------------------------------------------------------------------------------- /src/kernels/kernelEdgeY.AF: -------------------------------------------------------------------------------- 1 | IMPROC 3 3 AF 2 | -5 -5 -5 3 | 0 0 0 4 | 5 5 5 5 | -------------------------------------------------------------------------------- /src/kernels/kernelLaplacian1.AF: -------------------------------------------------------------------------------- 1 | IMPROC 3 3 AF 2 | -1 -1 -1 3 | -1 8 -1 4 | -1 -1 -1 5 | -------------------------------------------------------------------------------- /src/kernels/kernelLaplacian5.AF: -------------------------------------------------------------------------------- 1 | IMPROC 3 3 AF 2 | -5 -5 -5 3 | -5 40 -5 4 | -5 -5 -5 5 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | // ====================================================================== 2 | // Computer Graphics Homework Solutions 3 | // Copyright (C) 2016 by George Wolberg 4 | // 5 | // main.c - main() function. 6 | // 7 | // Written by: George Wolberg, 2016 8 | // ====================================================================== 9 | 10 | #include "MainWindow.h" 11 | 12 | int main(int argc, char **argv) 13 | { 14 | QApplication app(argc, argv); // create application 15 | MainWindow window; // create UI window 16 | window.setMinimumSize(QSize(1366, 768)); 17 | window.showMaximized(); // display window 18 | return app.exec(); // infinite processing loop 19 | } 20 | -------------------------------------------------------------------------------- /src/ops_neighborhood/HW_blur.cpp: -------------------------------------------------------------------------------- 1 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | // HW_blur: 3 | // 4 | // Blur image I1 with a box filter (unweighted averaging). 5 | // The filter has width filterW and height filterH. 6 | // We force the kernel dimensions to be odd. 7 | // Output is in I2. 8 | // 9 | // Written by: Weifan Lin, 2016 10 | // 11 | void blur1D(ChannelPtr, int, int, int, ChannelPtr); 12 | 13 | void 14 | HW_blur(ImagePtr I1, int filterW, int filterH, ImagePtr I2) 15 | { 16 | IP_copyImageHeader(I1, I2); 17 | 18 | ImagePtr I3; // intermediate buffer 19 | IP_copyImageHeader(I1, I3); 20 | 21 | int w = I1->width(); 22 | int h = I1->height(); 23 | int total = w * h; 24 | 25 | int type; 26 | ChannelPtr p1, p2, p3, endd; 27 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 28 | IP_getChannel(I2, ch, p2, type); 29 | IP_getChannel(I3, ch, p3, type); 30 | 31 | if (filterW == 1) for(endd = p1 + total; p1 1) { 33 | // blur rows one by one 34 | for (int y=0; y 1) { 45 | // blur columns one by one 46 | for (int x=0; x src, int len, int stride, int ww, ChannelPtr dst) 64 | { 65 | if(ww % 2 == 0) ww++; // set ww to always be an odd number 66 | int neighborSz = ww/2; // how many pixels on the left and right 67 | int bufSz = len+ww-1; // this is len for padded buffer 68 | short* buffer = new short[bufSz]; // buffer to store a padded rows or columns 69 | 70 | // copy to buffer 71 | for (int i = 0; i < neighborSz; i++) { buffer[i] = *src; } // copy first pixel to left padded area 72 | int index = 0; 73 | for (int i = neighborSz; i < len+neighborSz; i++) { // continue with pixel replication 74 | buffer[i] = src[index]; 75 | index+=stride; // next index 76 | } 77 | for (int i = len+neighborSz; i < bufSz; i++) { buffer[i] = src[index-stride]; } // copy last pixel to right padded area 78 | 79 | unsigned short sum = 0; 80 | for (int i = 0; i, short*, int, int); // see implementation in HW_errDiffusion.cpp 10 | 11 | void 12 | HW_convolve(ImagePtr I1, ImagePtr Ikernel, ImagePtr I2) 13 | { 14 | int sz = Ikernel->width(); 15 | // if(sz % 2 == 0) sz++; // set sz to always be an odd number 16 | 17 | IP_copyImageHeader(I1, I2); 18 | int w = I1->width(); 19 | int h = I1->height(); 20 | int total = w*h; 21 | 22 | int type; 23 | ChannelPtr p1, p2, endd; 24 | 25 | if (sz == 1) { 26 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 27 | IP_getChannel(I2, ch, p2, type); 28 | for(endd = p1 + total; p1 1) { 31 | 32 | ChannelPtr pKernel; // kernel value pointer 33 | IP_getChannel(Ikernel, 0, pKernel, type); 34 | 35 | int bufSz = sz+w-1; // size of buffer for each padded row 36 | short* buffers[sz]; // array of sz pointers 37 | for (int i=0; iwidth (); 9 | int h = I1->height(); 10 | 11 | // template dimensions 12 | int ww = I2->width (); 13 | int hh = I2->height(); 14 | 15 | // error checking: size of image I1 must be >= than template I2 16 | if(!(ww<=w && hh<=h)) { 17 | fprintf(stderr, "Correlation: image is smaller than template\n"); 18 | return 0.; 19 | } 20 | 21 | // cast image into buffer of type float 22 | ImagePtr II1; 23 | if(I1->channelType(0) != FLOAT_TYPE) { 24 | II1 = IP_allocImage(I1->width(), I1->height(), FLOATCH_TYPE); 25 | IP_castChannel(I1, 0, II1, 0, FLOAT_TYPE); 26 | } else II1 = I1; 27 | 28 | // cast template into buffer of type float 29 | ImagePtr II2; 30 | if(I2->channelType(0) != FLOAT_TYPE) { 31 | II2 = IP_allocImage(I2->width(), I2->height(), FLOATCH_TYPE); 32 | IP_castChannel(I2, 0, II2, 0, FLOAT_TYPE); 33 | } else II2 = I2; 34 | 35 | // create image and template pyramids with original images at base; 36 | // if no multiresolution is used, pyramids consist of only one level. 37 | int mxlevel; 38 | ImagePtr pyramid1[8], pyramid2[8]; 39 | pyramid1[0] = II1; // base: original image 40 | pyramid2[0] = II2; // base: original template 41 | mxlevel = 0; 42 | 43 | // init search window 44 | int x1 = 0; 45 | int y1 = 0; 46 | int x2 = (w-ww)>>mxlevel; 47 | int y2 = (h-hh)>>mxlevel; 48 | 49 | // declarations 50 | int total; 51 | float sum1, sum2, tmpl_pow; 52 | ChannelPtr image, templ; 53 | ImagePtr Iblur, Ifft1, Ifft2; 54 | 55 | // multiresolution correlation: use results of lower-res correlation 56 | // (at the top of the pyramid) to narrow the search in the higher-res 57 | // correlation (towards the base of the pyramid). 58 | for(int n=mxlevel; n>=0; n--) { 59 | // init vars based on pyramid at level n 60 | w = pyramid1[n]->width(); h = pyramid1[n]->height(); 61 | ww = pyramid2[n]->width(); hh = pyramid2[n]->height(); 62 | 63 | // pointers to image and template data 64 | ChannelPtr p1 = pyramid1[n][0]; // image ptr 65 | ChannelPtr p2 = pyramid2[n][0]; // template ptr 66 | 67 | // init min and max 68 | float max = 0.; 69 | 70 | for(int y=y1; y<=y2; y++) { // visit rows 71 | for(int x=x1; x<=x2; x++) { // slide window 72 | sum1 = sum2 = 0; 73 | image = p1 + y*w + x; 74 | templ = p2; 75 | for(int i=0; i max) { 87 | max = corr; 88 | dx = x; 89 | dy = y; 90 | } 91 | } 92 | } 93 | 94 | // update search window or normalize final correlation value 95 | if(n) { // set search window for next pyramid level 96 | x1 = MAX(0, 2*dx - n); 97 | y1 = MAX(0, 2*dy - n); 98 | x2 = MIN(2*w, 2*dx + n); 99 | y2 = MIN(2*h, 2*dy + n); 100 | } else { // normalize correlation value at final level 101 | tmpl_pow = 0; 102 | total = ww * hh; 103 | for(int i=0; iwidth(); 121 | int height = I1->width(); 122 | 123 | int width_k = Itemplate->width(); 124 | int height_k = Itemplate->height(); 125 | int xx, yy; // coordinate of where template image sits in input image 126 | 127 | // get cross-correlation value 128 | float corr = correlation(I1, Itemplate, xx, yy); 129 | 130 | int type; 131 | ChannelPtr p1, p2, p3, endd; 132 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 133 | IP_getChannel(I2, ch, p2, type); 134 | IP_getChannel(Itemplate, ch, p3, type); 135 | for(int i = 0; i < width; i++) { 136 | for(int j = 0; j < height; j++) { 137 | if(i < yy) { // if we are above template image 138 | *p2++ = *p1/2; 139 | p1++; 140 | } else if(i >= yy && i <= (yy-1+height_k)) { // if we are on the rows where template image resides 141 | if(j < xx) { // if we are before the template image columns 142 | *p2 = *p1/2; 143 | } else if(j >= xx && j < (xx+width_k)) { // if we are on the columns where template resides 144 | *p2 = *p1/2 + *p3/2; 145 | p3++; 146 | } else { // if we are after the template image columns 147 | *p2 = *p1/2; 148 | } 149 | p1++; 150 | p2++; 151 | } else { // if we are below the template images 152 | *p2++ = *p1/2; 153 | p1++; 154 | } 155 | } 156 | } 157 | } 158 | float *buf = new float[3]; 159 | buf[0] = xx; 160 | buf[1] = yy; 161 | buf[2] = corr; 162 | return buf; 163 | } 164 | -------------------------------------------------------------------------------- /src/ops_neighborhood/HW_median.cpp: -------------------------------------------------------------------------------- 1 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | // HW_median: 3 | // 4 | // Apply median filter of size sz x sz to I1. 5 | // Clamp sz to 9. 6 | // Output is in I2. 7 | // 8 | // Written by: Weifan Lin, 2016 9 | // 10 | #include 11 | #include 12 | 13 | extern void copyRowToBuffer(ChannelPtr, short*, int, int); // see implementation in HW_errDiffusion.cpp 14 | int getMedianWithK(std::vector, int); 15 | 16 | void 17 | HW_median(ImagePtr I1, int sz, ImagePtr I2) 18 | { 19 | if(sz % 2 == 0) sz++; // set sz to always be an odd number 20 | int k = 0; // k nearest neighbors, k is default 0 21 | IP_copyImageHeader(I1, I2); 22 | int w = I1->width(); 23 | int h = I1->height(); 24 | int total = w*h; 25 | 26 | int type; 27 | ChannelPtr p1, p2, endd; 28 | 29 | if (sz == 1) { 30 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 31 | IP_getChannel(I2, ch, p2, type); 32 | for(endd = p1 + total; p1 1) { 35 | int bufSz = sz+w-1; // size of buffer for each padded row 36 | short* buffers[sz]; // array of sz pointers 37 | for (int i=0; i v(0); // vector for storing neighbors 53 | for (int y=0; y v, int k) { 91 | int vSz = v.size(); // vector size, also equal to kernel size, always odd 92 | unsigned short sum; 93 | 94 | if (vSz==1) { return v[0]; } // no need to sort if there is only 1 ele 95 | else { 96 | std::sort(v.begin(), v.end()); // sort the vector 97 | int middleIndex = vSz/2; // middle index 98 | if (k==0) { return v[middleIndex]; } // if k is 0 return the value at the middle index 99 | else { 100 | sum=v[middleIndex]; // initialize sum 101 | // add left k values and right k values to sum 102 | for (int i=1; i<=k; i++) { sum+= (v[middleIndex-i]+v[middleIndex+i]); } 103 | return sum/(k*2+1); // returns the average 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/ops_neighborhood/HW_sharpen.cpp: -------------------------------------------------------------------------------- 1 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | // HW_sharpen: 3 | // 4 | // Sharpen image I1. Output is in I2. 5 | // 6 | // Written by: Weifan Lin, 2016 7 | // 8 | extern void HW_blur (ImagePtr, int, int, ImagePtr); 9 | extern void HW_blur1D(ChannelPtr, int, int, int, ChannelPtr); 10 | 11 | void 12 | HW_sharpen(ImagePtr I1, int size, double factor, ImagePtr I2) 13 | { 14 | IP_copyImageHeader(I1, I2); 15 | int w = I1->width(); 16 | int h = I1->height(); 17 | int total = w * h; 18 | int type; 19 | ChannelPtr p1, p2, endd; 20 | 21 | if(size == 1) { 22 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 23 | IP_getChannel(I2, ch, p2, type); 24 | for(endd = p1 + total; p1t2: output = t2; 8 | // 9 | void 10 | HW_clip(ImagePtr I1, int t1, int t2, ImagePtr I2) 11 | { 12 | IP_copyImageHeader(I1, I2); 13 | int w = I1->width (); 14 | int h = I1->height(); 15 | int total = w * h; 16 | 17 | // init lookup table 18 | int lut[MXGRAY]; 19 | for(int i=0; i t2) lut[i] = t2; 22 | else lut[i] = i; 23 | } 24 | 25 | // evaluate output: each input pixel indexes into lut[] to eval output 26 | int type; 27 | ChannelPtr p1, p2, endd; 28 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 29 | IP_getChannel(I2, ch, p2, type); 30 | for(endd = p1 + total; p1width (); 14 | int h = I1->height(); 15 | int total = w * h; 16 | 17 | // init lookup table: multiply by contrast; add brightness 18 | int lut[MXGRAY]; 19 | double shift = 128 + brightness; 20 | for(int i=0; i p1, p2, endd; 28 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 29 | IP_getChannel(I2, ch, p2, type); 30 | for(endd = p1 + total; p1width (); 11 | int h = I1->height(); 12 | int total = w * h; 13 | 14 | // init gamma 15 | gamma = 1.0 / gamma; 16 | 17 | // init lookup table 18 | uchar lut[MXGRAY]; 19 | for(int i=0; i p1, p2, endd; 25 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 26 | IP_getChannel(I2, ch, p2, type); 27 | for(endd = p1 + total; p1width (); 11 | int h = I1->height(); 12 | int total = w * h; 13 | 14 | // scale dynamic range of I1 to full intensity range [0,255] 15 | IP_embedRange(I1, 0., (double)MaxGray, I2); 16 | 17 | // allocate memory 18 | int len = Ilut->width(); 19 | if(len <= MaxGray) 20 | fprintf(stderr, "IP_histogramMatch: warning %d\n", len); 21 | int *lut = new int[len]; 22 | double *dd1 = new double[w]; 23 | if(dd1 == NULL) IP_bailout("IP_histogramMatch: No memory"); 24 | 25 | int h1[MXGRAY], lim[MXGRAY], luttype=0, *h2, t=0, R; 26 | int left[MXGRAY], right[MXGRAY], indx[MXGRAY]; 27 | double hmin, hmax; 28 | ChannelPtr p, endd, lutp; 29 | for(int ch=0; IP_getChannel(I2, ch, p, t); ch++) { 30 | IP_getChannel(Ilut, ch, lutp, luttype); 31 | h2 = (int *) &lutp[0]; 32 | 33 | // scale h2 to conform with dimensions of I1 34 | int Hsum =0; 35 | for(int i=0; i < MXGRAY; i++) Hsum += h2[i]; 36 | double scale = (double) total / Hsum; 37 | if(scale != 1) { 38 | Hsum = 0; 39 | for(int i=0; i < MXGRAY; i++) { 40 | h2[i] = ROUND(h2[i] * scale); 41 | Hsum += h2[i]; 42 | if(Hsum > total) { 43 | h2[i] -= (Hsum-total); 44 | for(; i < MXGRAY; i++) h2[i] = 0; 45 | } 46 | } 47 | } 48 | 49 | // eval h1 and init left[], right[], and lim[] 50 | IP_histogram(I2, ch, h1, MXGRAY, hmin, hmax); 51 | R = Hsum = 0; 52 | for(int i=0; ih2[R] 58 | while(Hsum>h2[R] && Rwidth (); 12 | int h = I1->height(); 13 | int total = w * h; 14 | 15 | // init clip lut 16 | int lutClip[MXGRAY]; 17 | for(int i=0; i t2) lutClip[i] = t2; 20 | else lutClip[i] = i; 21 | } 22 | 23 | // evaluate output 24 | int type; 25 | int lutScale[MXGRAY]; 26 | ChannelPtr p1, p2, endd; 27 | double scale; 28 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 29 | IP_getChannel(I2, ch, p2, type); 30 | 31 | // clip image: apply lutClip table 32 | for(endd = p1 + total; p1width (); 12 | int h = I1->height(); 13 | int total = w * h; 14 | 15 | // init lookup table 16 | double scale = (double) MXGRAY / levels; 17 | double bias = scale / 2; 18 | int i, lut[MXGRAY]; 19 | for(i=0; i p1, p2, endd; 26 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 27 | IP_getChannel(I2, ch, p2, type); 28 | for(endd = p1 + total; p1 p1, p2; 33 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 34 | IP_getChannel(I2, ch, p2, type); 35 | for(int y=0; y= thr: output=MaxGray (255) 6 | // 7 | void 8 | HW_threshold(ImagePtr I1, int thr, ImagePtr I2) 9 | { 10 | IP_copyImageHeader(I1, I2); 11 | int w = I1->width (); 12 | int h = I1->height(); 13 | int total = w * h; 14 | 15 | // init lookup table 16 | int i, lut[MXGRAY]; 17 | for(i=0; i p1, p2, endd; 23 | for(int ch = 0; IP_getChannel(I1, ch, p1, type); ch++) { 24 | IP_getChannel(I2, ch, p2, type); 25 | for(endd = p1 + total; p1 2 | 3 | fshader_passthrough.glsl 4 | vshader_passthrough.glsl 5 | fshader_passthrough_Mac.glsl 6 | vshader_passthrough_Mac.glsl 7 | ops_point/fshader_threshold.glsl 8 | ops_point/fshader_threshold_Mac.glsl 9 | ops_point/fshader_gamma.glsl 10 | ops_point/fshader_gamma_Mac.glsl 11 | ops_point/fshader_clip.glsl 12 | ops_point/fshader_clip_Mac.glsl 13 | ops_point/fshader_contrast.glsl 14 | ops_point/fshader_contrast_Mac.glsl 15 | ops_point/fshader_histoStretch.glsl 16 | ops_point/fshader_histoStretch_Mac.glsl 17 | ops_point/fshader_quantize.glsl 18 | ops_point/fshader_quantize_Mac.glsl 19 | ops_neighborhood/fshader_blur1.glsl 20 | ops_neighborhood/fshader_blur1_Mac.glsl 21 | ops_neighborhood/fshader_blur2.glsl 22 | ops_neighborhood/fshader_blur2_Mac.glsl 23 | ops_neighborhood/fshader_myblur.glsl 24 | ops_neighborhood/fshader_myblur_Mac.glsl 25 | ops_neighborhood/fshader_sharpen.glsl 26 | ops_neighborhood/fshader_sharpen_Mac.glsl 27 | ops_neighborhood/fshader_convolve.glsl 28 | ops_neighborhood/fshader_convolve_Mac.glsl 29 | ops_neighborhood/fshader_correlation.glsl 30 | ops_neighborhood/fshader_correlation_Mac.glsl 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/vshader_passthrough.glsl: -------------------------------------------------------------------------------- 1 | #version 130 2 | 3 | 4 | in vec2 a_Position; // attribute variable: position vector 5 | in vec2 a_TexCoord; // attribute variable: texture coordinate 6 | out vec2 v_TexCoord; // varying variable for passing texture coordinate to fragment shader 7 | 8 | 9 | void main() { 10 | 11 | gl_Position = vec4(a_Position, 0, 1); 12 | v_TexCoord = a_TexCoord; 13 | } 14 | -------------------------------------------------------------------------------- /src/vshader_passthrough_Mac.glsl: -------------------------------------------------------------------------------- 1 | #version 120 2 | 3 | 4 | attribute vec2 a_Position; // attribute variable: position vector 5 | attribute vec2 a_TexCoord; // attribute variable: texture coordinate 6 | varying vec2 v_TexCoord; // varying variable for passing texture coordinate to fragment shader 7 | 8 | 9 | void main() { 10 | 11 | gl_Position = vec4(a_Position, 0, 1); 12 | v_TexCoord = a_TexCoord; 13 | } 14 | --------------------------------------------------------------------------------