tcElevationOptimization: fix typo s/write/read/
[tecorrec.git] / geo / tcPixelOp.cpp
blobb12cd703c481482166b2ae87504791963271c987
1 /***************************************************************************
2 * This file is part of Tecorrec. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20 /**
21 * @file tcPixelOp.cpp
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)
36 , m_op(op)
37 , m_autoScale(false)
38 , m_radiance(false)
39 , m_scale(scale)
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)
53 , m_op(op)
54 , m_autoScale(true)
55 , m_radiance(radiance)
56 , m_scale(1.0f)
58 Q_ASSERT(m_inputChannels.size() > 0);
59 for (int c = 0; c < m_inputChannels.size(); ++c)
61 m_inputChannels[c]->addDerivitive(this);
65 /// Destructor.
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;
86 bool first = true;
87 int width = 0;
88 int height = 0;
89 switch (m_op)
91 case Add:
92 case Subtract:
93 case Diff:
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);
99 if (first)
101 first = false;
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));
111 if (m_radiance)
113 value = channel->valueToRadiance(value);
115 data->buffer()[index] = value;
119 else
121 if (m_op == Add)
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));
129 if (m_radiance)
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));
145 if (m_radiance)
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)));
163 break;
167 break;
169 case NormalizedDiff:
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));
181 if (m_radiance)
183 value1 = m_inputChannels[0]->valueToRadiance(value1);
184 value2 = m_inputChannels[1]->valueToRadiance(value2);
186 data->buffer()[index] = (value1-value2) / (value1+value2);
189 break;
191 default:
193 break;
196 if (m_autoScale)
198 float max = 0.0f;
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];
210 if (max > 0.0f)
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)));
223 return data;