1 //*******************************************************************
2 //
3 // License:  See top level LICENSE.txt file.
4 //
5 // Author:  Garrett Potts
6 //
7 //
8 // Description:
9 //
10 // Contains class definition for ossimResampler.
11 //
12 //*******************************************************************
13 //  $Id: ossimResampler.cpp 20204 2011-11-04 15:12:28Z dburken $
14 
15 
16 #include <iostream>
17 using namespace std;
18 #include <ossim/imaging/ossimResampler.h>
19 #include <ossim/base/ossimDpt.h>
20 #include <ossim/base/ossimDpt3d.h>
21 #include <ossim/base/ossimCommon.h>
22 #include <ossim/base/ossimKeywordlist.h>
23 #include <ossim/base/ossimKeywordNames.h>
24 #include <ossim/base/ossimNotifyContext.h>
25 #include <ossim/imaging/ossimImageData.h>
26 #include <ossim/imaging/ossimFilter.h>
27 #include <ossim/imaging/ossimTilePatch.h>
28 #include <ossim/imaging/ossimImageHandler.h>
29 
30 RTTI_DEF1(ossimResampler, "ossimResampler", ossimConnectableObject)
31 
32 
33 static const char* RESAMPLER_CONVOLUTION_TYPE_KW = "convolution_type";
34 static const char* RESAMPLER_SCALE_X_KW          = "scale_x";
35 static const char* RESAMPLER_SCALE_Y_KW          = "scale_y";
36 static const char* RESAMPLER_CUBIC_PARAMETER_KW  = "cubic_parameter";
37 
ossimResampler()38 ossimResampler::ossimResampler()
39    :ossimConnectableObject(NULL,0,0,true, false),
40     theOutputToInputRatio(1,1),
41     theResamplerType(ossimResampler_NONE),
42     theTableWidthX(0),
43     theTableWidthY(0),
44     theTableHeight(0),
45     theKernelWidth(0),
46     theKernelHeight(0),
47     theWeightTableX(NULL),
48     theWeightTableY(NULL),
49     theCubicAdjustableParameter(-.5)
50 {
51 }
52 
~ossimResampler()53 ossimResampler::~ossimResampler()
54 {
55    deleteWeightTable();
56 }
57 
resample(ossimImageData * input,ossimImageData * output)58 void ossimResampler::resample(ossimImageData* input,
59                               ossimImageData* output)
60 {
61    if(!input||
62       !output ||
63       !input->getBuf() ||
64       !output->getBuf())
65    {
66       return;
67    }
68 
69    if(theWeightTableX&&theWeightTableY)
70    {
71       ossimScalarType scalarType = input->getScalarType();
72       switch(scalarType)
73       {
74          case OSSIM_UINT8:
75          {
76             resampleTile(ossim_uint8(0), // dummy template variable
77                          input,
78                          output);
79             break;
80          }
81          case OSSIM_UINT16:
82          case OSSIM_USHORT11:
83          case OSSIM_USHORT12:
84          case OSSIM_USHORT13:
85          case OSSIM_USHORT14:
86          case OSSIM_USHORT15:
87          {
88             resampleTile(ossim_uint16(0), // dummy template variable
89                          input,
90                          output);
91             break;
92          }
93          case OSSIM_SSHORT16:
94          {
95             resampleTile(ossim_sint16(0), // dummy template variable
96                          input,
97                          output);
98             break;
99          }
100          case OSSIM_UINT32:
101          {
102             resampleTile(ossim_uint32(0), // dummy template variable
103                          input,
104                          output);
105             break;
106          }
107          case OSSIM_FLOAT32:
108          case OSSIM_NORMALIZED_FLOAT:
109          {
110             resampleTile(ossim_float32(0.0), // dummy template variable
111                          input,
112                          output);
113             break;
114          }
115          case OSSIM_FLOAT64:
116          case OSSIM_NORMALIZED_DOUBLE:
117          {
118             resampleTile(ossim_float64(0.0), // dummy template variable
119                          input,
120                          output);
121             break;
122          }
123          default:
124          {
125             ossimNotify(ossimNotifyLevel_WARN)
126                << "ossimResampler::resample error: unknown scalar type:  "
127                << scalarType
128                << endl;
129 
130          }
131       }
132    }
133    // convolve the input and copy to output.
134 }
135 
resample(ossimImageData * input,ossimImageData * output,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & length)136 void ossimResampler::resample(ossimImageData* input,
137                               ossimImageData* output,
138                               const ossimDpt& ul,
139                               const ossimDpt& ur,
140                               const ossimDpt& deltaUl,
141                               const ossimDpt& deltaUr,
142                               const ossimDpt& length)
143 {
144    resample(input,
145             output,
146             output->getImageRectangle(),
147             ul,
148             ur,
149             deltaUl,
150             deltaUr,
151             length);
152 }
153 
resample(ossimImageData * input,ossimImageData * output,const ossimIrect & outputSubRect,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & length)154 void ossimResampler::resample(ossimImageData* input,
155                               ossimImageData* output,
156                               const ossimIrect& outputSubRect,
157                               const ossimDpt& ul,
158                               const ossimDpt& ur,
159                               const ossimDpt& deltaUl,
160                               const ossimDpt& deltaUr,
161                               const ossimDpt& length)
162 {
163    if(!input||
164       !output ||
165       !input->getBuf() ||
166       !output->getBuf())
167    {
168       return;
169    }
170 
171    if(theWeightTableX&&theWeightTableY)
172    {
173       ossimScalarType scalarType = input->getScalarType();
174       switch(scalarType)
175       {
176          case OSSIM_UINT8:
177          {
178             resampleTile(ossim_uint8(0), // dummy template variable
179                          input,
180                          output,
181                          outputSubRect,
182                          ul,
183                          ur,
184                          deltaUl,
185                          deltaUr,
186                          length);
187             break;
188          }
189          case OSSIM_UINT16:
190          case OSSIM_USHORT11:
191          case OSSIM_USHORT12:
192          case OSSIM_USHORT13:
193          case OSSIM_USHORT14:
194          case OSSIM_USHORT15:
195          {
196             resampleTile(ossim_uint16(0), // dummy template variable
197                          input,
198                          output,
199                          outputSubRect,
200                          ul,
201                          ur,
202                          deltaUl,
203                          deltaUr,
204                          length);
205             break;
206          }
207          case OSSIM_SINT16:
208          {
209             resampleTile(ossim_sint16(0), // dummy template variable
210                          input,
211                          output,
212                          outputSubRect,
213                          ul,
214                          ur,
215                          deltaUl,
216                          deltaUr,
217                          length);
218             break;
219          }
220          case OSSIM_UINT32:
221          {
222             resampleTile(ossim_uint32(0), // dummy template variable
223                          input,
224                          output,
225                          outputSubRect,
226                          ul,
227                          ur,
228                          deltaUl,
229                          deltaUr,
230                          length);
231             break;
232          }
233          case OSSIM_FLOAT32:
234          case OSSIM_NORMALIZED_FLOAT:
235          {
236             resampleTile(ossim_float32(0.0), // dummy template variable
237                          input,
238                          output,
239                          outputSubRect,
240                          ul,
241                          ur,
242                          deltaUl,
243                          deltaUr,
244                          length);
245             break;
246          }
247          case OSSIM_FLOAT64:
248          case OSSIM_NORMALIZED_DOUBLE:
249          {
250             resampleTile(ossim_float64(0.0), // dummy template variable
251                          input,
252                          output,
253                          outputSubRect,
254                          ul,
255                          ur,
256                          deltaUl,
257                          deltaUr,
258                          length);
259             break;
260          }
261          default:
262          {
263             ossimNotify(ossimNotifyLevel_WARN)
264                << "ossimResampler::resample error: unknown scalar type:  "
265                << scalarType
266                << endl;
267          }
268       }
269    }
270 
271 }
272 
resampleNearestNeighbor(ossimImageData * input,ossimImageData * output,const ossimIrect & outputSubRect,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & length)273 void ossimResampler::resampleNearestNeighbor(ossimImageData* input,
274                                              ossimImageData* output,
275                                              const ossimIrect& outputSubRect,
276                                              const ossimDpt& ul,
277                                              const ossimDpt& ur,
278                                              const ossimDpt& deltaUl,
279                                              const ossimDpt& deltaUr,
280                                              const ossimDpt& length)
281 {
282    if(!input||
283       !output ||
284       !input->getBuf() ||
285       !output->getBuf())
286    {
287       return;
288    }
289 
290    ossimScalarType scalarType = input->getScalarType();
291    switch(scalarType)
292    {
293       case OSSIM_UINT8:
294       {
295          resampleTileNearestNeighbor(ossim_uint8(0),// dummy template variable
296                                      input,
297                                      output,
298                                      outputSubRect,
299                                      ul,
300                                      ur,
301                                      deltaUl,
302                                      deltaUr,
303                                      length);
304          break;
305       }
306       case OSSIM_UINT16:
307       case OSSIM_USHORT11:
308       case OSSIM_USHORT12:
309       case OSSIM_USHORT13:
310       case OSSIM_USHORT14:
311       case OSSIM_USHORT15:
312       {
313          resampleTileNearestNeighbor(ossim_uint16(0),// dummy template variable
314                                      input,
315                                      output,
316                                      outputSubRect,
317                                      ul,
318                                      ur,
319                                      deltaUl,
320                                      deltaUr,
321                                      length);
322          break;
323       }
324       case OSSIM_SINT16:
325       {
326          resampleTileNearestNeighbor(ossim_sint16(0),// dummy template variable
327                                      input,
328                                      output,
329                                      outputSubRect,
330                                      ul,
331                                      ur,
332                                      deltaUl,
333                                      deltaUr,
334                                      length);
335          break;
336       }
337       case OSSIM_UINT32:
338       {
339          resampleTileNearestNeighbor(ossim_uint32(0),// dummy template variable
340                                      input,
341                                      output,
342                                      outputSubRect,
343                                      ul,
344                                      ur,
345                                      deltaUl,
346                                      deltaUr,
347                                      length);
348          break;
349       }
350       case OSSIM_FLOAT32:
351       case OSSIM_NORMALIZED_FLOAT:
352       {
353          resampleTileNearestNeighbor(ossim_float32(0.0),
354                                      input,
355                                      output,
356                                      outputSubRect,
357                                      ul,
358                                      ur,
359                                      deltaUl,
360                                      deltaUr,
361                                      length);
362          break;
363       }
364       case OSSIM_FLOAT64:
365       case OSSIM_NORMALIZED_DOUBLE:
366       {
367          resampleTileNearestNeighbor(ossim_float64(0.0),
368                                      input,
369                                      output,
370                                      outputSubRect,
371                                      ul,
372                                      ur,
373                                      deltaUl,
374                                      deltaUr,
375                                      length);
376          break;
377       }
378       default:
379       {
380          ossimNotify(ossimNotifyLevel_WARN)
381             << "ossimResampler::resample error: unknown scalar type:  "
382             << scalarType
383             << endl;
384       }
385    }
386 }
387 
resampleNearestNeighbor(ossimImageData * input,ossimImageData * output,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & length)388 void ossimResampler::resampleNearestNeighbor(ossimImageData* input,
389                                              ossimImageData* output,
390                                              const ossimDpt& ul,
391                                              const ossimDpt& ur,
392                                              const ossimDpt& deltaUl,
393                                              const ossimDpt& deltaUr,
394                                              const ossimDpt& length)
395 {
396    resampleNearestNeighbor(input,
397                            output,
398                            output->getImageRectangle(),
399                            ul,
400                            ur,
401                            deltaUl,
402                            deltaUr,
403                            length);
404 }
405 
406 
407 template <class T>
resampleTile(T,ossimImageData * input,ossimImageData * output)408 void ossimResampler::resampleTile(T,// not used
409                                   ossimImageData* input,
410                                   ossimImageData* output)
411 {
412    switch(input->getDataObjectStatus())
413    {
414       case OSSIM_FULL:
415       {
416          resampleFullTile((T)0, input, output);
417          break;
418       }
419       case OSSIM_PARTIAL:
420       {
421          resamplePartialTile((T)0, input, output);
422          break;
423       }
424       default:
425       {
426          break;
427       }
428    }
429 }
430 
431 template <class T>
resamplePartialTile(T,ossimImageData * input,ossimImageData * output)432 void ossimResampler::resamplePartialTile(T,// not used
433                                          ossimImageData* input,
434                                          ossimImageData* output)
435 {
436    ossim_int32 maxInputSize  = std::max(input->getWidth(),  input->getHeight());
437    ossim_int32 maxOutputSize = std::max(output->getWidth(), output->getHeight());
438    ossim_int32 k;
439    double *h  = new double[maxInputSize];
440    int    *Lx = new int[maxOutputSize];
441    int    *Ly = new int[maxOutputSize];
442    ossim_int32 out_height = output->getHeight();
443    ossim_int32 out_width  = output->getWidth();
444    ossim_int32 in_width   = input->getWidth();
445    ossim_int32 in_height  = input->getHeight();
446    ossim_int32 j;
447    ossim_int32 l;
448 
449    ossimIpt origin=output->getOrigin();
450    ossimIpt scaledOriginShift(input->getOrigin()*-1);
451 
452    ossim_int32 evenKernelW = (ossim_int32)(!(theKernelWidth%2));
453    ossim_int32 evenKernelH = (ossim_int32)(!(theKernelHeight%2));
454    ossim_int32 kernelHorizontalShift = (ossim_int32)(-theKernelWidth/2.0+evenKernelW);
455    ossim_int32 kernelVerticalShift   = (ossim_int32)(-theKernelHeight/2.0+evenKernelH);
456 
457    for (k = 0; k < maxOutputSize; ++k)
458    {
459       Lx[k] = (ossim_int32)(scaledOriginShift.x+((k+origin.x)/
460                                            theOutputToInputRatio.x));
461    }
462    for (k = 0; k < maxOutputSize; ++k)
463    {
464       Ly[k] = (ossim_int32)(scaledOriginShift.y+((k+origin.y)/
465                                            theOutputToInputRatio.y));
466    }
467    for(ossim_int32 band = 0; band < (ossim_int32)input->getNumberOfBands();++band)
468    {
469       const T* inputBuf  = static_cast<T*>(input->getBuf(band));
470       T*       outputBuf = static_cast<T*>(output->getBuf(band));
471       T        minPix    = static_cast<T>(input->getMinPix(band));
472       T        maxPix    = static_cast<T>(input->getMaxPix(band));
473       T        np        = static_cast<T>(input->getNullPix(band));
474 
475       for (k = 0; k < out_height; ++k)
476       {
477          ossim_int32 indexMod = (ossim_int32)fmod((k+origin.y), theOutputToInputRatio.y);
478          if(indexMod >= theTableWidthY) indexMod = theTableWidthY - 1;
479          if(indexMod <0) indexMod = 0;
480          for (j = 0; j < in_width; ++j)
481          {
482             h[j] = 0.0;
483             ossim_int32 count = 0;
484             double lastValue = ossim::nan();
485             for (l = 0; l < theKernelHeight; ++l)
486             {
487                ossim_int32 index = Ly[k] + l + kernelVerticalShift;
488                if ((index >= 0) && (index < in_height))
489                {
490                   ossim_int32 offset = index*in_width +j;
491                   if(!input->isNull(offset))
492                   {
493                      lastValue = (double)inputBuf[offset];
494                      h[j] += lastValue *
495                              theWeightTableY[theKernelHeight - l-1][indexMod];
496                      ++count;
497                   }
498                   // I think instead of skipping to next value I'll just assume 0
499 
500                   // this was code to skip to next non-null value and use it
501                   //
502 //                   else
503 //                   {
504 //                      for(ossim_int32 templ = l; templ < theKernelHeight; ++templ)
505 //                      {
506 //                         index = Ly[k] + templ + kernelVerticalShift;
507 //                         offset = index*in_width +j;
508 //                         if(!input->isNull(offset))
509 //                         {
510 //                            lastValue = (double)inputBuf[offset];
511 //                            break;
512 //                         }
513 //                      }
514 //                      if(ossim::isnan(lastValue) == false)
515 //                      {
516 //                         h[j] += lastValue *
517 //                                 theWeightTableY[theKernelHeight - l-1][indexMod];
518 
519 //                         ++count;
520 //                      }
521 //                      else
522 //                      {
523 //                         break;
524 //                      }
525 //                   }
526                }
527             }
528             if(!count)
529             {
530                h[j] = ossim::nan();
531             }
532          }
533          for (ossim_int32 m = 0; m < out_width; ++m)
534          {
535             double x = 0.0;
536             ossim_int32 indexMod = (ossim_int32)fmod((m+origin.x), theOutputToInputRatio.x);
537             if(indexMod >= theTableWidthX) indexMod = theTableWidthX-1;
538             if(indexMod <0) indexMod = 0;
539 
540             if(input->isNull(ossimIpt(Lx[m]-scaledOriginShift.x, Ly[k]-scaledOriginShift.y)))
541             {
542                outputBuf[k*out_width +m] = np;
543             }
544             else
545             {
546                for (l = 0; l < theKernelWidth; ++l)
547                {
548                   ossim_int32 index = Lx[m] + l + kernelHorizontalShift;
549                   if ((index >= 0) && (index < in_width))
550                   {
551                      if(ossim::isnan(h[index]) == false)
552                      {
553                         x += h[index] * theWeightTableX[theKernelWidth - l-1][indexMod];
554                      }
555 
556                      // I am commenting out the code that searches for the next
557                      // non null value with the kernel range.  This will have the
558                      // same effect as multiplying by 0.0 for the NULL value.
559                      //
560 //                      else
561 //                      {
562 //                         for(ossim_int32 templ = l; templ < l; ++templ)
563 //                         {
564 //                            ossim_int32 index = Lx[m] + templ + kernelHorizontalShift;
565 //                            if(ossim::isnan(h[index]) == false))
566 //                            {
567 //                               lastValue = h[index];
568 //                               break;
569 //                            }
570 //                         }
571 //                         if(ossim::isnan(lastValue) == false)
572 //                         {
573 //                            x += lastValue * theWeightTableX[theKernelWidth - l-1][indexMod];
574 //                         }
575 //                      }
576                   }
577                }
578                if (x < minPix)
579                {
580                   outputBuf[k*out_width +m] = static_cast<T>(minPix);
581                }
582                else if (x > maxPix)
583                {
584                   outputBuf[k*out_width +m] = static_cast<T>(maxPix);
585                }
586                else
587                {
588                   outputBuf[k*out_width +m] = static_cast<T>(x);
589                }
590             }
591          }
592       }
593    }
594 
595    delete [] h;
596    delete [] Lx;
597    delete [] Ly;
598 }
599 
600 template <class T>
resampleFullTile(T,ossimImageData * input,ossimImageData * output)601 void ossimResampler::resampleFullTile(T,// not used
602                                       ossimImageData* input,
603                                       ossimImageData* output)
604 {
605    ossim_int32 maxInputSize  = std::max(input->getWidth(),  input->getHeight());
606    ossim_int32 maxOutputSize = std::max(output->getWidth(), output->getHeight());
607    ossim_int32 k;
608    double *h     = new double[maxInputSize];
609    ossim_int32 *Lx        = new ossim_int32[maxOutputSize];
610    ossim_int32 *Ly        = new ossim_int32[maxOutputSize];
611    ossim_int32 out_height = output->getHeight();
612    ossim_int32 out_width  = output->getWidth();
613    ossim_int32 in_width   = input->getWidth();
614    ossim_int32 in_height  = input->getHeight();
615    ossim_int32 j;
616    ossim_int32 l;
617 
618    ossimIpt origin=output->getOrigin();
619    ossimIpt scaledOriginShift(input->getOrigin()*-1);
620 
621    ossim_int32 evenKernelW = (ossim_int32)(!(theKernelWidth%2));
622    ossim_int32 evenKernelH = (ossim_int32)(!(theKernelHeight%2));
623    ossim_int32 kernelHorizontalShift = (ossim_int32)(-theKernelWidth/2.0+evenKernelW);
624    ossim_int32 kernelVerticalShift   = (ossim_int32)(-theKernelHeight/2.0+evenKernelH);
625 
626    for (k = 0; k < maxOutputSize; ++k)
627    {
628       Lx[k] = (ossim_int32)(scaledOriginShift.x+((k+origin.x)/
629                                            theOutputToInputRatio.x));
630    }
631    for (k = 0; k < maxOutputSize; ++k)
632    {
633       Ly[k] = (ossim_int32)(scaledOriginShift.y+((k+origin.y)/
634                                            theOutputToInputRatio.y));
635    }
636    for(ossim_int32 band = 0; band < (ossim_int32)input->getNumberOfBands();++band)
637    {
638       const T* inputBuf  = (const T*)(input->getBuf(band));
639       T*       outputBuf = (T*)(output->getBuf(band));
640       double  minPix    = static_cast<T>(input->getMinPix()[band]);
641       double  maxPix    = static_cast<T>(input->getMaxPix()[band]);
642 
643       for (k = 0; k < out_height; ++k)
644       {
645          int indexMod = (int)fmod((k+origin.y), theOutputToInputRatio.y);
646          if(indexMod >= theTableWidthY) indexMod = theTableWidthY - 1;
647          if(indexMod <0) indexMod = 0;
648          for (j = 0; j < in_width; ++j)
649          {
650             h[j] = 0.0;
651             for (l = 0; l < theKernelHeight; ++l)
652             {
653                ossim_int32 index = Ly[k] + l + kernelVerticalShift;
654                if ((index >= 0) && (index < in_height))
655                {
656                   h[j] += ((double)inputBuf[index*in_width +j]) *
657                           theWeightTableY[theKernelHeight - l-1][indexMod];
658                }
659             }
660          }
661          for (ossim_int32 m = 0; m < out_width; ++m)
662          {
663             double x = 0.0;
664             int indexMod = (int)fmod((m+origin.x), theOutputToInputRatio.x);
665             if(indexMod >= theTableWidthX) indexMod = theTableWidthX-1;
666             if(indexMod <0) indexMod = 0;
667 
668             for (l = 0; l < theKernelWidth; ++l)
669             {
670                ossim_int32 index = Lx[m] + l + kernelHorizontalShift;
671                if ((index >= 0) && (index < in_width))
672                {
673 
674                   x += h[index] * theWeightTableX[theKernelWidth - l-1][indexMod];
675                }
676             }
677             if (x < minPix)
678             {
679                outputBuf[k*out_width +m] = static_cast<T>(minPix);
680             }
681             else if (x > maxPix)
682             {
683                outputBuf[k*out_width +m] = static_cast<T>(maxPix);
684             }
685             else
686             {
687                outputBuf[k*out_width +m] = static_cast<T>(x);
688             }
689          }
690       }
691    }
692 
693    delete [] h;
694    delete [] Lx;
695    delete [] Ly;
696 }
697 
698 
699 
700 template <class T>
resampleTile(T,ossimImageData * input,ossimImageData * output,const ossimIrect & outputSubRect,const ossimDpt & inputUl,const ossimDpt & inputUr,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & outLength)701 void ossimResampler::resampleTile(T,// not used
702                                   ossimImageData* input,
703                                   ossimImageData* output,
704                                   const ossimIrect& outputSubRect,
705                                   const ossimDpt& inputUl,
706                                   const ossimDpt& inputUr,
707                                   const ossimDpt& deltaUl,
708                                   const ossimDpt& deltaUr,
709                                   const ossimDpt& outLength)
710 {
711    ossimRefPtr<ossimImageData> dupIn = input;
712    ossimDpt origin = input->getOrigin();
713    ossimDpt newInputUl = inputUl;
714    ossimDpt newInputUr = inputUr;
715    ossimDpt newDeltaUl = deltaUl;
716    ossimDpt newDeltaUr = deltaUr;
717 
718    if(theResamplerType != ossimResampler_NEAREST_NEIGHBOR)
719    {
720       newInputUl = ossimDpt(inputUl.x * theOutputToInputRatio.x,
721                             inputUl.y * theOutputToInputRatio.y);
722       newInputUr = ossimDpt(inputUr.x * theOutputToInputRatio.x,
723                             inputUr.y * theOutputToInputRatio.y);
724       newDeltaUl = ossimDpt(deltaUl.x * theOutputToInputRatio.x,
725                             deltaUl.y * theOutputToInputRatio.y);
726       newDeltaUr = ossimDpt(deltaUr.x * theOutputToInputRatio.x,
727                             deltaUr.y * theOutputToInputRatio.y);
728 
729       ossimDpt newLl = newInputUl + newDeltaUl*outLength.y;
730       ossimDpt newLr = newInputUr + newDeltaUr*outLength.y;
731 
732       ossimDrect newBoundingRect(newInputUl,
733                                  newInputUr,
734                                  newLl,
735                                  newLr);
736 
737 
738       newBoundingRect = ossimDrect(newBoundingRect.ul() - ossimDpt(theKernelWidth, theKernelHeight),
739                                    newBoundingRect.lr() + ossimDpt(theKernelWidth, theKernelHeight));
740       ossimIrect roundedRect = newBoundingRect;
741       origin = roundedRect.ul();
742 
743       dupIn = new ossimImageData(NULL,
744                                  input->getScalarType(),
745                                  input->getNumberOfBands(),
746                                  roundedRect.width(),
747                                  roundedRect.height());
748       dupIn->setOrigin(roundedRect.ul());
749       dupIn->initialize();
750       resampleTile(static_cast<T>(0), input, dupIn.get());
751    }
752    long    inWidth        = dupIn->getWidth();
753    long    inHeight       = dupIn->getHeight();
754    double  stepSizeWidth  = 1.0/outLength.x;
755    double  stepSizeHeight = 1.0/outLength.y;
756    ossimIrect rect = dupIn->getImageRectangle();
757 
758    ossimDpt startSave(newInputUl.x - rect.ul().x,
759                       newInputUl.y - rect.ul().y );
760    ossimDpt endSave(newInputUr.x - rect.ul().x,
761                     newInputUr.y - rect.ul().y);
762 
763    ossimIrect outputRect = output->getImageRectangle();
764    ossimIpt subRectUl = outputSubRect.ul();
765    long     subRectH  = outputSubRect.height();
766    long     subRectW  = outputSubRect.width();
767 
768    ossimIpt outputRectUl    = outputRect.ul();
769    long outputRectW         = outputRect.width();
770    long resultOffset = (subRectUl.y - outputRectUl.y)*outputRectW + (subRectUl.x - outputRectUl.x);
771 
772    for(ossim_uint32 band = 0; band < input->getNumberOfBands(); ++band)
773    {
774       T* resultBuf       = static_cast<T*>(output->getBuf(band))+resultOffset;
775       const T *sourceBuf = static_cast<T*>(dupIn->getBuf(band));
776       ossimDpt start = startSave;
777       ossimDpt end   = endSave;
778       T np = (T)output->getNullPix(band);
779 
780       for(long y = 0; y < subRectH; ++y)
781       {
782          double deltaX = (end.x - start.x)*stepSizeWidth;
783          double deltaY = (end.y - start.y)*stepSizeHeight;
784          ossimDpt pointXY = start;
785 
786          for(long x = 0; x < subRectW; ++x)
787          {
788             int xPixel = pointXY.x<0?(int)floor(pointXY.x):(int)pointXY.x;
789             int yPixel = pointXY.y<0?(int)floor(pointXY.y):(int)pointXY.y;
790 
791 
792             if( (xPixel >=0) && (xPixel < inWidth) &&
793                 (yPixel >=0) && (yPixel < inHeight))
794             {
795                resultBuf[x] = sourceBuf[yPixel*inWidth + xPixel];
796             }
797             else
798             {
799                resultBuf[x] = np;
800             }
801 
802             pointXY.y += deltaY;
803             pointXY.x += deltaX;
804          }
805          resultBuf += outputRectW;
806 
807          start.x += newDeltaUl.x;
808          start.y += newDeltaUl.y;
809          end.x   += newDeltaUr.x;
810          end.y   += newDeltaUr.y;
811       }
812    }
813    dupIn = 0;
814 }
815 
816 template <class T>
resampleTileNearestNeighbor(T,ossimImageData * input,ossimImageData * output,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & length)817 void ossimResampler::resampleTileNearestNeighbor(T, // dummy template variable
818                                                  ossimImageData* input,
819                                                  ossimImageData* output,
820                                                  const ossimDpt& ul,
821                                                  const ossimDpt& ur,
822                                                  const ossimDpt& deltaUl,
823                                                  const ossimDpt& deltaUr,
824                                                  const ossimDpt& length)
825 {
826    resampleTileNearestNeighbor((T)0,
827                                input,
828                                output,
829                                output->getImageRectangle(),
830                                ul,
831                                ur,
832                                deltaUl,
833                                deltaUr,
834                                length);
835 }
836 
837 template <class T>
resampleTileNearestNeighbor(T,ossimImageData * input,ossimImageData * output,const ossimIrect & outputSubRect,const ossimDpt & ul,const ossimDpt & ur,const ossimDpt & deltaUl,const ossimDpt & deltaUr,const ossimDpt & length)838 void ossimResampler::resampleTileNearestNeighbor(T, // dummy template variable
839                                                  ossimImageData* input,
840                                                  ossimImageData* output,
841                                                  const ossimIrect& outputSubRect,
842                                                  const ossimDpt& ul,
843                                                  const ossimDpt& ur,
844                                                  const ossimDpt& deltaUl,
845                                                  const ossimDpt& deltaUr,
846                                                  const ossimDpt& length)
847 {
848    long    inWidth        = input->getWidth();
849    long    inHeight       = input->getHeight();
850    double  stepSizeWidth  = 1.0/length.x;
851    double  stepSizeHeight = 1.0/length.y;
852    ossimIrect rect        = input->getImageRectangle();
853 
854    ossimDpt startSave(ul.x - rect.ul().x,
855                       ul.y - rect.ul().y );
856 
857    ossimDpt endSave(ur.x - rect.ul().x,
858                     ur.y - rect.ul().y);
859 
860    ossimIrect outputRect = output->getImageRectangle();
861    ossimIpt subRectUl = outputSubRect.ul();
862 //   ossimIpt subRectUl((int)outputSubRect.ul().x,
863 //                      (int)outputSubRect.ul().y);
864    long     subRectH  = outputSubRect.height();
865    long     subRectW  = outputSubRect.width();
866 
867    ossimIpt outputRectUl    = outputRect.ul();
868    long outputRectW         = outputRect.width();
869 
870    long resultOffset = (subRectUl.y - outputRectUl.y)*outputRectW + (subRectUl.x - outputRectUl.x);
871    for(ossim_uint32 band = 0; band < input->getNumberOfBands(); ++band)
872    {
873       T* resultBuf       = static_cast<T*>(output->getBuf(band))+resultOffset;
874       const T *sourceBuf = static_cast<T*>(input->getBuf(band));
875       ossimDpt start = startSave;
876       ossimDpt end   = endSave;
877       T inNp  = (T)input->getNullPix(band);
878       T outNp = (T)output->getNullPix(band);
879 
880       for(long y = 0; y < subRectH; ++y)
881       {
882          double deltaX = (end.x - start.x)*stepSizeWidth;
883          double deltaY = (end.y - start.y)*stepSizeHeight;
884          ossimDpt pointXY = start;
885 
886          for(long x = 0; x < subRectW; ++x)
887          {
888             int xPixel = pointXY.x<0?(int)floor(pointXY.x):(int)pointXY.x;
889             int yPixel = pointXY.y<0?(int)floor(pointXY.y):(int)pointXY.y;
890 
891 
892              if( (xPixel >=0) && (xPixel < inWidth) &&
893                  (yPixel >=0) && (yPixel < inHeight))
894              {
895                 T value = sourceBuf[yPixel*inWidth + xPixel];
896 
897                 if(value != inNp)
898                 {
899                    resultBuf[x] = value;
900                 }
901                 else
902                 {
903                    resultBuf[x] = outNp;
904                 }
905             }
906             else
907             {
908                resultBuf[x] = outNp;
909             }
910 
911             pointXY.y += deltaY;
912             pointXY.x += deltaX;
913          }
914          resultBuf += outputRectW;
915 
916          start.x += deltaUl.x;
917          start.y += deltaUl.y;
918          end.x   += deltaUr.x;
919          end.y   += deltaUr.y;
920       }
921    }
922 }
923 
getKernelWidth() const924 ossim_int32 ossimResampler::getKernelWidth()const
925 {
926    return theKernelWidth;
927 }
928 
getKernelHeight() const929 ossim_int32 ossimResampler::getKernelHeight()const
930 {
931    return theKernelHeight;
932 }
933 
deleteWeightTable()934 void ossimResampler::deleteWeightTable()
935 {
936    if(theWeightTableX)
937    {
938       for(ossim_int32 index = 0; index < theTableHeight; ++index)
939       {
940          delete [] theWeightTableX[index];
941       }
942       delete [] theWeightTableX;
943 
944       theWeightTableX = NULL;
945    }
946    if(theWeightTableY)
947    {
948       for(ossim_int32 index = 0; index < theTableHeight; ++index)
949       {
950          delete [] theWeightTableY[index];
951       }
952       delete [] theWeightTableY;
953 
954       theWeightTableY = NULL;
955    }
956 }
957 
allocateWeightTable()958 void ossimResampler::allocateWeightTable()//uint32 outWidth)
959 {
960    if(theWeightTableX||
961       theWeightTableY)
962    {
963       deleteWeightTable();
964    }
965 
966    switch(theResamplerType)
967    {
968    case ossimResampler_BICUBIC:
969    {
970       theTableHeight = 4;
971       break;
972    }
973    case ossimResampler_BILINEAR:
974    {
975       theTableHeight = 2;
976       break;
977    }
978    case ossimResampler_NEAREST_NEIGHBOR:
979    {
980       theTableHeight = 1;
981       break;
982    }
983    case ossimResampler_NONE:
984      {
985        theResamplerType = ossimResampler_NEAREST_NEIGHBOR;
986       theTableHeight = 1;
987       break;
988      }
989    }
990    theTableWidthX = (ossim_int32)ossim::round<int>(theOutputToInputRatio.x);
991    theTableWidthY = (ossim_int32)ossim::round<int>(theOutputToInputRatio.y);
992    if(theTableWidthX&&theTableHeight)
993    {
994       theWeightTableX = new double*[theTableHeight];
995 
996       for(ossim_int32 index = 0; index < theTableHeight; ++index)
997       {
998          theWeightTableX[index] = new double[theTableWidthX];
999       }
1000    }
1001    if(theTableWidthY&&theTableHeight)
1002    {
1003       theWeightTableY = new double*[theTableHeight];
1004 
1005       for(ossim_int32 index = 0; index < theTableHeight; ++index)
1006       {
1007          theWeightTableY[index] = new double[theTableWidthY];
1008       }
1009    }
1010 }
1011 
generateWeightTable()1012 void ossimResampler::generateWeightTable()
1013 {
1014    if(theWeightTableX&&
1015       theWeightTableY)
1016    {
1017 //      ossim_int32 d = theOutputToInputRatio.theDen;
1018 //      ossim_int32 n = theOutputToInputRatio.theNum;
1019       ossim_int32 i = 0;
1020 
1021       double x = 0.0;
1022 
1023       switch(theResamplerType)
1024       {
1025    case ossimResampler_NONE:
1026      {
1027        theResamplerType = ossimResampler_NEAREST_NEIGHBOR;
1028        for (i = 0; i < theTableWidthY; ++i)
1029          {
1030 	   theWeightTableY[0][i] = 1;
1031          }
1032        for (i = 0; i < theTableWidthX; ++i)
1033          {
1034 	   theWeightTableX[0][i] = 1;
1035          }
1036       break;
1037      }
1038       case ossimResampler_NEAREST_NEIGHBOR:
1039       {
1040          for (i = 0; i < theTableWidthY; ++i)
1041          {
1042             theWeightTableY[0][i] = 1;
1043          }
1044          for (i = 0; i < theTableWidthX; ++i)
1045          {
1046             theWeightTableX[0][i] = 1;
1047          }
1048          break;
1049       }
1050       case ossimResampler_BILINEAR:
1051       {
1052          for (i = 0; i < theTableWidthX; ++i)
1053          {
1054             x = (double)i/(double)(theTableWidthX);
1055             theWeightTableX[0][i] = x;
1056             theWeightTableX[1][i] = 1-x;
1057          }
1058          for (i = 0; i < theTableWidthY; ++i)
1059          {
1060             x = (double)i/(double)(theTableWidthY);
1061             theWeightTableY[0][i] = x;
1062             theWeightTableY[1][i] = 1-x;
1063          }
1064          break;
1065       }
1066       case ossimResampler_BICUBIC:
1067       {
1068          for (i = 0; i < theTableWidthX; ++i)
1069          {
1070             x = (double)i/(double)(theTableWidthX);
1071             theWeightTableX[0][i] = getCubicC0(x);
1072             theWeightTableX[1][i] = getCubicC1(x);
1073             theWeightTableX[2][i] = getCubicC2(x);
1074             theWeightTableX[3][i] = getCubicC3(x);
1075          }
1076          for (i = 0; i < theTableWidthY; ++i)
1077          {
1078             x = (double)i/(double)(theTableWidthY);
1079             theWeightTableY[0][i] = getCubicC0(x);
1080             theWeightTableY[1][i] = getCubicC1(x);
1081             theWeightTableY[2][i] = getCubicC2(x);
1082             theWeightTableY[3][i] = getCubicC3(x);
1083          }
1084          break;
1085       }
1086       }
1087    }
1088 }
1089 
setResamplerType(ossimResLevelResamplerType type)1090 void ossimResampler::setResamplerType(ossimResLevelResamplerType type)
1091 {
1092    if(theResamplerType != type)
1093    {
1094       theResamplerType = type;
1095 
1096       switch(theResamplerType)
1097       {
1098       case ossimResampler_NONE:
1099       {
1100 	theResamplerType = ossimResampler_NEAREST_NEIGHBOR;
1101          theKernelWidth  = 1;
1102          theKernelHeight = 1;
1103 
1104          break;
1105       }
1106       case ossimResampler_NEAREST_NEIGHBOR:
1107       {
1108          theKernelWidth  = 1;
1109          theKernelHeight = 1;
1110 
1111          break;
1112       }
1113       case ossimResampler_BILINEAR:
1114       {
1115          theKernelWidth  = 2;
1116          theKernelHeight = 2;
1117 
1118          break;
1119       }
1120       case ossimResampler_BICUBIC:
1121       {
1122          theKernelWidth  = 4;
1123          theKernelHeight = 4;
1124 
1125          break;
1126       }
1127       }
1128 
1129       allocateWeightTable();
1130       generateWeightTable();
1131    }
1132 }
1133 
setRatio(double outputToInputRatio)1134 void ossimResampler::setRatio(double outputToInputRatio)
1135 {
1136    // make it square
1137    setRatio(ossimDpt(outputToInputRatio, outputToInputRatio));
1138 }
1139 
setRatio(const ossimDpt & outputToInputRatio)1140 void ossimResampler::setRatio(const ossimDpt& outputToInputRatio)
1141 {
1142    // make it square
1143    theOutputToInputRatio.x = (outputToInputRatio.x);
1144    theOutputToInputRatio.y = (outputToInputRatio.y);
1145 
1146    if((theTableWidthX != ossim::round<int>(outputToInputRatio.x))||
1147       (theTableWidthY != ossim::round<int>(outputToInputRatio.y)))
1148    {
1149       allocateWeightTable();
1150       generateWeightTable();
1151    }
1152 }
1153 
getCubicC0(double t) const1154 double ossimResampler::getCubicC0(double t)const
1155 {
1156    return ((-theCubicAdjustableParameter * t * t * t) +
1157            (theCubicAdjustableParameter * t * t));
1158 }
1159 
getCubicC1(double t) const1160 double ossimResampler::getCubicC1(double t)const
1161 {
1162    return (-(theCubicAdjustableParameter + 2.0) * t * t * t +
1163            (2.0 * theCubicAdjustableParameter + 3.0) * t * t -
1164            theCubicAdjustableParameter * t);
1165 }
1166 
getCubicC2(double t) const1167 double ossimResampler::getCubicC2(double t)const
1168 {
1169    return ((theCubicAdjustableParameter + 2.0) * t * t * t -
1170            (theCubicAdjustableParameter + 3.0) * t * t + 1.0);
1171 }
1172 
getCubicC3(double t) const1173 double ossimResampler::getCubicC3(double t)const
1174 {
1175    return ((theCubicAdjustableParameter * t * t * t) -
1176            (2.0f * theCubicAdjustableParameter * t * t) +
1177            (theCubicAdjustableParameter * t));
1178 }
1179 
loadState(const ossimKeywordlist & kwl,const char * prefix)1180 bool ossimResampler::loadState(const ossimKeywordlist& kwl,
1181                                const char* prefix)
1182 {
1183    const char* resamplerType = kwl.find(prefix, RESAMPLER_CONVOLUTION_TYPE_KW);
1184    const char* scaleX        = kwl.find(prefix, RESAMPLER_SCALE_X_KW);
1185    const char* scaleY        = kwl.find(prefix, RESAMPLER_SCALE_Y_KW);
1186    const char* cubicParameter= kwl.find(prefix, RESAMPLER_CUBIC_PARAMETER_KW);
1187 
1188    if(cubicParameter)
1189    {
1190       theCubicAdjustableParameter = ossimString(cubicParameter).toDouble();
1191       if(theCubicAdjustableParameter < -1) theCubicAdjustableParameter = -1;
1192       if(theCubicAdjustableParameter > 0)  theCubicAdjustableParameter = 0;
1193    }
1194    else
1195    {
1196       theCubicAdjustableParameter = -.5;
1197    }
1198    if(resamplerType)
1199    {
1200       ossimString test =ossimString(resamplerType).upcase().trim();
1201 
1202       if( test == "BICUBIC")
1203       {
1204          setResamplerType(ossimResampler::ossimResampler_BICUBIC);
1205       }
1206       else if( test == "BILINEAR")
1207       {
1208          setResamplerType(ossimResampler::ossimResampler_BILINEAR);
1209       }
1210       else
1211       {
1212          setResamplerType(ossimResampler::ossimResampler_NEAREST_NEIGHBOR);
1213       }
1214    }
1215    if(scaleX&&scaleY)
1216    {
1217       setRatio(ossimDpt(ossimString(scaleX).toDouble(),
1218                         ossimString(scaleY).toDouble()));
1219    }
1220    allocateWeightTable();
1221    generateWeightTable();
1222 
1223    return ossimConnectableObject::loadState(kwl, prefix);
1224 }
1225 
saveState(ossimKeywordlist & kwl,const char * prefix) const1226 bool ossimResampler::saveState(ossimKeywordlist& kwl,
1227                                const char* prefix)const
1228 {
1229    ossimString resamplerType;
1230    if(getResamplerType() == ossimResampler_BICUBIC)
1231    {
1232       resamplerType = "BICUBIC";
1233    }
1234    else if(getResamplerType() == ossimResampler_BILINEAR)
1235    {
1236       resamplerType = "BILINEAR";
1237    }
1238    else
1239    {
1240       resamplerType = "NEAREST_NEIGHBOR";
1241    }
1242    kwl.add(prefix,
1243            RESAMPLER_CONVOLUTION_TYPE_KW,
1244            resamplerType.c_str(),
1245            true);
1246 
1247    kwl.add(prefix,
1248            RESAMPLER_SCALE_X_KW,
1249            theOutputToInputRatio.x,
1250            true);
1251 
1252    kwl.add(prefix,
1253            RESAMPLER_SCALE_Y_KW,
1254            theOutputToInputRatio.y,
1255            true);
1256 
1257    kwl.add(prefix,
1258            RESAMPLER_CUBIC_PARAMETER_KW,
1259            theCubicAdjustableParameter,
1260            true);
1261 
1262    return ossimConnectableObject::saveState(kwl, prefix);
1263 }
1264