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