Tweaks and attempts to get shape from shading working
[tecorrec.git] / geo / tcPixelOp.cpp
blob1a29dcb6125fca7f51a9f7c2f6e17bf70df47daa
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 default:
171 break;
174 if (m_autoScale)
176 float max = 0.0f;
177 for (int j = 0; j < height; ++j)
179 for (int i = 0; i < width; ++i)
181 int index = j*width+i;
182 if (data->buffer()[index] > max)
184 max = data->buffer()[index];
188 if (max > 0.0f)
190 float min = max*0.25f;
191 for (int j = 0; j < height; ++j)
193 for (int i = 0; i < width; ++i)
195 int index = j*width+i;
196 data->buffer()[index] = qMax(0.0f, qMin(1.0f, (data->buffer()[index]-min)/(max-min)));
201 return data;