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