1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
5 * Tecorrec is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
10 * Tecorrec is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with Tecorrec. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
22 * @brief Performs a pixel operation on a set of input channels.
25 #include "tcPixelOp.h"
28 * Constructors + destructor
31 /// Primary constructor.
32 tcPixelOp::tcPixelOp(Op op
, const QList
<tcChannel
*>& inputChannels
, float scale
)
33 : tcChannel(tr("Pixel Operation"),
34 tr("Some pixel operation"))
35 , m_inputChannels(inputChannels
)
41 Q_ASSERT(m_inputChannels
.size() > 0);
42 for (int c
= 0; c
< m_inputChannels
.size(); ++c
)
44 m_inputChannels
[c
]->addDerivitive(this);
48 /// Primary constructor.
49 tcPixelOp::tcPixelOp(Op op
, const QList
<tcChannel
*>& inputChannels
, bool radiance
)
50 : tcChannel(tr("Pixel Operation"),
51 tr("Some pixel operation"))
52 , m_inputChannels(inputChannels
)
55 , m_radiance(radiance
)
58 Q_ASSERT(m_inputChannels
.size() > 0);
59 for (int c
= 0; c
< m_inputChannels
.size(); ++c
)
61 m_inputChannels
[c
]->addDerivitive(this);
66 tcPixelOp::~tcPixelOp()
68 foreach (tcChannel
* channel
, m_inputChannels
)
70 channel
->removeDerivitive(this);
75 * Interface for derived class to implement
78 void tcPixelOp::roundPortion(double* x1
, double* y1
, double* x2
, double* y2
)
80 m_inputChannels
.first()->roundPortion(x1
, y1
, x2
, y2
);
83 tcAbstractPixelData
* tcPixelOp::loadPortion(double x1
, double y1
, double x2
, double y2
, bool changed
)
85 tcPixelData
<float>* data
= 0;
95 for (int c
= 0; c
< m_inputChannels
.size(); ++c
)
97 tcChannel
* channel
= m_inputChannels
[c
];
98 Reference
<tcAbstractPixelData
> channelData
= channel
->portion(x1
, y1
, x2
, y2
);
102 width
= channelData
->width();
103 height
= channelData
->height();
104 data
= new tcPixelData
<float>(width
, height
);
105 for (int j
= 0; j
< height
; ++j
)
107 for (int i
= 0; i
< width
; ++i
)
109 int index
= j
*width
+i
;
110 float value
= m_scale
*channelData
->sampleFloat((float)i
/(width
-1), (float)j
/(height
-1));
113 value
= channel
->valueToRadiance(value
);
115 data
->buffer()[index
] = value
;
123 for (int j
= 0; j
< height
; ++j
)
125 for (int i
= 0; i
< width
; ++i
)
127 int index
= j
*width
+i
;
128 float value
= m_scale
*channelData
->sampleFloat((float)i
/(width
-1), (float)j
/(height
-1));
131 value
= channel
->valueToRadiance(value
);
133 data
->buffer()[index
] += value
;
137 else if (m_op
== Subtract
)
139 for (int j
= 0; j
< height
; ++j
)
141 for (int i
= 0; i
< width
; ++i
)
143 int index
= j
*width
+i
;
144 float value
= m_scale
*channelData
->sampleFloat((float)i
/(width
-1), (float)j
/(height
-1));
147 value
= channel
->valueToRadiance(value
);
149 data
->buffer()[index
] -= value
;
153 else if (m_op
== Diff
)
155 for (int j
= 0; j
< height
; ++j
)
157 for (int i
= 0; i
< width
; ++i
)
159 int index
= j
*width
+i
;
160 data
->buffer()[index
] += m_scale
*(0.5f
- channelData
->sampleFloat((float)i
/(width
-1), (float)j
/(height
-1)));
171 // "Scene shadow effects on multispectral response"
172 Reference
<tcAbstractPixelData
> channelData1
= m_inputChannels
[0]->portion(x1
, y1
, x2
, y2
);
173 Reference
<tcAbstractPixelData
> channelData2
= m_inputChannels
[1]->portion(x1
, y1
, x2
, y2
);
174 for (int j
= 0; j
< height
; ++j
)
176 for (int i
= 0; i
< width
; ++i
)
178 int index
= j
*width
+i
;
179 float value1
= m_scale
*channelData1
->sampleFloat((float)i
/(width
-1), (float)j
/(height
-1));
180 float value2
= m_scale
*channelData2
->sampleFloat((float)i
/(width
-1), (float)j
/(height
-1));
183 value1
= m_inputChannels
[0]->valueToRadiance(value1
);
184 value2
= m_inputChannels
[1]->valueToRadiance(value2
);
186 data
->buffer()[index
] = (value1
-value2
) / (value1
+value2
);
199 for (int j
= 0; j
< height
; ++j
)
201 for (int i
= 0; i
< width
; ++i
)
203 int index
= j
*width
+i
;
204 if (data
->buffer()[index
] > max
)
206 max
= data
->buffer()[index
];
212 float min
= max
*0.25f
;
213 for (int j
= 0; j
< height
; ++j
)
215 for (int i
= 0; i
< width
; ++i
)
217 int index
= j
*width
+i
;
218 data
->buffer()[index
] = qMax(0.0f
, qMin(1.0f
, (data
->buffer()[index
]-min
)/(max
-min
)));