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