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: ossimScaleFilter.cpp 21631 2012-09-06 18:10:55Z dburken $
12 #include <ossim/imaging/ossimScaleFilter.h>
13 #include <ossim/imaging/ossimFilter.h>
14 #include <ossim/imaging/ossimImageGeometry.h>
15 #include <ossim/imaging/ossimDiscreteConvolutionKernel.h>
16 #include <ossim/imaging/ossimImageDataFactory.h>
17 #include <ossim/projection/ossimProjectionFactoryRegistry.h>
18 #include <ossim/projection/ossimMapProjection.h>
19 #include <ossim/base/ossimKeywordNames.h>
20
21 using namespace std;
22
23 RTTI_DEF1(ossimScaleFilter, "ossimScaleFilter", ossimImageSourceFilter);
24
25 //**************************************************************************************************
ossimScaleFilter()26 ossimScaleFilter::ossimScaleFilter()
27 :ossimImageSourceFilter(),
28 m_BlankTile(NULL),
29 m_Tile(NULL),
30 m_MinifyFilter(NULL),
31 m_MagnifyFilter(NULL),
32 m_MinifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR),
33 m_MagnifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR),
34 m_ScaleFactor(1.0, 1.0),
35 m_InverseScaleFactor(1.0, 1.0),
36 m_TileSize(64, 64),
37 m_BlurFactor(1.0)
38 {
39 m_InputRect.makeNan();
40 m_MinifyFilter = new ossimNearestNeighborFilter();
41 m_MagnifyFilter = new ossimNearestNeighborFilter();
42 }
43
44 //**************************************************************************************************
ossimScaleFilter(ossimImageSource * inputSource,const ossimDpt & scaleFactor)45 ossimScaleFilter::ossimScaleFilter(ossimImageSource* inputSource,
46 const ossimDpt& scaleFactor)
47 :ossimImageSourceFilter(inputSource),
48 m_BlankTile(NULL),
49 m_Tile(NULL),
50 m_MinifyFilter(NULL),
51 m_MagnifyFilter(NULL),
52 m_MinifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR),
53 m_MagnifyFilterType(ossimScaleFilter_NEAREST_NEIGHBOR),
54 m_ScaleFactor(scaleFactor),
55 m_TileSize(64, 64),
56 m_BlurFactor(1.0)
57 {
58 m_InputRect.makeNan();
59 m_MinifyFilter = new ossimNearestNeighborFilter();
60 m_MagnifyFilter = new ossimNearestNeighborFilter();
61 }
62
63 //**************************************************************************************************
~ossimScaleFilter()64 ossimScaleFilter::~ossimScaleFilter()
65 {
66 if(m_MinifyFilter)
67 {
68 delete m_MinifyFilter;
69 m_MinifyFilter = NULL;
70 }
71
72 if(m_MagnifyFilter)
73 {
74 delete m_MagnifyFilter;
75 m_MagnifyFilter = NULL;
76 }
77 }
78
79 //**************************************************************************************************
getTile(const ossimIrect & tileRect,ossim_uint32 resLevel)80 ossimRefPtr<ossimImageData> ossimScaleFilter::getTile(
81 const ossimIrect& tileRect, ossim_uint32 resLevel)
82 {
83
84 if((!isSourceEnabled())||
85 (!theInputConnection)||
86 ((m_ScaleFactor.x == 1.0)&&
87 (m_ScaleFactor.y == 1.0)&&
88 (m_BlurFactor == 1.0)))
89 {
90 return ossimImageSourceFilter::getTile(tileRect, resLevel);
91 }
92 if(!m_Tile.valid())
93 {
94 allocate();
95 }
96
97 if(!m_Tile)
98 {
99 return ossimImageSourceFilter::getTile(tileRect, resLevel);
100 }
101
102 m_Tile->makeBlank();
103
104
105 ossimIrect imageRect = tileRect*m_InverseScaleFactor;
106
107 m_Tile->setImageRectangle(tileRect);
108 m_BlankTile->setImageRectangle(tileRect);
109
110
111 double xSupport;
112 double ySupport;
113
114 getSupport(xSupport, ySupport);
115
116 ossimIpt deltaPt;
117 deltaPt.x = (ossim_int32)ceil(xSupport);
118 deltaPt.y = (ossim_int32)ceil(ySupport);
119
120 imageRect = ossimIrect(imageRect.ul().x - (deltaPt.x),
121 imageRect.ul().y - (deltaPt.y),
122 imageRect.lr().x + (deltaPt.x),
123 imageRect.lr().y + (deltaPt.y));
124
125
126 runFilter(imageRect, tileRect);
127
128 m_Tile->validate();
129
130 return m_Tile;
131 }
132
133 //**************************************************************************************************
runFilter(const ossimIrect & imageRect,const ossimIrect & viewRect)134 void ossimScaleFilter::runFilter(const ossimIrect& imageRect,
135 const ossimIrect& viewRect)
136 {
137 switch(m_Tile->getScalarType())
138 {
139 case OSSIM_UINT8:
140 {
141 runFilterTemplate((ossim_uint8)0,
142 imageRect,
143 viewRect);
144 break;
145 }
146 case OSSIM_USHORT11:
147 case OSSIM_USHORT12:
148 case OSSIM_USHORT13:
149 case OSSIM_USHORT14:
150 case OSSIM_USHORT15:
151 case OSSIM_UINT16:
152 {
153 runFilterTemplate((ossim_uint16)0,
154 imageRect,
155 viewRect);
156 break;
157 }
158 case OSSIM_SINT16:
159 {
160 runFilterTemplate((ossim_sint16)0,
161 imageRect,
162 viewRect);
163 break;
164 }
165 case OSSIM_UINT32:
166 {
167 runFilterTemplate((ossim_uint32)0,
168 imageRect,
169 viewRect);
170 break;
171 }
172 case OSSIM_DOUBLE:
173 case OSSIM_NORMALIZED_DOUBLE:
174 {
175 runFilterTemplate((ossim_float64)0,
176 imageRect,
177 viewRect);
178 break;
179 }
180 case OSSIM_FLOAT:
181 case OSSIM_NORMALIZED_FLOAT:
182 {
183 runFilterTemplate((ossim_float32)0,
184 imageRect,
185 viewRect);
186 break;
187 }
188 default:
189 break;
190 }
191 }
192
193 //**************************************************************************************************
194 template <class T>
runFilterTemplate(T dummy,const ossimIrect & imageRect,const ossimIrect & viewRect)195 void ossimScaleFilter::runFilterTemplate(T dummy,
196 const ossimIrect& imageRect,
197 const ossimIrect& viewRect)
198 {
199 ossimRefPtr<ossimImageData> inputData =
200 theInputConnection->getTile(imageRect);
201
202 if(!inputData.valid() ||
203 !inputData->getBuf() ||
204 (inputData->getDataObjectStatus() == OSSIM_EMPTY))
205 {
206 return;
207 }
208
209 ossim_int32 h = imageRect.height();
210 ossimRefPtr<ossimImageData> tempData =
211 ossimImageDataFactory::instance()->create(NULL,
212 inputData->getScalarType(),
213 inputData->getNumberOfBands(),
214 viewRect.width(),
215 h);
216 tempData->setOrigin(ossimIpt(viewRect.ul().x,
217 imageRect.ul().y));
218
219 tempData->initialize();
220
221 if((m_ScaleFactor.x != 1.0)||
222 (m_BlurFactor != 1.0))
223 {
224 runHorizontalFilterTemplate(dummy,
225 inputData,
226 tempData);
227 tempData->validate();
228 }
229 else
230 {
231 tempData->loadTile(inputData.get());
232 }
233
234 if((m_ScaleFactor.y != 1.0)||
235 (m_BlurFactor != 1.0))
236 {
237 runVerticalFilterTemplate(dummy,
238 tempData,
239 m_Tile);
240 }
241 else
242 {
243 m_Tile->loadTile(tempData.get());
244 }
245
246 m_Tile->validate();
247 }
248
249 //**************************************************************************************************
getBoundingRect(ossim_uint32 resLevel) const250 ossimIrect ossimScaleFilter::getBoundingRect(ossim_uint32 resLevel)const
251 {
252 ossimIrect result = ossimImageSourceFilter::getBoundingRect(resLevel);
253
254 if(!result.hasNans())
255 {
256 result *= m_ScaleFactor;
257 }
258
259 return result;
260 }
261
262 //**************************************************************************************************
setFilterType(ossimScaleFilterType filterType)263 void ossimScaleFilter::setFilterType(ossimScaleFilterType filterType)
264 {
265 setFilterType(filterType, filterType);
266 }
267
268
269 //**************************************************************************************************
setFilterType(ossimScaleFilterType minifyFilterType,ossimScaleFilterType magnifyFilterType)270 void ossimScaleFilter::setFilterType(ossimScaleFilterType minifyFilterType,
271 ossimScaleFilterType magnifyFilterType)
272 {
273 if(m_MinifyFilter)
274 {
275 delete m_MinifyFilter;
276 m_MinifyFilter = NULL;
277 }
278 if(m_MagnifyFilter)
279 {
280 delete m_MagnifyFilter;
281 m_MagnifyFilter = NULL;
282 }
283
284 m_MinifyFilterType = minifyFilterType;
285 m_MagnifyFilterType = magnifyFilterType;
286
287 m_MinifyFilter = createNewFilter(minifyFilterType, m_MinifyFilterType);
288 m_MagnifyFilter = createNewFilter(magnifyFilterType, m_MagnifyFilterType);
289 }
290
291 //**************************************************************************************************
createNewFilter(ossimScaleFilterType filterType,ossimScaleFilterType & result)292 ossimFilter* ossimScaleFilter::createNewFilter(ossimScaleFilterType filterType,
293 ossimScaleFilterType& result)
294 {
295 switch(filterType)
296 {
297 case ossimScaleFilter_NEAREST_NEIGHBOR:
298 {
299 return new ossimNearestNeighborFilter();
300 }
301 case ossimScaleFilter_BOX:
302 {
303 return new ossimBoxFilter();
304 }
305 case ossimScaleFilter_GAUSSIAN:
306 {
307 return new ossimGaussianFilter();
308 }
309 case ossimScaleFilter_CUBIC:
310 {
311 return new ossimCubicFilter();
312 }
313 case ossimScaleFilter_HANNING:
314 {
315 return new ossimHanningFilter();
316 }
317 case ossimScaleFilter_HAMMING:
318 {
319 return new ossimHammingFilter();
320 }
321 case ossimScaleFilter_LANCZOS:
322 {
323 return new ossimLanczosFilter();
324 }
325 case ossimScaleFilter_CATROM:
326 {
327 return new ossimCatromFilter();
328 }
329 case ossimScaleFilter_MITCHELL:
330 {
331 return new ossimMitchellFilter();
332 }
333 case ossimScaleFilter_BLACKMAN:
334 {
335 return new ossimBlackmanFilter();
336 }
337 case ossimScaleFilter_BLACKMAN_SINC:
338 {
339 return new ossimBlackmanSincFilter();
340 }
341 case ossimScaleFilter_BLACKMAN_BESSEL:
342 {
343 return new ossimBlackmanBesselFilter();
344 }
345 case ossimScaleFilter_QUADRATIC:
346 {
347 return new ossimQuadraticFilter();
348 }
349 case ossimScaleFilter_TRIANGLE:
350 {
351 return new ossimTriangleFilter();
352 }
353 case ossimScaleFilter_HERMITE:
354 {
355 return new ossimHermiteFilter();
356 }
357
358 }
359
360 result = ossimScaleFilter_NEAREST_NEIGHBOR;
361 return new ossimNearestNeighborFilter();
362 }
363
364 //**************************************************************************************************
setScaleFactor(const ossimDpt & scale)365 void ossimScaleFilter::setScaleFactor(const ossimDpt& scale)
366 {
367 m_ScaleFactor = scale;
368 if(fabs(m_ScaleFactor.x) <= FLT_EPSILON)
369 {
370 m_ScaleFactor.x = 1.0;
371 }
372 if(fabs(m_ScaleFactor.y) <= FLT_EPSILON)
373 {
374 m_ScaleFactor.y = 1.0;
375 }
376
377 m_InverseScaleFactor.x = 1.0/m_ScaleFactor.x;
378 m_InverseScaleFactor.y = 1.0/m_ScaleFactor.y;
379
380 // A change in the scale factor implies a change to the image geometry. If one has been created
381 // it needs to be modified:
382 updateGeometry();
383 }
384
385
386 //**************************************************************************************************
runHorizontalFilterTemplate(T,const ossimRefPtr<ossimImageData> & input,ossimRefPtr<ossimImageData> & output)387 template <class T> void ossimScaleFilter::runHorizontalFilterTemplate(
388 T /* dummy */,
389 const ossimRefPtr<ossimImageData>& input,
390 ossimRefPtr<ossimImageData>& output)
391 {
392 ossimIrect viewRect = output->getImageRectangle();
393 ossimIrect imageRect = input->getImageRectangle();
394 ossim_int32 vw = viewRect.width();
395 ossim_int32 vh = viewRect.height();
396 ossim_int32 iw = imageRect.width();
397 ossimIpt origin(viewRect.ul());
398 ossimIpt imageOrigin(imageRect.ul());
399 ossimIpt inputUl = m_InputRect.ul();
400 ossimIpt inputLr = m_InputRect.lr();
401
402 double scale = 0.0;
403 double support = 0.0;
404 ossim_int32 x = 0;
405 ossim_int32 y = 0;
406 ossim_int32 start = 0;
407 ossim_int32 stop = 0;
408 ossim_int32 kernelIdx = 0;
409 const ossimFilter* filter = getHorizontalFilter();
410 ossim_float64 center = 0.0;
411 ossim_int32 bandIdx = 0;
412 ossim_int32 numberOfBands = m_Tile->getNumberOfBands();
413
414 scale = m_BlurFactor*ossim::max(1.0/m_ScaleFactor.x, 1.0);
415
416 support=scale*filter->getSupport();
417 if (support <= 0.5)
418 {
419 support = 0.5 + FLT_EPSILON;
420 scale = 1.0;
421 }
422 scale=1.0/scale;
423 for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx)
424 {
425 T* imageBuf = (T*)input->getBuf(bandIdx);
426 T* viewBuf = (T*)output->getBuf(bandIdx);
427 T np = (T)input->getNullPix(bandIdx);
428 T outNp = (T)output->getNullPix(bandIdx);
429 T outMinPix = (T)output->getMinPix(bandIdx);
430 T outMaxPix = (T)output->getMaxPix(bandIdx);
431
432 for(x = 0; x < vw; ++x)
433 {
434 center=(origin.x + x+ .5)/m_ScaleFactor.x;
435 start=ossim::max((ossim_int32)ossim::round<int>(center-support), (ossim_int32)inputUl.x);
436 stop=ossim::min((ossim_int32)ossim::round<int>(center+support), (ossim_int32)inputLr.x);
437 ossim_int32 delta = stop-start;
438 if (delta <= 0)
439 {
440 break;
441 }
442 vector<double> kernel(delta);
443 double density=0.0;
444
445 for(kernelIdx = 0; kernelIdx < delta; ++kernelIdx)
446 {
447 double t = scale*(start + kernelIdx -
448 center + .5);
449 kernel[kernelIdx] = filter->filter(t,
450 filter->getSupport());
451 density += kernel[kernelIdx];
452 }
453 if ((density != 0.0) && (density != 1.0))
454 {
455 /*
456 Normalize.
457 */
458 density=1.0/density;
459 for (kernelIdx=0; kernelIdx < delta; kernelIdx++)
460 kernel[kernelIdx]*=density;
461 }
462 ossim_int32 offset = start - imageOrigin.x;
463
464 T* xptr = imageBuf + offset;
465 T* xCenterptr = imageBuf + offset;
466 T* outptr = viewBuf + x;
467
468 for(y = 0; y < vh; ++y)
469 {
470 double result = 0.0;
471 density = 0.0;
472 if((*xCenterptr) == np)
473 {
474 *outptr = outNp;
475 }
476 else
477 {
478 for(kernelIdx = 0; kernelIdx < (int)kernel.size(); ++kernelIdx)
479 {
480 if((*xptr != np)&&
481 (kernel[kernelIdx] != 0.0))
482 {
483 result += ((double)(*(xptr+kernelIdx))*kernel[kernelIdx]);
484 density += kernel[kernelIdx];
485 }
486 }
487 if(density != 0.0)
488 {
489 result /= density;
490
491 if(result < outMinPix) result = outMinPix;
492 if(result > outMaxPix) result = outMaxPix;
493
494 *outptr = (T)result;
495 }
496 else
497 {
498 *outptr = outNp;
499 }
500 }
501 xCenterptr += iw;
502 xptr += iw;
503 outptr += vw;
504 }
505 }
506 }
507 }
508
509 //**************************************************************************************************
runVerticalFilterTemplate(T,const ossimRefPtr<ossimImageData> & input,ossimRefPtr<ossimImageData> & output)510 template <class T> void ossimScaleFilter::runVerticalFilterTemplate(
511 T /* dummy */,
512 const ossimRefPtr<ossimImageData>& input,
513 ossimRefPtr<ossimImageData>& output)
514 {
515 ossimIrect viewRect = output->getImageRectangle();
516 ossimIrect imageRect = input->getImageRectangle();
517 ossim_int32 vw = viewRect.width();
518 ossim_int32 vh = viewRect.height();
519 ossim_int32 iw = imageRect.width();
520 ossimIpt origin(viewRect.ul());
521 ossimIpt imageOrigin(imageRect.ul());
522 ossimIpt inputUl = m_InputRect.ul();
523 ossimIpt inputLr = m_InputRect.lr();
524 double scale = 0.0;
525 double support = 0.0;
526 ossim_int32 x = 0;
527 ossim_int32 y = 0;
528 ossim_int32 start = 0;
529 ossim_int32 stop = 0;
530 ossim_int32 kernelIdx = 0;
531 const ossimFilter* filter = getVerticalFilter();
532 ossim_float64 center = 0.0;
533 ossim_int32 bandIdx = 0;
534 ossim_int32 numberOfBands = m_Tile->getNumberOfBands();
535
536 scale = m_BlurFactor*ossim::max(1.0/m_ScaleFactor.y, 1.0);
537
538 support=scale*filter->getSupport();
539 if (support <= 0.5)
540 {
541 support = .5 + FLT_EPSILON;
542 scale = 1.0;
543 }
544 scale=1.0/scale;
545
546 for(bandIdx = 0; bandIdx < numberOfBands; ++bandIdx)
547 {
548 T* imageBuf = (T*)input->getBuf(bandIdx);
549 T* viewBuf = (T*)output->getBuf(bandIdx);
550 T np = (T)input->getNullPix(bandIdx);
551 T outNp = (T)output->getNullPix(bandIdx);
552 T outMinPix = (T)output->getMinPix(bandIdx);
553 T outMaxPix = (T)output->getMaxPix(bandIdx);
554
555 for(y = 0; y < vh; ++y)
556 {
557 center=(double) ((y + origin.y+0.5)/m_ScaleFactor.y);
558 start=ossim::max((ossim_int32)ossim::round<int>(center-support), (ossim_int32)inputUl.y);
559 stop=ossim::min((ossim_int32)ossim::round<int>(center+support), (ossim_int32)inputLr.y);
560 ossim_int32 delta = stop-start;
561 if (delta <= 0)
562 {
563 break;
564 }
565 vector<double> kernel(delta);
566 double density = 0.0;
567 for(kernelIdx = 0; kernelIdx < delta; ++kernelIdx)
568 {
569 kernel[kernelIdx] = filter->filter(scale*(start + kernelIdx - center + .5),
570 filter->getSupport());
571 density += kernel[kernelIdx];
572 }
573 if ((density != 0.0) && (density != 1.0))
574 {
575 /*
576 Normalize.
577 */
578 density=1.0/density;
579 for (kernelIdx=0; kernelIdx < delta; kernelIdx++)
580 kernel[kernelIdx]*=density;
581 }
582
583 ossim_int32 offset = ((start - imageOrigin.y)*iw);
584 ossim_int32 offsetCenter = ((((ossim_int32)center) - imageOrigin.y)*iw);
585
586 for(x = 0; x < vw; ++x)
587 {
588 T* yptr = imageBuf + offset + x;
589 T* yCenterptr = imageBuf + offsetCenter + x;
590 double result = 0.0;
591 density = 0.0;
592
593 if((*yCenterptr) == np)
594 {
595 *viewBuf = outNp;
596 }
597 else
598 {
599 for(kernelIdx = 0; kernelIdx < delta; ++kernelIdx)
600 {
601 if((*yptr != np)&&
602 (kernel[kernelIdx] != 0.0))
603 {
604 result += ((*yptr)*kernel[kernelIdx]);
605 density += kernel[kernelIdx];
606 }
607 yptr += iw;
608 }
609 if(density != 0.0)
610 {
611 result /= density;
612
613 if(result < outMinPix) result = outMinPix;
614 if(result > outMaxPix) result = outMaxPix;
615
616 *viewBuf = (T)result;
617 }
618 else
619 {
620 *viewBuf = outNp;
621 }
622 }
623 ++viewBuf;
624 }
625 }
626 }
627 }
628
629 //**************************************************************************************************
initialize()630 void ossimScaleFilter::initialize()
631 {
632 ossimImageSourceFilter::initialize();
633
634 // Force an allocate next getTile.
635 m_Tile = NULL;
636 m_BlankTile = NULL;
637 m_InputRect.makeNan();
638 }
639
640 //**************************************************************************************************
allocate()641 void ossimScaleFilter::allocate()
642 {
643 m_Tile = NULL;
644 m_BlankTile = NULL;
645 m_InputRect.makeNan();
646
647 if(theInputConnection&&isSourceEnabled())
648 {
649 m_Tile = ossimImageDataFactory::instance()->create(this, this);
650 m_BlankTile = ossimImageDataFactory::instance()->create(this, this);
651
652 m_Tile->initialize();
653
654 m_InputRect = theInputConnection->getBoundingRect();
655 }
656 }
657
658 //**************************************************************************************************
659 // Returns a pointer reference to the active image geometry at this filter. The input source
660 // geometry is modified, so we need to maintain our own geometry object as a data member.
661 //**************************************************************************************************
getImageGeometry()662 ossimRefPtr<ossimImageGeometry> ossimScaleFilter::getImageGeometry()
663 {
664 // Have we already defined our own geometry? Return it if so:
665 if (m_ScaledGeometry.valid()) return m_ScaledGeometry;
666
667 // Otherwise we'll need to establish a geometry based on the input connection:
668 if(theInputConnection)
669 {
670 // Fetch the map projection of the input image if it exists:
671 ossimRefPtr<ossimImageGeometry> inputGeom = theInputConnection->getImageGeometry();
672
673 // If trivial case of identity scale, just pass along the input connection's geometry:
674 if ((m_ScaleFactor.x == 1.0) && (m_ScaleFactor.y == 1.0))
675 return inputGeom;
676
677 // Need to create a copy of the input geom and modify it as our own, then pass that:
678 if ( inputGeom.valid() )
679 {
680 m_ScaledGeometry = new ossimImageGeometry(*inputGeom);
681 updateGeometry();
682
683 // Return the modified geometry:
684 return m_ScaledGeometry;
685 }
686 }
687
688 // No geometry defined, return NULL pointer:
689 return ossimRefPtr<ossimImageGeometry>();
690 }
691
692 //**************************************************************************************************
scaleRect(const ossimIrect input,const ossimDpt & scaleFactor) const693 ossimIrect ossimScaleFilter::scaleRect(const ossimIrect input,
694 const ossimDpt& scaleFactor)const
695 {
696 ossimIpt origin(ossim::round<int>(input.ul().x*scaleFactor.x),
697 ossim::round<int>(input.ul().y*scaleFactor.y));
698 ossim_int32 w = ossim::round<int>(input.width()*scaleFactor.x);
699 ossim_int32 h = ossim::round<int>(input.height()*scaleFactor.y);
700
701 if(w < 1) w = 1;
702 if(h < 1) h = 1;
703
704 return ossimIrect(origin.x,
705 origin.y,
706 origin.x + (w-1),
707 origin.y + (h-1));
708 }
709
710 //**************************************************************************************************
getFilterTypeAsString(ossimScaleFilterType type) const711 ossimString ossimScaleFilter::getFilterTypeAsString(ossimScaleFilterType type)const
712 {
713 switch(type)
714 {
715 case ossimScaleFilter_NEAREST_NEIGHBOR:
716 {
717 return "nearest_neighbor";
718 }
719 case ossimScaleFilter_BOX:
720 {
721 return "box";
722 }
723 case ossimScaleFilter_GAUSSIAN:
724 {
725 return "gaussian";
726 }
727 case ossimScaleFilter_CUBIC:
728 {
729 return "cubic";
730 }
731 case ossimScaleFilter_HANNING:
732 {
733 return "hanning";
734 }
735 case ossimScaleFilter_HAMMING:
736 {
737 return "hamming";
738 }
739 case ossimScaleFilter_LANCZOS:
740 {
741 return "lanczos";
742 }
743 case ossimScaleFilter_MITCHELL:
744 {
745 return "mitchell";
746 }
747 case ossimScaleFilter_CATROM:
748 {
749 return "catrom";
750 }
751 case ossimScaleFilter_BLACKMAN:
752 {
753 return "blackman";
754 }
755 case ossimScaleFilter_BLACKMAN_SINC:
756 {
757 return "blackman_sinc";
758 }
759 case ossimScaleFilter_BLACKMAN_BESSEL:
760 {
761 return "blackman_bessel";
762 }
763 case ossimScaleFilter_QUADRATIC:
764 {
765 return "quadratic";
766 }
767 case ossimScaleFilter_TRIANGLE:
768 {
769 return "triangle";
770 }
771 case ossimScaleFilter_HERMITE:
772 {
773 return "hermite";
774 }
775 }
776
777 return "nearest_neighbor";
778 }
779
780 //**************************************************************************************************
getFilterType(const ossimString & type) const781 ossimScaleFilter::ossimScaleFilterType ossimScaleFilter::getFilterType(const ossimString& type)const
782 {
783 ossimString typeUpper = type;
784 typeUpper = typeUpper.upcase();
785
786 if(typeUpper.contains("BOX"))
787 {
788 return ossimScaleFilter_BOX;
789 }
790 else if(typeUpper.contains("NEAREST_NEIGHBOR"))
791 {
792 return ossimScaleFilter_NEAREST_NEIGHBOR;
793 }
794 else if(typeUpper.contains("GAUSSIAN"))
795 {
796 return ossimScaleFilter_GAUSSIAN;
797 }
798 else if(typeUpper.contains("HANNING"))
799 {
800 return ossimScaleFilter_HANNING;
801 }
802 else if(typeUpper.contains("HAMMING"))
803 {
804 return ossimScaleFilter_HAMMING;
805 }
806 else if(typeUpper.contains("LANCZOS"))
807 {
808 return ossimScaleFilter_LANCZOS;
809 }
810 else if(typeUpper.contains("MITCHELL"))
811 {
812 return ossimScaleFilter_MITCHELL;
813 }
814 else if(typeUpper.contains("CATROM"))
815 {
816 return ossimScaleFilter_CATROM;
817 }
818 else if(typeUpper.contains("CUBIC"))
819 {
820 return ossimScaleFilter_CUBIC;
821 }
822 else if(typeUpper.contains("BLACKMAN_BESSEL"))
823 {
824 return ossimScaleFilter_BLACKMAN_BESSEL;
825 }
826 else if(typeUpper.contains("BLACKMAN_SINC"))
827 {
828 return ossimScaleFilter_BLACKMAN_SINC;
829 }
830 else if(typeUpper.contains("BLACKMAN"))
831 {
832 return ossimScaleFilter_BLACKMAN;
833 }
834 else if(typeUpper.contains("QUADRATIC"))
835 {
836 return ossimScaleFilter_QUADRATIC;
837 }
838 else if(typeUpper.contains("TRIANGLE"))
839 {
840 return ossimScaleFilter_TRIANGLE;
841 }
842 else if(typeUpper.contains("HERMITE"))
843 {
844 return ossimScaleFilter_HERMITE;
845 }
846
847 return ossimScaleFilter_NEAREST_NEIGHBOR;
848 }
849
850 //**************************************************************************************************
getSupport(double & x,double & y)851 void ossimScaleFilter::getSupport(double& x, double& y)
852 {
853 const ossimFilter* horizontalFilter = getHorizontalFilter();
854 const ossimFilter* verticalFilter = getVerticalFilter();
855
856 x = m_BlurFactor*ossim::max(1.0/m_ScaleFactor.x, 1.0)*
857 horizontalFilter->getSupport();
858 y = m_BlurFactor*ossim::max(1.0/m_ScaleFactor.y, 1.0)*
859 verticalFilter->getSupport();
860 }
861
862 //**************************************************************************************************
getHorizontalFilter() const863 const ossimFilter* ossimScaleFilter::getHorizontalFilter()const
864 {
865 if(m_ScaleFactor.x < 1)
866 {
867 return m_MinifyFilter;
868 }
869
870 return m_MagnifyFilter;
871 }
872
873 //**************************************************************************************************
getVerticalFilter() const874 const ossimFilter* ossimScaleFilter::getVerticalFilter()const
875 {
876 if(m_ScaleFactor.y < 1)
877 {
878 return m_MinifyFilter;
879 }
880
881 return m_MagnifyFilter;
882 }
883
884
885
886 //**************************************************************************************************
saveState(ossimKeywordlist & kwl,const char * prefix) const887 bool ossimScaleFilter::saveState(ossimKeywordlist& kwl, const char* prefix)const
888 {
889 kwl.add(prefix,
890 ossimKeywordNames::SCALE_X_KW,
891 m_ScaleFactor.x,
892 true);
893 kwl.add(prefix,
894 ossimKeywordNames::SCALE_Y_KW,
895 m_ScaleFactor.y,
896 true);
897 kwl.add(prefix,
898 "minify_type",
899 getFilterTypeAsString(m_MinifyFilterType),
900 true);
901 kwl.add(prefix,
902 "magnify_type",
903 getFilterTypeAsString(m_MagnifyFilterType),
904 true);
905
906 return ossimImageSourceFilter::saveState(kwl, prefix);
907 }
908
909 //**************************************************************************************************
loadState(const ossimKeywordlist & kwl,const char * prefix)910 bool ossimScaleFilter::loadState(const ossimKeywordlist& kwl,
911 const char* prefix)
912 {
913 ossimString scalex = kwl.find(prefix,
914 ossimKeywordNames::SCALE_X_KW);
915 ossimString scaley = kwl.find(prefix,
916 ossimKeywordNames::SCALE_Y_KW);
917 ossimString minify = kwl.find(prefix,
918 "minify_type");
919 ossimString magnify = kwl.find(prefix,
920 "magnify_type");
921
922 m_ScaleFactor.x = scalex.toDouble();
923 m_ScaleFactor.y = scaley.toDouble();
924
925 if(fabs(m_ScaleFactor.x) <= FLT_EPSILON)
926 {
927 m_ScaleFactor.x = 1.0;
928 }
929 if(fabs(m_ScaleFactor.y) <= FLT_EPSILON)
930 {
931 m_ScaleFactor.y = 1.0;
932 }
933
934 m_InverseScaleFactor.x = 1.0/m_ScaleFactor.x;
935 m_InverseScaleFactor.y = 1.0/m_ScaleFactor.y;
936
937 setFilterType(getFilterType(minify),
938 getFilterType(magnify));
939
940 // A change in the scale factor implies a change to the image geometry. If one has been created
941 // it needs to be modified:
942 updateGeometry();
943
944 return ossimImageSourceFilter::loadState(kwl, prefix);
945 }
946
947 //**************************************************************************************************
948 //! If this object is maintaining an ossimImageGeometry, this method needs to be called after
949 //! a scale change so that the geometry's projection is modified accordingly.
950 //**************************************************************************************************
updateGeometry()951 void ossimScaleFilter::updateGeometry()
952 {
953 if (m_ScaledGeometry.valid())
954 {
955 // Modify the image geometry's projection with the scale factor before returning geom:
956 ossimProjection* proj = m_ScaledGeometry->getProjection();
957 ossimMapProjection* mapProj = PTR_CAST(ossimMapProjection, proj);
958 if(mapProj)
959 mapProj->applyScale(m_InverseScaleFactor, true);
960 }
961 }
962