1 //  ------------------------------------------------------------------------------------------------
2 //
3 //                    IMAGE VIEW TOOLKIT
4 //
5 //  This source code is the property of FITS Imaging inc.
6 //
7 //  MODULE    : AdvancedIVUE
8 //  LANGUAGE  : C++
9 //  AUTHOR    : Philippe BOSSUT
10 //  DATE    : Mardi 23 Novembre 1993
11 //  DESCRIPTION :
12 //  COMMENT   :
13 //      SCCSID          : @(#)viewimg.cpp 1.4 12:48:05 01 Jul 1997
14 //  ------------------------------------------------------------------------------------------------
15 //  Copyright (c) 1999 Digital Imaging Group, Inc.
16 //  For conditions of distribution and use, see copyright notice
17 //  in Flashpix.h
18 //  ------------------------------------------------------------------------------------------------
19   #include "viewimg.h"
20 //  ------------------------------------------------------------------------------------------------
21 
22 //  Includes
23 //  --------
24 
25 #ifndef Debug_h
26   #include  "debug.h"
27 #endif
28 #ifndef Numbers_h
29   #include  "numbers.h"
30 #endif
31 
32 #ifndef PRIImage_h
33   #include "priimage.h"
34 #endif
35 
36 #ifndef ColorTwist_h
37   #include "coltwist.h"
38 #endif
39 
40 #ifndef FPXImageView_h
41   #include  "fpximgvw.h"
42 #endif
43 
44 #ifndef IVUEToolkit_h
45   #include  "ri_lib.h"
46 #endif
47 
48 #ifndef FileFlashPixIO_h
49   #include  "f_fpxio.h"
50 #endif
51 
52 //  Constants
53 //  ---------
54 
55 //  Variables
56 //  ---------
57 
58 //  ------------------------------------------------------------------------------------------------
59 #ifdef macintosh
60   #pragma segment AdvancedIVUE
61 #endif
62 //  ------------------------------------------------------------------------------------------------
63 
64 //  ------------------------------------------------------------------------------------------------
65 //  Internal Functions
66 //  ------------------------------------------------------------------------------------------------
67 
68 
69 //  ------------------------------------------------------------------------------------------------
70 //  Methods of the ViewWorld class
71 //  ------------------------------------------------------------------------------------------------
72 
73 
ViewWorld(float width,float height,Pixel color)74 ViewWorld::ViewWorld (float width, float height, Pixel color) : state ((float)0.0, (float)0.0, width, height)
75 {
76   // Init World size
77   this->height    = Toolkit_ConvertToMm(height);
78   this->width     = Toolkit_ConvertToMm(width);
79 
80   // Set the color of the System background
81   GtheSystemToolkit->SetBackgroundColor (color,SPACE_32_BITS_RGB);
82 
83   // Init ViewImage list
84   first       = NULL;
85   last        = NULL;
86   current       = NULL;
87 }
88 
89 
~ViewWorld()90 ViewWorld::~ViewWorld ()
91 {
92   ViewImage*  next;
93 
94   // Delete all ViewImage within World
95   current = first;
96   while (current) {
97     next = current->next;
98     delete current;
99     current = next;
100   }
101 }
102 
103 
AddImage(ref_FicNom refNom)104 FPXStatus ViewWorld::AddImage (ref_FicNom refNom)
105 {
106   register FPXStatus status = FPX_OK;
107   ViewImage* image;
108 
109   // Open Image file (among other things�)
110   if ((image = new PFlashPixImageView (refNom,NULL)) == NULL) {
111     status = FPX_FILE_NOT_FOUND;    // Best guess as to why this failed
112     goto end;
113   }
114   // Test if Image file is successfully opened, exit if not
115   if (image->FileStatus() != 0) {
116     delete image;
117     image = NULL;
118     status = FPX_FILE_NOT_OPEN_ERROR;
119     goto end;
120   }
121 
122   // Insert image in list
123   if (!first)           // if list empty, set first element in list
124     first = image;
125   else {              // else add image at the end of the list
126     image->previous = last;
127     last->next = image;
128   }
129   last  = image;        // update last & current pointers
130   current = image;
131 
132   {
133   // Update state and modification rectangle
134   PositionMv p0, p1;
135   image->GetOutlineRectangle (&p0, &p1);
136   state.Increment(p0,p1);
137   }
138 
139 end:
140   return (status);
141 }
142 
143 
AddImage(PRIImage * theImage)144 FPXStatus ViewWorld::AddImage (PRIImage* theImage)
145 {
146   register FPXStatus status = FPX_OK;
147   ViewImage* image;
148 
149   // Open image file (among other things�)
150   if ((image = new ViewImage (theImage)) == NULL) {
151     status = FPX_FILE_NOT_FOUND;    // Best guess as to why this failed
152     goto end;
153   }
154 
155   // Test if the image file is successfully opened, exit if not
156   if (image->FileStatus() != 0) {
157     delete image;
158     image = NULL;
159     status = FPX_FILE_NOT_OPEN_ERROR;
160     goto end;
161   }
162 
163   // Insert image in list
164   if (!first)           // if list empty, set first element in list
165     first = image;
166   else {              // else add image at the end of the list
167     image->previous = last;
168     last->next = image;
169   }
170   last  = image;        // update last & current pointers
171   current = image;
172 
173   {
174   // Update state and modification rectangle
175   PositionMv p0, p1;
176   image->GetOutlineRectangle (&p0, &p1);
177   state.Increment(p0,p1);
178   }
179 
180 end:
181   return (status);
182 }
183 
184 
AddImage(ViewImage * image)185 FPXStatus ViewWorld::AddImage (ViewImage* image)
186 {
187   register FPXStatus status = FPX_OK;
188 
189   // Test if the image file is successfully opened, exit if not
190   if (image->FileStatus() != 0) {
191     status = FPX_FILE_NOT_OPEN_ERROR;
192     goto end;
193   }
194 
195   // Insert image in list
196   if (!first)           // if list empty, set first element in list
197     first = image;
198   else {              // else add image at the end of the list
199     image->previous = last;
200     last->next = image;
201   }
202   last  = image;        // update last & current pointers
203   current = image;
204 
205   {
206   // Update state and modification rectangle
207   PositionMv p0, p1;
208   image->GetOutlineRectangle (&p0, &p1);
209   state.Increment(p0,p1);
210   }
211 
212 end:
213   return (status);
214 }
215 
216 
DeleteImage(ViewImage * theImage,Boolean doNotCloseFile)217 FPXStatus ViewWorld::DeleteImage (ViewImage* theImage, Boolean doNotCloseFile)
218 {
219   register FPXStatus status = FPX_OK;
220   ViewImage* image;
221 
222   // Error if list empty
223   if (!first) {
224     status = FPX_FILE_NOT_OPEN_ERROR;
225     goto end;
226   }
227 
228   // search theImage in list
229   image = first;          // Init loop
230   while (image != last) {
231     if (image == theImage)    // Exit from loop if theImage found
232       break;
233     image = image->next;
234   }
235   if (image != theImage) {      // Error if theImage not found
236     status = FPX_ERROR;
237     goto end;
238   }
239 
240   // delete image from list : don't forget to set current to a valid value if necessary�
241   if ((image == first) && (image == last)) {  // if list contain a single image
242     first   = NULL;
243     last  = NULL;
244     current = NULL;
245   } else if (image == first) {        // if image is the first element of the list
246     first = image->next;
247     if (current == image)
248       current = first;
249   } else if (image == last) {         // if image is the last element of the list
250     last = image->previous;
251     if (current == image)
252       current = last;
253   } else {                  // if image in the middle of the list
254     if (current == image)
255       current = image->next;
256   }
257 
258   {
259   // Update state and modification rectangle
260   PositionMv p0, p1;
261   image->GetOutlineRectangle (&p0, &p1);
262   state.Increment(p0,p1);
263   }
264 
265   // delete the ViewImage itself and update pointers in list
266   if (doNotCloseFile) {
267     PRIImage* imageFile = image->GetImage();
268     ((PHierarchicalImage*)(imageFile))->DoNotCloseFileWhenDelete();
269   }
270   delete image;
271 
272 end:
273   return (status);
274 }
275 
276 
First(ViewImage ** theImage)277 long ViewWorld::First (ViewImage** theImage)
278 {
279   register long status = 0;
280 
281   *theImage = first;  // Get first element of the list
282   current = first;  // Set current pointer
283   if (!first)     // Warning if list empty
284     status = 1;
285 
286   return (status);
287 }
288 
289 
Last(ViewImage ** theImage)290 long ViewWorld::Last (ViewImage** theImage)
291 {
292   register long status = 0;
293 
294   *theImage = last; // Get last element of the list
295   current = last;   // Set current pointer
296   if (!last)      // Warning if list empty
297     status = 1;
298 
299   return (status);
300 }
301 
302 
Next(ViewImage ** theImage)303 long ViewWorld::Next (ViewImage** theImage)
304 {
305   register long status = 0;
306 
307   if (!first)           // Warning if list empty
308     status = 1;
309   else {
310     *theImage = current->next;  // get next element
311     if (!*theImage)       // Warning if bottom of the list reached
312       status = 2;
313     else            // set current pointer
314       current = *theImage;
315   }
316 
317   return (status);
318 }
319 
320 
Previous(ViewImage ** theImage)321 long ViewWorld::Previous (ViewImage** theImage)
322 {
323   register long status = 0;
324 
325   if (!first)             // Warning if list empty
326     status = 1;
327   else {
328     *theImage = current->previous;  // get previous element
329     if (!*theImage)         // Warning if top of the list reached
330       status = 2;
331     else              // set current pointer
332       current = *theImage;
333   }
334 
335   return (status);
336 }
337 
338 
Current(ViewImage ** theImage)339 long ViewWorld::Current (ViewImage** theImage)
340 {
341   register long status = 0;
342 
343   if (!current)       // Warning if list empty
344     status = 1;
345   else
346     *theImage = current;    // get current element
347 
348   return (status);
349 }
350 
351 
352 //  ------------------------------------------------------------------------------------------------
353 //  Methods of the ViewImage class
354 //  ------------------------------------------------------------------------------------------------
355 
ViewImage(ref_FicNom)356 ViewImage::ViewImage (ref_FicNom /*refName*/) : previous(0), next(0), state((float)0.0, (float)0.0, (float)0.0, (float)0.0)
357 {
358   dirtyCount = 0;
359   doNotDelete = FALSE;
360 
361   // Init Viewing parameters
362   image = NULL;
363   InitViewParameters();
364 }
365 
366 
ViewImage()367 ViewImage::ViewImage () : previous(0), next(0), state((float)0.0, (float)0.0, (float)0.0, (float)0.0)
368 {
369   dirtyCount = 0;
370   doNotDelete = FALSE;
371 
372   // Init Viewing parameters
373   image = NULL;
374   InitViewParameters();
375 }
376 
377 
ViewImage(PRIImage * theImage)378 ViewImage::ViewImage (PRIImage* theImage) : previous(0), next(0), state((float)0.0, (float)0.0, (float)0.0, (float)0.0)
379 {
380   dirtyCount = 0;
381   doNotDelete = TRUE;
382 
383   // Store the Image pointer
384   image = theImage;
385 
386   // Test if Image file is successfully opened
387   if (image->Status() != 0)
388     image = NULL;
389 
390   // Init Viewing parameters
391   InitViewParameters();
392 
393   // Copy FPX image viewing parameters
394   if (image && image->imageParam) {
395     hasColorTwist     = image->imageParam->HasColorTwist();
396     if (hasColorTwist) {
397       colorTwist = new PColorTwist();
398       if (colorTwist)
399         image->imageParam->GetColorTwist(colorTwist);
400       else
401         hasColorTwist = FALSE;
402     }
403 
404     hasContrastValue  = image->imageParam->HasContrastValue();
405     image->imageParam->GetContrast(&contrastValue);
406 
407     hasFilteringValue = image->imageParam->HasFilteringValue();
408     image->imageParam->GetFiltering(&filteringValue);
409 
410     dirtyCount = image->imageParam->GetDirtyCount ();
411 
412     originHeight = image->imageParam->originHeight;
413     originWidth  = image->imageParam->originWidth;
414     height     = image->imageParam->height;
415     width      = image->imageParam->width;
416     cropX0     = image->imageParam->cropX0;
417     cropY0     = image->imageParam->cropY0;
418     cropX1     = image->imageParam->cropX1;
419     cropY1     = image->imageParam->cropY1;
420     position   = image->imageParam->position;
421     resizeFinalDimensions = image->imageParam->resizeFinalDimensions;
422     image->imageParam->GetFinalDimensions(&finalWidth, &finalHeight);
423   }
424 }
425 
426 
427 
InitViewParameters()428 void ViewImage::InitViewParameters()
429 {
430   if (image) {
431     // Init image size within World according to scanned size
432     int pix_height, pix_width;
433     float resol;
434     image->GetDimensions (&pix_width, &pix_height);
435     image->GetResolution (&resol);
436     originHeight = (float)(pix_height) / resol;
437     originWidth  = (float)(pix_width)  / resol;
438     height = originHeight;
439     width  = originWidth;
440     cropX0 = (float)0;  cropY0 = (float)0;
441     cropX1 = width; cropY1 = height;
442     resizeFinalDimensions = TRUE;
443     finalHeight = height;
444     finalWidth  = width;
445 
446     // Store the back pointer in image
447     if(!image->imageParam)
448       image->SetImageParameter(this);
449   }
450   normalizationRatio = (float)1.0;
451   contrastValue = (float)1.0;
452   filteringValue  = (float)0.0;
453   colorTwist    = NULL;
454   // Remark: position are automatically set to identity when created -> no need to reinit them
455 
456   // By default, none of these values has to be taken into account
457   hasColorTwist     = FALSE;
458   hasContrastValue  = FALSE;
459   hasFilteringValue = FALSE;
460 }
461 
462 
~ViewImage()463 ViewImage::~ViewImage ()
464 {
465   // LS 06/27/96: remove the pointer to myself inside "image"
466   if ( (image != NULL) && (image->imageParam == this) )
467     image->SetImageParameter(NULL);
468 
469   // Delete Image if present
470   if (image && !doNotDelete)
471     delete image;
472 
473   // Delete ColorTwist
474   if (colorTwist)
475     delete colorTwist;
476 
477   // Update pointers up and down in the list
478   if (next)
479     next->previous = previous;
480   if (previous)
481     previous->next = next;
482 }
483 
484 
FileStatus()485 FPXStatus ViewImage::FileStatus ()
486 {
487   register FPXStatus status = FPX_OK;
488 
489   // test if image exist (has been opened)
490   if (image == NULL)
491     status = FPX_FILE_NOT_OPEN_ERROR;
492 
493   return(status);
494 }
495 
496 // Position setting tools :
497 
UseAlphaChannel(Boolean useAlpha)498 FPXStatus ViewImage::UseAlphaChannel (Boolean useAlpha)
499 {
500   register FPXStatus status = FPX_OK;
501 
502   // test if image exist (has been opened)
503   if (!(status = FileStatus())) {
504 
505     status = image->UseAlphaChannel(useAlpha);
506 
507     // Compute rectangle of the image
508     PositionMv  p0, p1;
509     GetOutlineRectangle (&p0, &p1);
510     RectangleMv rectangle (p0, p1);
511 
512     // Update state and modification rectangle
513     state.Increment(rectangle);
514   }
515   return status;
516 }
517 
518 
InvertAlphaChannel(Boolean inverseAlpha)519 FPXStatus ViewImage::InvertAlphaChannel (Boolean inverseAlpha)
520 {
521   register FPXStatus status = FPX_OK;
522 
523   // test if image exist (has been opened)
524   if (!(status = FileStatus())) {
525 
526     status = image->InvertAlphaChannel(inverseAlpha);
527 
528     // Compute rectangle of the image
529     PositionMv  p0, p1;
530     GetOutlineRectangle (&p0, &p1);
531     RectangleMv rectangle (p0, p1);
532 
533     // Update state and modification rectangle
534     state.Increment(rectangle);
535   }
536   return status;
537 }
538 
539 
SetImageSize(float theWidth,float theHeight)540 FPXStatus ViewImage::SetImageSize (float theWidth, float theHeight)
541 {
542   if ((theHeight <= 0.0001) || (theWidth <= 0.0001))  // Error if size doesn't make sense
543     return FPX_ERROR;
544   else {                        // Rescale the image to fit the given size
545 
546     // Compute the current size of the image
547     float x0, y0, x1, y1;
548     GetOutlineRectangle (&x0, &y0, &x1, &y1);
549     float previousWidth  = x1 - x0;
550     float previousHeight = y1 - y0;
551 
552     // Rescale the image
553     GetOrigin (&x0, &y0);             // CAUTION : x0, y0 are in unit but Scale() use unit�
554     Scale (x0, y0, theWidth/previousWidth, theHeight/previousHeight);
555   }
556   return FPX_OK;
557 }
558 
559 
SetPosition(TransfoPerspective & position)560 void ViewImage::SetPosition (TransfoPerspective& position)
561 {
562   // Update transformation matrix with given values without modification
563   this->position = position;
564 }
565 
566 
SetPosition(float x0,float y0,float m11,float m12,float m21,float m22)567 void ViewImage::SetPosition (float x0, float y0, float m11, float m12, float m21, float m22)
568 {
569   TransfoPerspective trans (m11, m21, m12, m22, (float)0.0, (float)0.0);
570 
571   // Update transformation matrix with given values without modification
572   position = trans;
573   Translate (x0, y0);
574 }
575 
576 
GetPosition(float * x0,float * y0,float * m11,float * m12,float * m21,float * m22)577 void ViewImage::GetPosition (float* x0, float* y0, float* m11, float* m12, float* m21, float* m22)
578 {
579   TransfoPerspective uvToxy (position);
580 
581   uvToxy.GetAffineMatrix(m11,m21,m12,m22,x0,y0);
582 }
583 
584 
ApplyTransform(TransfoPerspective & trans)585 void ViewImage::ApplyTransform (TransfoPerspective& trans)
586 {
587   PositionMv  p0, p1;
588 
589   // Compute initial rectangle of the image
590   GetOutlineRectangle (&p0, &p1);
591   RectangleMv sourceRectangle (p0, p1);
592 
593   // Update transformation matrix with given values without modification
594   position *= trans;
595 
596   // Compute final rectangle of the image
597   GetOutlineRectangle (&p0, &p1);
598   RectangleMv destinationRectangle (p0, p1);
599 
600   // Update final dimensions if required
601   if (resizeFinalDimensions) {
602     finalWidth  = p1.h;
603     finalHeight = p1.v;
604   }
605 
606   // Update state and modification rectangle
607   state.Increment(sourceRectangle + destinationRectangle);
608 }
609 
610 
ApplyTransform(float x0,float y0,float m11,float m12,float m21,float m22)611 void ViewImage::ApplyTransform (float x0, float y0, float m11, float m12, float m21, float m22)
612 {
613   // Create the transformation matrix
614   TransfoPerspective trans (m11, m21, m12, m22, -x0, -y0);
615   ApplyTransform(trans);
616 }
617 
618 
Translate(float dx,float dy)619 void ViewImage::Translate (float dx, float dy)
620 {
621   PositionMv  p0, p1;
622 
623   dx = Toolkit_ConvertToMm(dx);
624   dy = Toolkit_ConvertToMm(dy);
625 
626   // Compute initial rectangle of the image
627   GetOutlineRectangle (&p0, &p1);
628   RectangleMv sourceRectangle (p0, p1);
629 
630   // Translate origin of the image
631   position.Translate(dx,dy);
632 
633   // Compute final rectangle of the image
634   GetOutlineRectangle (&p0, &p1);
635   RectangleMv destinationRectangle (p0, p1);
636 
637   // Update final dimensions if required
638   if (resizeFinalDimensions) {
639     finalWidth  = p1.h;
640     finalHeight = p1.v;
641   }
642 
643   // Update state and modification rectangle
644   state.Increment(sourceRectangle + destinationRectangle);
645 }
646 
647 
Rotate(float x0,float y0,float theta)648 void ViewImage::Rotate (float x0, float y0, float theta)
649 {
650   PositionMv  p0, p1;
651 
652   x0 = Toolkit_ConvertToMm(x0);
653   y0 = Toolkit_ConvertToMm(y0);
654 
655   // Compute initial rectangle of the image
656   GetOutlineRectangle (&p0, &p1);
657   RectangleMv sourceRectangle (p0, p1);
658 
659   // Rotate the image of an angle theta
660   // (x0,y0) is the center of the rotation expressed in World coordinates
661   // theta is in degree and in reverse trigonometric sense -> conversion in radian
662   position.Rotate (x0, y0, -theta*(float)PI/(float)180.0);
663 
664   // Compute final rectangle of the image
665   GetOutlineRectangle (&p0, &p1);
666   RectangleMv destinationRectangle (p0, p1);
667 
668   // Update final dimensions if required
669   if (resizeFinalDimensions) {
670     finalWidth  = p1.h;
671     finalHeight = p1.v;
672   }
673 
674   // Update state and modification rectangle
675   state.Increment(sourceRectangle + destinationRectangle);
676 }
677 
678 
Scale(float x0,float y0,float sx,float sy)679 void ViewImage::Scale (float x0, float y0, float sx, float sy)
680 {
681   PositionMv  p0, p1;
682 
683   x0 = Toolkit_ConvertToMm(x0);
684   y0 = Toolkit_ConvertToMm(y0);
685 
686   // Compute initial rectangle of the image
687   GetOutlineRectangle (&p0, &p1);
688   RectangleMv sourceRectangle (p0, p1);
689 
690   // Scale the image along x and y axes
691   // (x0,y0) is the center of the scaling effect expressed in World coordinates
692   position.Scale (x0, y0, sx, sy);
693 
694   // Compute final rectangle of the image
695   GetOutlineRectangle (&p0, &p1);
696   RectangleMv destinationRectangle (p0, p1);
697 
698   // Update final dimensions if required
699   if (resizeFinalDimensions) {
700     finalWidth  = p1.h;
701     finalHeight = p1.v;
702   }
703 
704   // Update state and modification rectangle
705   state.Increment(sourceRectangle + destinationRectangle);
706 }
707 
708 
ShearHorizontal(float x0,float y0,float sh)709 void ViewImage::ShearHorizontal (float x0, float y0, float sh)
710 {
711   PositionMv  p0, p1;
712 
713   x0 = Toolkit_ConvertToMm(x0);
714   y0 = Toolkit_ConvertToMm(y0);
715 
716   // Compute initial rectangle of the image
717   GetOutlineRectangle (&p0, &p1);
718   RectangleMv sourceRectangle (p0, p1);
719 
720   // Skew the image along x axe
721   // (x0,y0) is the center of the skewing effect expressed in World coordinates
722   position.ShearHorizontal (x0, y0, sh);
723 
724   // Compute final rectangle of the image
725   GetOutlineRectangle (&p0, &p1);
726   RectangleMv destinationRectangle (p0, p1);
727 
728   // Update final dimensions if required
729   if (resizeFinalDimensions) {
730     finalWidth  = p1.h;
731     finalHeight = p1.v;
732   }
733 
734   // Update state and modification rectangle
735   state.Increment(sourceRectangle + destinationRectangle);
736 }
737 
738 
ShearVertical(float x0,float y0,float sh)739 void ViewImage::ShearVertical (float x0, float y0, float sh)
740 {
741   PositionMv  p0, p1;
742 
743   x0 = Toolkit_ConvertToMm(x0);
744   y0 = Toolkit_ConvertToMm(y0);
745 
746   // Compute initial rectangle of the image
747   GetOutlineRectangle (&p0, &p1);
748   RectangleMv sourceRectangle (p0, p1);
749 
750   // Skew the image along y axe
751   // (x0,y0) is the center of the skewing effect expressed in World coordinates
752   position.ShearVertical (x0, y0, sh);
753 
754   // Compute final rectangle of the image
755   GetOutlineRectangle (&p0, &p1);
756   RectangleMv destinationRectangle (p0, p1);
757 
758   // Update final dimensions if required
759   if (resizeFinalDimensions) {
760     finalWidth  = p1.h;
761     finalHeight = p1.v;
762   }
763 
764   // Update state and modification rectangle
765   state.Increment(sourceRectangle + destinationRectangle);
766 }
767 
768 
FlipHorizontal(float x0,float y0)769 void ViewImage::FlipHorizontal (float x0, float y0)
770 {
771   PositionMv  p0, p1;
772 
773   x0 = Toolkit_ConvertToMm(x0);
774   y0 = Toolkit_ConvertToMm(y0);
775 
776   // Compute initial rectangle of the image
777   GetOutlineRectangle (&p0, &p1);
778   RectangleMv sourceRectangle (p0, p1);
779 
780   // Flip the image along a vertical line
781   // (x0,y0) is the center of the flip effect expressed in World coordinates
782   position.FlipHorizontal (x0,y0);
783 
784   // Compute final rectangle of the image
785   GetOutlineRectangle (&p0, &p1);
786   RectangleMv destinationRectangle (p0, p1);
787 
788   // Update final dimensions if required
789   if (resizeFinalDimensions) {
790     finalWidth  = p1.h;
791     finalHeight = p1.v;
792   }
793 
794   // Update state and modification rectangle
795   state.Increment(sourceRectangle + destinationRectangle);
796 }
797 
798 
FlipVertical(float x0,float y0)799 void ViewImage::FlipVertical (float x0, float y0)
800 {
801   PositionMv  p0, p1;
802 
803   x0 = Toolkit_ConvertToMm(x0);
804   y0 = Toolkit_ConvertToMm(y0);
805 
806   // Compute initial rectangle of the image
807   GetOutlineRectangle (&p0, &p1);
808   RectangleMv sourceRectangle (p0, p1);
809 
810   // Flip the image along an horizontal line
811   // (x0,y0) is the center of the flip effect expressed in World coordinates
812   position.FlipVertical (x0,y0);
813 
814   // Compute final rectangle of the image
815   GetOutlineRectangle (&p0, &p1);
816   RectangleMv destinationRectangle (p0, p1);
817 
818   // Update final dimensions if required
819   if (resizeFinalDimensions) {
820     finalWidth  = p1.h;
821     finalHeight = p1.v;
822   }
823 
824   // Update state and modification rectangle
825   state.Increment(sourceRectangle + destinationRectangle);
826 }
827 
828 
SetContrast(float theContrastValue)829 void ViewImage::SetContrast (float theContrastValue)
830 {
831   contrastValue = theContrastValue;
832   hasContrastValue = (((contrastValue > 1.00001) || (contrastValue < 0.99999)) ? TRUE : FALSE);
833   dirtyCount++;
834 }
835 
836 
SetColorTwist(PColorTwist * theColorTwist)837 void ViewImage::SetColorTwist (PColorTwist* theColorTwist)
838 {
839   if (theColorTwist) {
840     if (colorTwist)
841       delete colorTwist;
842     colorTwist = NULL;
843     hasColorTwist = (theColorTwist->IsIdentity() ? FALSE : TRUE);
844     if (hasColorTwist) {
845       colorTwist  = new PColorTwist();
846       if (colorTwist)
847         *colorTwist = *theColorTwist;
848       else
849         hasColorTwist = FALSE;
850     }
851     dirtyCount++;
852   }
853 }
854 
855 
SetFiltering(float theFilteringValue)856 void ViewImage::SetFiltering (float theFilteringValue)
857 {
858   filteringValue = theFilteringValue;
859   hasFilteringValue = (((filteringValue > 0.00001) || (filteringValue < -0.00001)) ? TRUE : FALSE);
860   dirtyCount++;
861 }
862 
863 
SetFinalDimensions(float theFinalWidth,float theFinalHeight)864 long ViewImage::SetFinalDimensions (float theFinalWidth, float theFinalHeight)
865 {
866   finalHeight = theFinalHeight;
867   finalWidth  = theFinalWidth;
868   return 0;
869 }
870 
871 
GetContrast(float * theContrastValue)872 void ViewImage::GetContrast (float* theContrastValue)
873 {
874   *theContrastValue = contrastValue;
875 }
876 
877 
GetColorTwist(PColorTwist * theColorTwist)878 void ViewImage::GetColorTwist (PColorTwist* theColorTwist)
879 {
880   if (colorTwist)
881     *theColorTwist = *colorTwist;
882   else {
883     PColorTwist identity;
884     *theColorTwist = identity;
885   }
886 }
887 
888 
GetFiltering(float * theFilteringValue)889 void ViewImage::GetFiltering (float* theFilteringValue)
890 {
891   *theFilteringValue = filteringValue;
892 }
893 
894 
GetFinalDimensions(float * theFinalWidth,float * theFinalHeight)895 void ViewImage::GetFinalDimensions (float* theFinalWidth, float* theFinalHeight)
896 {
897   *theFinalHeight = finalHeight;
898   *theFinalWidth  = finalWidth;
899 }
900 
901 
GetDirtyCount()902 long ViewImage::GetDirtyCount ()
903 {
904   return dirtyCount;
905 }
906 
907 
SetImageCrop(float x0,float y0,float x1,float y1)908 FPXStatus ViewImage::SetImageCrop(float x0, float y0, float x1, float y1)
909 {
910   // Test bounds to ensure rect is within the image
911   if (x0 < 0.0)
912     x0 = 0.0;
913   if (x1 > originWidth)
914     x1 =  originWidth;
915 
916   if (y0 < 0.0)
917     y0 = 0.0;
918   if (y1 > originHeight)
919     y1 =  originHeight;
920 
921   if ((x0 >= x1) || (y0 >= y1))
922     return FPX_BAD_COORDINATES;
923 
924   // Reset the cropping before applying the new one
925   ResetImageCrop();
926 
927   // Get the crop rect in dot per mm in image space
928   PositionMv p0 (x0, y0);
929   PositionMv p1 (x1, y1);
930 
931 
932   // Set the cropping rectangle by converting image coords into pixel
933   // coords using the current resolution
934   float resol;
935   image->GetResolution (&resol);
936   image->SetCropRectangle (FLOAT_TO_LONG(p0.h*resol), FLOAT_TO_LONG(p0.v*resol),
937               FLOAT_TO_LONG(p1.h*resol), FLOAT_TO_LONG(p1.v*resol));
938 
939   // Update width and height according to the cropping definition
940   int  pix_height, pix_width;
941   image->GetDimensions (&pix_width, &pix_height);
942   height = (float)(pix_height) / resol;
943   width = (float)(pix_width)  / resol;
944 
945   // Update final dimensions if required
946   PositionMv pt0, pt1;
947   if (resizeFinalDimensions) {
948     GetOutlineRectangle (&pt0, &pt1);
949     finalWidth  = pt1.h;
950     finalHeight = pt1.v;
951   }
952 
953   // Save new crop coordinates
954   cropX0 = x0;
955   cropX1 = x1;
956   cropY0 = y0;
957   cropY1 = y1;
958 
959   // Update state and modification rectangle
960   RectangleMv rectangle (pt0, pt1);
961   state.Increment(rectangle);
962 
963   return FPX_OK;
964 }
965 
966 
ResetImageCrop()967 void ViewImage::ResetImageCrop()
968 {
969   int  i0, j0, i1, j1;
970   int  x0, y0, x1, y1;
971   float resol;
972   TransfoPerspective uvToxy (position);
973 
974   // Inverse position matrix (position is the xy to uv transformation)
975   uvToxy.Inverse();
976 
977   // Get the crop rectangle before reset
978   image->GetCropRectangle (&i0, &j0, &i1, &j1);
979 
980   // Reset crop rectangle
981   image->ResetCropRectangle ();
982 
983   // Get the crop rectangle after reset
984   image->GetCropRectangle (&x0, &y0, &x1, &y1);
985 
986   // Update width and height according to the new cropping definition
987   image->GetResolution (&resol);
988   width = (float)(x1 - x0) / resol;
989   height  = (float)(y1 - y0) / resol;
990   cropX0 = (float)0;  cropY0 = (float)0;
991   cropX1 = width; cropY1 = height;
992 
993   // Compute rectangle of the image
994   PositionMv  p2, p3;
995   GetOutlineRectangle (&p2, &p3);
996   RectangleMv rectangle (p2, p3);
997 
998   // Update final dimensions if required
999   if (resizeFinalDimensions) {
1000     finalWidth  = p3.h;
1001     finalHeight = p3.v;
1002   }
1003 
1004   // Update state and modification rectangle
1005   state.Increment(rectangle);
1006 }
1007 
1008 
1009 // Get geometric information tools :
1010 
GetOutlineParallelogram(float * x0,float * y0,float * x1,float * y1,float * x2,float * y2,float * x3,float * y3)1011 long ViewImage::GetOutlineParallelogram (float* x0, float* y0, float* x1, float* y1,
1012                      float* x2, float* y2, float* x3, float* y3)
1013 {
1014   PositionMv p0, p1, p2, p3;
1015 
1016   // get positions of the 4 points
1017   GetOutlineParallelogram (&p0, &p1, &p2, &p3);
1018 
1019   // update float values according to point positions
1020   *x0 = Toolkit_ConvertToUnit(p0.h);
1021   *y0 = Toolkit_ConvertToUnit(p0.v);
1022 
1023   *x1 = Toolkit_ConvertToUnit(p1.h);
1024   *y1 = Toolkit_ConvertToUnit(p1.v);
1025 
1026   *x2 = Toolkit_ConvertToUnit(p2.h);
1027   *y2 = Toolkit_ConvertToUnit(p2.v);
1028 
1029   *x3 = Toolkit_ConvertToUnit(p3.h);
1030   *y3 = Toolkit_ConvertToUnit(p3.v);
1031 
1032   return 0;
1033 }
1034 
1035 
GetOutlineParallelogram(PositionMv * p0,PositionMv * p1,PositionMv * p2,PositionMv * p3)1036 void ViewImage::GetOutlineParallelogram (PositionMv* p0, PositionMv* p1, PositionMv* p2, PositionMv* p3)
1037 {
1038   TransfoPerspective  uvToxy (position);
1039   PositionMv      pointUV;
1040 
1041 
1042   // Inverse position matrix (position is the xy to uv transformation)
1043   uvToxy.Inverse();
1044 
1045   // Set first corner of image and transform
1046   pointUV.h = cropX0;
1047   pointUV.v = cropY0;
1048   *p0 = uvToxy * pointUV;
1049 
1050 
1051   // Set second corner of image and transform
1052   pointUV.h = cropX1;
1053   pointUV.v = cropY0;
1054   *p1 = uvToxy * pointUV;
1055 
1056 
1057   // Set third corner of image and transform
1058   pointUV.h = cropX0;
1059   pointUV.v = cropY1;
1060   *p2 = uvToxy * pointUV;
1061 
1062 
1063   // Set fourth corner of image and transform
1064   pointUV.h = cropX1;
1065   pointUV.v = cropY1;
1066   *p3 = uvToxy * pointUV;
1067 }
1068 
1069 
GetOutlineRectangle(float * x0,float * y0,float * x1,float * y1)1070 void ViewImage::GetOutlineRectangle (float* x0, float* y0, float* x1, float* y1)
1071 {
1072   PositionMv p0, p1;
1073 
1074   // get positions of the 2 points
1075   GetOutlineRectangle (&p0, &p1);
1076 
1077   // update float values according to point positions
1078   *x0 = Toolkit_ConvertToUnit(p0.h);
1079   *y0 = Toolkit_ConvertToUnit(p0.v);
1080 
1081   *x1 = Toolkit_ConvertToUnit(p1.h);
1082   *y1 = Toolkit_ConvertToUnit(p1.v);
1083 }
1084 
1085 
GetOutlineRectangle(PositionMv * p0,PositionMv * p1)1086 void ViewImage::GetOutlineRectangle (PositionMv* p0, PositionMv* p1)
1087 {
1088   PositionMv p[4];
1089 
1090   // get parallelogram outline positions
1091   GetOutlineParallelogram (&p[0], &p[1], &p[2], &p[3]);
1092 
1093   // init min and max values with the first point
1094   *p0 = p[0];
1095   *p1 = p[0];
1096 
1097   // loop to find min and max values in both direction
1098   for (short i = 1; i < 4; i++) {
1099     if (p[i].h < p0->h) p0->h = p[i].h;
1100     if (p[i].v < p0->v) p0->v = p[i].v;
1101     if (p[i].h > p1->h) p1->h = p[i].h;
1102     if (p[i].v > p1->v) p1->v = p[i].v;
1103   }
1104 }
1105 
1106 
GetOrigin(float * x0,float * y0)1107 void ViewImage::GetOrigin (float* x0, float* y0)
1108 {
1109   PositionMv p0;
1110 
1111   // get positions of the point
1112   GetOrigin (&p0);
1113 
1114   // update float values according to point positions
1115   *x0 = Toolkit_ConvertToUnit(p0.h);
1116   *y0 = Toolkit_ConvertToUnit(p0.v);
1117 }
1118 
1119 
GetOrigin(PositionMv * p0)1120 void ViewImage::GetOrigin (PositionMv* p0)
1121 {
1122   PositionMv p[4];
1123 
1124   // get parallelogram outline positions
1125   GetOutlineParallelogram (&p[0], &p[1], &p[2], &p[3]);
1126 
1127   // origin is the first point
1128   *p0 = p[0];
1129 }
1130 
1131 
1132 // Read a rectangle of the transformed image
1133 
Read4x4Points(float x0,float y0,float x1,float y1,Pixel * bufPix)1134 FPXStatus ViewImage::Read4x4Points (float x0, float y0, float x1, float y1, Pixel* bufPix)
1135 {
1136   FPXStatus status = FPX_OK;
1137 
1138   // Save the background (for the post cropping)
1139   Pixel backGround[16];
1140   BlockMove (bufPix, backGround, 16*sizeof(Pixel));
1141 
1142   PositionMv topleft(x0,y0);
1143   PositionMv topright(x1,y0);
1144   PositionMv botleft(x0,y1);
1145   PositionMv botright(x1,y1);
1146 
1147   topleft  = position * topleft;
1148   topright = position * topright;
1149   botleft  = position * botleft;
1150   botright = position * botright;
1151 
1152   float resolution;
1153   image->GetResolution(&resolution);
1154   resolution *= (float)4096.0;
1155 
1156   long i0 = (FLOAT_TO_LONG)((topleft.h ) * resolution);
1157   long j0 = (FLOAT_TO_LONG)((topleft.v ) * resolution);
1158   long i1 = (FLOAT_TO_LONG)((topright.h) * resolution);
1159   long j1 = (FLOAT_TO_LONG)((topright.v) * resolution);
1160   long i2 = (FLOAT_TO_LONG)((botleft.h ) * resolution);
1161   long j2 = (FLOAT_TO_LONG)((botleft.v ) * resolution);
1162   long i3 = (FLOAT_TO_LONG)((botright.h) * resolution);
1163   long j3 = (FLOAT_TO_LONG)((botright.v) * resolution);
1164 
1165   // Read the sample
1166   status = image->Read4Points (i0, j0, i1, j1, i2, j2, i3, j3, bufPix, -1);
1167 
1168   // Crop the result image
1169   if ((x0 < 0.0) || (y0 < 0.0) || (x1 > finalWidth) || (y1 > finalHeight)) {
1170     float dx = (x1 - x0) / (float)4.0;
1171     float dy = (y1 - y0) / (float)4.0;
1172     float x, y;
1173     int32_t* pt = (int32_t*)(bufPix);
1174     int32_t* bk = (int32_t*)(backGround);
1175     y = y0;
1176     for (long i = 0; i < 4; ++i) {
1177       x = x0;
1178       for (long j = 0; j < 4; ++j) {
1179         if ((x < 0.0) || (y < 0.0) || (x > finalWidth) || (y > finalHeight))
1180           *pt = *bk;
1181         x += dx;
1182         pt++; bk++;
1183       }
1184       y += dy;
1185     }
1186   }
1187 
1188   return status;
1189 }
1190 
1191 
1192 //  ------------------------------------------------------------------------------------------------
1193 //  Methods of the ViewWindow class
1194 //  ------------------------------------------------------------------------------------------------
1195 
ViewWindow(ViewWorld * world,float x0,float y0,float width,float height,float resolution)1196 ViewWindow::ViewWindow (ViewWorld* world, float x0, float y0, float width, float height, float resolution)
1197 {
1198   // Update Window record
1199   this->world     = world;
1200   this->resolution  = resolution;
1201   this->x0      =   Toolkit_ConvertToMm(x0);
1202   this->y0      =   Toolkit_ConvertToMm(y0);
1203 
1204   // Compute Window size in pixels
1205   // CAUTION : WorldToWindow() use unit !
1206   WorldToWindow (x0 + width, y0 + height, &pix_width, &pix_height);
1207   // Convert back to units
1208   WindowToWorld (pix_width, pix_height, &width, &height);
1209 
1210   // Update Window record in mm
1211   this->width  = Toolkit_ConvertToMm(width  - x0);
1212   this->height = Toolkit_ConvertToMm(height - y0);
1213 
1214   // State flag and integral transformation chain initialization
1215   modifiedWindow    = TRUE;
1216   worldState      = 0;
1217   first       = NULL;
1218 }
1219 
1220 
~ViewWindow()1221 ViewWindow::~ViewWindow ()
1222 {
1223   ViewTransfoState* next;
1224   ViewTransfoState* current;
1225 
1226   // Delete integral transformation chain
1227   current = first;
1228   while (current) {
1229     next = current->next;
1230     delete current;
1231     current = next;
1232   }
1233 }
1234 
1235 
1236 // Basic access tools :
1237 
ReadSample(long i0,long j0,Pixel * sample,FPXBaselineColorSpace space)1238 FPXStatus ViewWindow::ReadSample (long i0, long j0, Pixel* sample, FPXBaselineColorSpace space)
1239 {
1240   float     px0, py0, px1, py1;
1241   ViewImage *image;
1242   FPXStatus status = FPX_OK;
1243   Pixel     sampleTmp[SAMPLE_WIDTH*SAMPLE_WIDTH];
1244 
1245   // Compute Window position of each corner of the sample
1246   px0 = ((float)(i0)/resolution) + x0;
1247   py0 = ((float)(j0)/resolution) + y0;
1248   px1 = px0 + (float)(SAMPLE_WIDTH)/resolution;
1249   py1 = py0 + (float)(SAMPLE_WIDTH)/resolution;
1250 
1251   // Set the global color model used by the user and the sample
1252   GtheSystemToolkit->SetUsedColorSpace(space);
1253   GtheSystemToolkit->SetToBackground(sampleTmp,SAMPLE_WIDTH,SAMPLE_WIDTH);
1254 
1255   // Read sample for each image of the World
1256   world->First(&image);
1257   while (image) {
1258 
1259     // Set the image color space: supported only by FlashPix images for the moment...
1260     PFileFlashPixIO* FlashPixFile = (PFileFlashPixIO*)(image->GetImage());
1261     FlashPixFile->SetUsedColorSpace(space);
1262 
1263     // Read sample in file
1264     if ((status = image->Read4x4Points (px0, py0, px1, py1, sampleTmp)) != FPX_OK)
1265       return status;
1266     world->Next(&image);                // Next image
1267   }
1268 
1269   // Copy the sample read according to the interleaving and the active channel choosed by the user
1270   short plan = Toolkit_ActiveChannel();
1271   // Copy pixels to the tile
1272   if (plan == ActiveChannel_All) {
1273     // move all the buffer if all planes available to copy
1274     BlockMove(sampleTmp,sample,SAMPLE_WIDTH*SAMPLE_WIDTH*sizeof(Pixel));
1275   } else {
1276     if (GtheSystemToolkit->interleaving == Interleaving_Channel) {
1277       // Pixel by pixel if planes specified and there is only one channel in the output buffer
1278       register long j;
1279       register unsigned char *src, *dst;
1280       src = (unsigned char *)(sampleTmp) + plan;
1281       dst = (unsigned char *)(sample);
1282       for (j=0; j<SAMPLE_WIDTH*SAMPLE_WIDTH;j++,dst++,src+=sizeof(Pixel))
1283         *dst = *src;
1284     } else {
1285       // Pixel by pixel if planes specified
1286       register long j;
1287       register unsigned char *src, *dst;
1288       src = (unsigned char *)(sampleTmp) + plan;
1289       dst = (unsigned char *)(sample)  + plan;
1290       for (j=0; j<SAMPLE_WIDTH*SAMPLE_WIDTH;j++,src+=sizeof(Pixel),dst+=sizeof(Pixel))
1291         *dst = *src;
1292     }
1293   }
1294   if ((GtheSystemToolkit->interleaving != Interleaving_Channel) || (plan == ActiveChannel_All))
1295     if (Toolkit_Interleave (sample, SAMPLE_WIDTH, SAMPLE_WIDTH))
1296       status = FPX_MEMORY_ALLOCATION_FAILED;
1297   return status;
1298 }
1299 
1300 
Refresh(Pixel * map,FPXBaselineColorSpace space,long pixelWidth,long pixelHeight)1301 FPXStatus ViewWindow::Refresh (Pixel* map, FPXBaselineColorSpace space, long pixelWidth,
1302               long pixelHeight)
1303 {
1304   long    i, j;
1305   Pixel     sample[SAMPLE_WIDTH*SAMPLE_WIDTH];
1306   FPXStatus status = FPX_OK;
1307 
1308   j = 0;
1309   while (j < pixelHeight) {                       // For each horizontal bar
1310     i = 0;
1311     if ( GtheSystemToolkit->fnctProgFunc)
1312        if (GtheSystemToolkit->fnctProgFunc( pixelHeight, j))
1313         return FPX_USER_ABORT;
1314 
1315     while ((i < pixelWidth) && (status == FPX_OK)) {
1316       status = ReadSample (i, j, sample, space);              // Read sample
1317       Toolkit_CopyInterleaved (map, pixelWidth, pixelHeight,
1318                    sample, SAMPLE_WIDTH, SAMPLE_WIDTH, i, j);
1319       i += SAMPLE_WIDTH;                          // Next sample
1320     }
1321     j += SAMPLE_WIDTH;                            // Next horizontal bar
1322   }
1323   return status;
1324 }
1325 
1326 
1327 // Modifying Window tools :
1328 
Translate(float dx,float dy)1329 void ViewWindow::Translate (float dx, float dy)
1330 {
1331   // translate Window origin
1332   x0 += Toolkit_ConvertToMm(dx);
1333   y0 += Toolkit_ConvertToMm(dy);
1334 
1335   // Update Window state
1336   modifiedWindow = TRUE;
1337 }
1338 
1339 
Resize(float width,float height)1340 void ViewWindow::Resize (float width, float height)
1341 {
1342   // Compute Window size in pixels
1343   // CAUTION : WorldToWindow() use unit => conversion of x0 and y0 from mm to unit
1344   WorldToWindow (Toolkit_ConvertToUnit(x0) + width, Toolkit_ConvertToUnit(y0) + height, &pix_width, &pix_height);
1345 
1346   // Convert to a multiple of SAMPLE_WIDTH
1347   // CHG_FIX_RESIZE - rounding-up here causes RI to write beyond the end of the users
1348   //  buffer later. So don't recalculate pixel sizes here and just let the rendering
1349   //  code handle special cases where buffer is not a multiple of SAMPLE_WIDTH
1350   //pix_width  = (((pix_width -1)/SAMPLE_WIDTH) + 1) * SAMPLE_WIDTH;
1351   //pix_height = (((pix_height-1)/SAMPLE_WIDTH) + 1) * SAMPLE_WIDTH;
1352 
1353   // Convert back to unit
1354   WindowToWorld (pix_width, pix_height, &width, &height);
1355 
1356   // Set the new size in mm
1357   this->width  = Toolkit_ConvertToMm(width)  - x0;
1358   this->height = Toolkit_ConvertToMm(height) - y0;
1359 
1360   // Update Window state
1361   modifiedWindow = TRUE;
1362 }
1363 
1364 
Zoom(float zoomRatio)1365 FPXStatus ViewWindow::Zoom (float zoomRatio)
1366 {
1367   // Test parameter consistency
1368   if (zoomRatio <= 0.0)
1369     return FPX_ERROR;
1370 
1371   // update resolution according to zoomRatio
1372   resolution *= zoomRatio;
1373 
1374   // zoom is performed from the center of the Window, so, translate the origin
1375   x0 += width  * (zoomRatio - 1) / (2*zoomRatio);
1376   y0 += height * (zoomRatio - 1) / (2*zoomRatio);
1377 
1378   // size is changed in order to maintain the same amount of pixels in the Window
1379   width /= zoomRatio;
1380   height /= zoomRatio;
1381 
1382   // Note that pix_width and pix_height are not changed through zoom effect�
1383   // Update Window state
1384   modifiedWindow = TRUE;
1385 
1386   return FPX_OK;
1387 }
1388 
1389 
1390 // Get usefull information :
1391 
GetWindowDefinition(float * x0,float * y0,float * width,float * height,float * resolution)1392 void ViewWindow::GetWindowDefinition (float* x0, float* y0, float* width, float* height, float* resolution)
1393 {
1394   // read information from Window record
1395   *x0       = Toolkit_ConvertToUnit(this->x0);
1396   *y0       = Toolkit_ConvertToUnit(this->y0);
1397   *height     = Toolkit_ConvertToUnit(this->height);
1398   *width      = Toolkit_ConvertToUnit(this->width);
1399   *resolution   = Toolkit_ConvertToMm(this->resolution);
1400 }
1401 
1402 
WindowToWorld(int i,int j,float * x,float * y)1403 void ViewWindow::WindowToWorld (int i, int j, float* x, float* y)
1404 {
1405   // Convert Window pixels coordinates into World coordinates
1406   *x = Toolkit_ConvertToUnit((float)(i)/resolution + x0);
1407   *y = Toolkit_ConvertToUnit((float)(j)/resolution + y0);
1408 }
1409 
1410 
WorldToWindow(float x,float y,int * i,int * j)1411 void ViewWindow::WorldToWindow (float x, float y, int* i, int* j)
1412 {
1413   // Convert World coordinates into Window pixels coordinates
1414   *i = (long)((Toolkit_ConvertToMm(x)-x0) * resolution + 0.5);
1415   *j = (long)((Toolkit_ConvertToMm(y)-y0) * resolution + 0.5);
1416 }
1417 
1418 
1419 // Update integral transformation chain, allocate it if necessary
UpdateTransfoChain()1420 void ViewWindow::UpdateTransfoChain()
1421 {
1422   if (modifiedWindow || (worldState!=world->GetState())) {// If World or Window state is different
1423     ViewImage*      image;
1424     ViewTransfoState* transfo;
1425     world->First(&image);               // Set image to be the first of the World
1426     if (!first) {
1427       first = new ViewTransfoState();         // Allocate first integral transformation
1428       if (first==NULL) {
1429         return;
1430       }
1431     }
1432     transfo = first;                  // Set transfo to be the first of the Window
1433     while (image) {                   // For every image of the World
1434       transfo->Update (x0, y0, resolution, image);  // Update transfo according to Window and image
1435       world->Next(&image);              // Step to the next image
1436       if (!transfo->next) {
1437         transfo->next = new ViewTransfoState();   // Allocate next transfo if necessary
1438         if (first==NULL) {
1439           return;
1440         }
1441       }
1442       transfo = transfo->next;            // Step to the next transfo
1443     }
1444     modifiedWindow  = FALSE;              // Update Window state
1445     worldState    = world->GetState();        // Update World state
1446   }
1447 }
1448 
1449 
1450 
1451 //  ------------------------------------------------------------------------------------------------
1452 //  Methods of the substructures
1453 //  ------------------------------------------------------------------------------------------------
1454 
~ViewWorldRect()1455 ViewWorldRect::~ViewWorldRect ()
1456 {
1457 
1458 }
1459 
1460 
1461 // Compute transformation matrice according to Window and image parameters
1462 
Update(float x0,float y0,float resolution,ViewImage * image)1463 void ViewTransfoState::Update (float x0, float y0, float resolution, ViewImage* image)
1464 {
1465   int pix_height, pix_width;
1466 
1467   (*image)->GetDimensions (&pix_width, &pix_height);
1468 
1469   // Translation and scaling of pixel Window to World mm
1470   TransfoPerspective  windowposition ((float)1.0/resolution, (float)0.0, (float)0.0, (float)1.0/resolution, x0, y0);
1471 
1472   // Scaling of World mm to Image pixel
1473   TransfoPerspective  imagescaling ((float)(pix_width)/image->width, (float)0.0, (float)0.0, (float)(pix_height)/image->height, (float)0.0, (float)0.0);
1474 
1475   // Combinaison of the 3 matrices in float
1476   TransfoPerspective  scaledposition = imagescaling * (image->position * windowposition);
1477 
1478   // Convert matrice into integral transformation matrice
1479   pixelPosition = scaledposition;
1480 
1481   // Save image state
1482   imageState = image->GetState();
1483 }
1484 
1485 
ViewState(float x0,float y0,float x1,float y1)1486 ViewState::ViewState(float x0, float y0, float x1, float y1) : largestRectangle (x0, y0, x1, y1)
1487 {
1488   long i;
1489 
1490   // Initialize state and last modified rectangle
1491   stateNumber     = 1;
1492   lastModRectangle  = &modRectangles[0];
1493 
1494   // "modRectangles" array is a closed chain of "ViewStateNumber" members
1495   modRectangles[0].next   = &modRectangles[1];
1496   modRectangles[0].previous = &modRectangles[ViewStateNumber-1];
1497   for (i=1;i<(ViewStateNumber-1);i++) {
1498     modRectangles[i].next   = &modRectangles[i+1];
1499     modRectangles[i].previous = &modRectangles[i-1];
1500   }
1501   modRectangles[ViewStateNumber-1].next   = &modRectangles[0];
1502   modRectangles[ViewStateNumber-1].previous = &modRectangles[ViewStateNumber-2];
1503 }
1504 
1505 
Increment()1506 void ViewState::Increment()
1507 {
1508   lastModRectangle = lastModRectangle->next;    // Set to next rectangle
1509   lastModRectangle->rectangle = largestRectangle; // Store rectangle
1510   stateNumber++;                  // Update state number
1511 }
1512 
1513 
Increment(const PositionMv & p0,const PositionMv & p1)1514 void ViewState::Increment(const PositionMv& p0, const PositionMv& p1)
1515 {
1516   RectangleMv modifiedArea (p0, p1);
1517   lastModRectangle = lastModRectangle->next;    // Set to next rectangle
1518   lastModRectangle->rectangle = modifiedArea;   // Store rectangle
1519   stateNumber++;                  // Update state number
1520 }
1521 
1522 
Increment(const RectangleMv & r)1523 void ViewState::Increment(const RectangleMv& r)
1524 {
1525   lastModRectangle = lastModRectangle->next;    // Set to next rectangle
1526   lastModRectangle->rectangle = r;        // Store rectangle
1527   stateNumber++;                  // Update state number
1528 }
1529 
1530 
GetRectangle(long fromState)1531 RectangleMv ViewState::GetRectangle (long fromState)
1532 {
1533   RectangleMv result;
1534 
1535   if (fromState < stateNumber) {                  // If asking for an old state
1536     if ((fromState - stateNumber) > ViewStateNumber)      // If state to old�
1537       result = largestRectangle;                // �return largest rectangle
1538     else {
1539       ViewWorldRect* curModRectangle = lastModRectangle;
1540       result = curModRectangle->rectangle;          // make union of all previous
1541       while (++fromState != stateNumber) {          // state rectangles
1542         curModRectangle = curModRectangle->previous;
1543         result += curModRectangle->rectangle;
1544       }
1545     }
1546   }
1547 
1548   // Note : if "fromState" >= "stateNumber" the returned rectangle will be equal to 0.0 everywhere�
1549 
1550   return result;
1551 }
1552 
1553 
1554 
1555 
1556 
1557