views:

118

answers:

1

Found the function which position the image(s) in the multiscaleimage... but I'm not sure how to get the actual image width (for single or multiple) and change the _msi.ViewportOrigin x param based on that.

There are 2 lines which affect the image position... one is

_msi.ViewportOrigin = new Point(0, 0);

and the other is:

//if (layout == ImageLayout.Vertical) //single column
//    X = ((_msi.ViewportWidth - subImages[i].Width) / 2);

I'm ok to change either of which.. but need some help with that.

The code where the above snippets are taken from:

 private void ArrangeImagesTile(ImageLayout layout)
        {
            if (_msi.ActualWidth <= 0 || _msi.ActualHeight <= 0)
                return;

            _lastMousePos = new Point(0, 0);
            _msi.ViewportOrigin = new Point(0, 0);
            _msi.ViewportWidth = 1;


            Storyboard moveStoryboard = initStoryboard();

            double containerAspectRatio = this._msi.ActualWidth / this._msi.ActualHeight;
            double spaceBetweenImages = 0.005;

            List<SubImage> subImages = new List<SubImage>();
            _imagesToShow.ForEach(subImage => subImages.Add(new SubImage(subImage)));

            // Capture the total width of all images
            double totalImagesWidth = 0.0;
            subImages.ForEach(subImage => totalImagesWidth += subImage.Width);

            // Calculate the total number of rows required to display all the images
            int numRows = 1; // layout - horizontal
            if (layout == ImageLayout.One)
                numRows = 1; //(int)Math.Sqrt((totalImagesWidth / containerAspectRatio) + 1);
            else if (layout == ImageLayout.Four) //.Vertical)
                numRows = 2; // subImages.Count;

            // Assign images to each row
            List<Row> rows = new List<Row>(numRows);
            for (int i = 0; i < numRows; i++)
                rows.Add(new Row(spaceBetweenImages));

            double widthPerRow = totalImagesWidth / numRows;
            double imagesWidth = 0;

            // Separate the images into rows. The total width of all images in a row should not exceed widthPerRow
            for (int i = 0, j = 0; i < numRows; i++, imagesWidth = 0)
            {
                while (imagesWidth < widthPerRow && j < subImages.Count)
                {
                    rows[i].AddImage(subImages[j]);
                    subImages[j].RowNum = i;
                    imagesWidth += subImages[j++].Width;
                }
            }

            // At this point in time the subimage height is 1 
            // If we assume that the total height is also 1 we need to scale the subimages to fit within a total height of 1
            // If the total height is 1, the total width is aspectRatio. Hence (aspectRatio)/(total width of all images in a row) is the scaling factor.
            // Added later: take into account spacing between images
            rows.ForEach(Row => Row.Scale(containerAspectRatio));

            // Calculate the total height, with space between images, of the images across all rows
            // Also adjust the colNum for each image
            double totalImagesHeight = (numRows - 1) * spaceBetweenImages;
            rows.ForEach(Row => totalImagesHeight += Row.Height);

            // The totalImagesHeight should not exceed 1. 
            // if it does, we need to scale all images by a factor of (1 / totalImagesHeight)
            if (totalImagesHeight > 1)
            {
                subImages.ForEach(subImage => subImage.Scale(1 / (totalImagesHeight + spaceBetweenImages)));
                totalImagesHeight = (numRows - 1) * spaceBetweenImages;
                rows.ForEach(Row => totalImagesHeight += Row.Height);
            }

            // Calculate the top and bottom margin
            double margin = (1 - totalImagesHeight) / 2;

            if (_imagesToHide != null)
            {
                // First hide all the images that should not be displayed
                _imagesToHide.ForEach(subImage =>
                {
                    //Do not use opacity for this as it slows down the animation after a few arranges
                    subImage.ViewportWidth = 0;
                });
            }

            // Then display the displayable images to scale
            for (int i = 0; i < _imagesToShow.Count; i++)
            {
                double X = rows[subImages[i].RowNum].CalcX(subImages[i].ColNum);
                //if (layout == ImageLayout.Vertical) //single column
                //    X = ((_msi.ViewportWidth - subImages[i].Width) / 2);

                double Y = margin;
                for (int j = 0; j < subImages[i].RowNum; j++)
                    Y += spaceBetweenImages + rows[j].Height;

                _imagesToShow[i].ViewportWidth = containerAspectRatio / subImages[i].Width;
                animateImage(moveStoryboard, _imagesToShow[i], new Point(-(X / subImages[i].Width), -(Y / subImages[i].Width)));    // for animation, use this statement instead of the next one                
                _imagesToShow[i].Opacity = 1.0;
            }

            if (ImagesRearranged != null)
            {
                ImagesRearranged(this, EventArgs.Empty);
            }

            // Play Storyboard
            moveStoryboard.Begin();
        }

Previous Code Reference which goes to the function above when opening the image in msi:

Backend:

private void RootMultiScaleImage_Loaded(object sender, RoutedEventArgs e)
        {
            // Use the mid point of the image to zoom from    
            var xx = (MultiScaleImage) sender;
            xx.ZoomAboutLogicalPoint(1, 0.5, 0.5);
        }

Front-end:

 <ControlTemplate x:Key="DeepZoomerControlTemplate" TargetType="zoom:DeepZoomer">
            <Grid>
<MultiScaleImage x:Name="RootMultiScaleImage" Loaded="RootMultiScaleImage_Loaded" />
+1  A: 

I agree it's rather confusing, however playing with viewPortWidth and viewPortOrigin you should be able to do it.

  • First you have to check if ViewPortWidth is > 1 (this means your image is currently "narrower" with respect to is parent. If this is not the case, you can check if ViewPortHeight > 1 (the image is shorter and you have to center vertically).

  • Assuming you found that ViewPortWidth is > 1, i.e. you have empty space on the right and want to center the viewport horizontally, you set a negative value to ViewPortOrigin to move the viewport to the right.

Example: ViewPortWidth is 3. This means your image is filling 1/3 of the available width. You have to move it to the right one time its width. ViewportOrigin becomes (-1, 0).

Another example: ViewPortWidth is 4. Your image is filling 1/4 of the available width. If you set ViewPortOrigin to -1.5 the viewport is actually moved 1.5 times its width to the right and actually goes to the center.

The general formula* should be ViewPortOrigin.x = - (ViewPortWidth - 1) / 2

I suggest you look at the doc and draw some sketches on paper until you figure it out.

Francesco De Vittori
You're the man!
Brandon
Would you mind awarding the bounty if my answer actually solved your problem? (Is this against etiquette?)
Francesco De Vittori
no I don't mind, I thought it was automatic until I got the mail reminding me to do so, this is my first time giving a bounty.
Brandon