1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossimRgbLutDataObject.cpp 13710 2008-10-14 16:27:57Z gpotts $
12 #include <ossim/base/ossimRgbLutDataObject.h>
13 #include <ossim/base/ossimKeywordlist.h>
14 #include <ossim/base/ossimFilename.h>
15 #include <ossim/base/ossimColumnVector3d.h>
16 #include <ossim/base/ossimNotifyContext.h>
17
18 #include <sstream>
19 using namespace std;
20
21 RTTI_DEF1(ossimRgbLutDataObject, "ossimRgbLutDataObject", ossimObject);
22
23 ostream& operator <<(ostream& out,
24 const ossimRgbLutDataObject& lut)
25 {
26 for(ossim_uint32 index = 0; index < lut.theNumberOfEntries; ++index)
27 {
28 out << "entry" << index << " " << lut[index] << endl;
29 }
30
31 return out;
32 }
33
34 ossimRgbLutDataObject::ossimRgbLutDataObject(unsigned long numberOfEntries)
35 :
36 theLut(NULL),
37 theNumberOfEntries(numberOfEntries)
38 {
39 if(theNumberOfEntries > 0)
40 {
41 // allocate 256 entries for the data object;
42 theLut = new ossimRgbVector[theNumberOfEntries];
43 }
44
45 }
46
47 ossimRgbLutDataObject::ossimRgbLutDataObject(const ossimRgbLutDataObject& lut)
48 :
49 theLut(NULL),
50 theNumberOfEntries(0)
51 {
52 theNumberOfEntries = lut.theNumberOfEntries;
53 if(theNumberOfEntries > 0)
54 {
55 theLut = new ossimRgbVector[theNumberOfEntries];
56 for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index)
57 {
58 theLut[index] = lut.theLut[index];
59 }
60 }
61 }
62
63 ossimRgbLutDataObject::~ossimRgbLutDataObject()
64 {
65 if(theLut)
66 {
67 delete [] theLut;
68 theLut = NULL;
69 }
70 theNumberOfEntries = 0;
71 }
72
73 int ossimRgbLutDataObject::findIndex(ossim_uint8 r, ossim_uint8 g, ossim_uint8 b)
74 {
75 ossim_uint32 distance = 0x7FFFFFFF; // max 4 byte signed
76 ossim_int32 result = 0;
77
78 if(theNumberOfEntries > 0)
79 {
80 for(ossim_uint32 i = 0; i < theNumberOfEntries; ++i)
81 {
82 ossim_uint32 rDelta = r - theLut[i].getR();
83 ossim_uint32 gDelta = g - theLut[i].getG();
84 ossim_uint32 bDelta = b - theLut[i].getB();
85
86 ossim_uint32 deltaSumSquare = (rDelta*rDelta +
87 gDelta*gDelta +
88 bDelta*bDelta);
89 if(deltaSumSquare == 0)
90 {
91 return static_cast<int>(i);
92 }
93 else if( deltaSumSquare < distance)
94 {
95 result = static_cast<int>(i);
96 distance = deltaSumSquare;
97 }
98 }
99 }
100
101 return result;
102 }
103
104 ossimRgbLutDataObject ossimRgbLutDataObject::rotate(long numberOfElements)const
105 {
106 if(numberOfElements < 0)
107 {
108 ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: Negative rotation is not supported yet in ossimRgbLutDataObject::rotate" << endl;
109 return *this;
110 }
111 ossimRgbLutDataObject lut;
112 for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index)
113 {
114 int adjustedDestinationIndex = (index+numberOfElements)%theNumberOfEntries;
115 lut[adjustedDestinationIndex] = theLut[index] ;
116 }
117
118 return lut;
119 }
120
121 ossimRgbLutDataObject& ossimRgbLutDataObject::rotate(long numberOfElements)
122 {
123 if(numberOfElements < 0)
ossimRegExp(const ossimRegExp & rxp)124 {
125 ossimNotify(ossimNotifyLevel_FATAL) << "FATAL: Negative rotation is not supported yet in ossimRgbLutDataObject::rotate" << endl;
126 return *this;
127 }
128 const ossimRgbLutDataObject* temp = this;
129
130 *this = temp->rotate(numberOfElements);
131
132 return *this;
133 }
134
135 const ossimRgbLutDataObject& ossimRgbLutDataObject::operator =(const ossimRgbLutDataObject& lut)
136 {
137 if(theNumberOfEntries != lut.theNumberOfEntries)
138 {
139 delete [] theLut;
140 theLut = NULL;
141 }
142
143 theNumberOfEntries = lut.theNumberOfEntries;
144 if(!theLut&&(theNumberOfEntries > 0))
145 {
146 theLut = new ossimRgbVector[theNumberOfEntries];
147 }
148 for(unsigned long index = 0; index < theNumberOfEntries; ++index)
149 {
150 theLut[index] = lut.theLut[index];
151 }
152
153 return *this;
154 }
155
156 bool ossimRgbLutDataObject::operator ==(const ossimRgbLutDataObject& lut)const
157 {
158 if(theNumberOfEntries != lut.theNumberOfEntries)
159 {
160 return false;
161 }
162 for(unsigned long index = 0; index < theNumberOfEntries; ++index)
163 {
164 if(theLut[index] != lut.theLut[index])
165 {
166 return false;
167 }
168 }
169 return true;
170 }
171
172 bool ossimRgbLutDataObject::saveState(ossimKeywordlist& kwl, const char* prefix)const
operator ==(const ossimRegExp & rxp) const173 {
174 kwl.add(prefix,
175 "type",
176 getClassName(),
177 true);
178 kwl.add(prefix,
179 "number_of_entries",
180 ossimString::toString(theNumberOfEntries).c_str(),
181 true);
182 for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index)
183 {
184 ossimString newPrefix = "entry";
185 newPrefix += ossimString::toString(index);
186 ostringstream ostr;
187 ostr << (int)(theLut[index].getR())
188 << " " << (int)(theLut[index].getG())
189 << " " << (int)(theLut[index].getB());
190 kwl.add(prefix,
191 newPrefix,
192 ostr.str().c_str(),
193 true);
194 }
195
196 return true;
197 }
198
199 bool ossimRgbLutDataObject::loadState(const ossimKeywordlist& kwl, const char* prefix)
200 {
201 const char* lutFile = kwl.find(prefix, "lut_file");
202 ossimKeywordlist fileLut;
203 ossimKeywordlist* tempKwl = (const_cast<ossimKeywordlist*>(&kwl));
204 ossimString tempPrefix = prefix;
205
206 // this should have been used instead of lut_file. We will still look
207 // for lut_file for backward compatibility.
208 //
209 if(!lutFile)
210 {
211 lutFile = kwl.find(prefix, "filename");
212 }
213 // check to see if we should open an external file
214 // if so point the fileLut to the one that we use
215 if(lutFile)
216 {
217 ossimFilename filename(lutFile);
218 if(filename.exists())
219 {
220 fileLut.addFile(filename.c_str());
221 tempKwl = &fileLut;
222 tempPrefix = "";
223 }
224 }
225
226 const char* numberOfEntries = tempKwl->find(tempPrefix, "number_of_entries");
227 if(!numberOfEntries)
228 {
229 numberOfEntries = tempKwl->find(tempPrefix, "number_entries");
230 }
231 if(!numberOfEntries) return false;
232 theNumberOfEntries = ossimString(numberOfEntries).toULong();
233
234 delete [] theLut;
235 theLut = new ossimRgbVector[theNumberOfEntries];
236
237 if(tempKwl->find(tempPrefix, "entry0"))
238 {
239 for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index)
240 {
241 ossimString newPrefix = "entry";
242 newPrefix += ossimString::toString(index);
243 ossimString v = tempKwl->find(tempPrefix, newPrefix.c_str());
244 istringstream istr(v);
245
246 ossimString r, g, b;
247 istr >> r >> g >> b;
248 theLut[index].setR((unsigned char)r.toInt32());
249 theLut[index].setG((unsigned char)g.toInt32());
250 theLut[index].setB((unsigned char)b.toInt32());
251 }
252 }
253 else
254 {
255 for(ossim_uint32 index = 0; index < theNumberOfEntries; ++index)
256 {
257 ossimString newPrefix = "entry";
258 newPrefix += ossimString::toString(index);
259
260 const char* r = tempKwl->find(tempPrefix, (newPrefix+".r").c_str());
261 const char* g = tempKwl->find(tempPrefix, (newPrefix+".g").c_str());
262 const char* b = tempKwl->find(tempPrefix, (newPrefix+".b").c_str());
263
264 if(r)
265 {
266 theLut[index].setR((unsigned char)ossimString(r).toLong());
267 }
268 if(g)
269 {
270 theLut[index].setG((unsigned char)ossimString(g).toLong());
271 }
272 if(b)
273 {
274 theLut[index].setB((unsigned char)ossimString(b).toLong());
275 }
276 }
277 }
278 return true;
279 }
280