Question

I want to place an image over a parent image and save the final image. So I used parent image inside Canvas and added the child image in the canvas.

Problems:

  1. Right after when i loaded the thumbnail(child) image, if i click on the parent image, then the thumbnail(child) image become in-Visible.
  2. I couldn't place the the thumbnail(child) image over the parent image precisely using the mouse left button up release.
  3. I couldn't save the final image with the actual image Height & Width. The final saved image output height & width is wrong.

please guide me to fix the above problems.

SpecialEffects XAML:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"
         x:Class="ImagePrintUtility.SpecialEffects"
        Title="SpecialEffects" Height="768" Width="1024" >


    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="125"/>
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <DockPanel Grid.Row="0"  HorizontalAlignment="Stretch" Margin="0" Background="AliceBlue" Name="DockPanel1">
            <WrapPanel>

                <StackPanel Margin="5">
                    <Button Content="AddLogo" Click="Button_Click"    Height="50" Width="90" />
                    <Button Content="Reset Logo" x:Name="bresetLogo" Height="50" Width="90" Margin="0,5"  />
                </StackPanel>
                <StackPanel Margin="5">
                    <Button  Name="bSave" Width="90"   Height="50"  Foreground="White" Content="Save" Click="bSave_Click" />
                    <Button x:Name="btnClose" Content="Close" Height="50" Width="90" Margin="0,5"  FontSize="20" Click="btnClose_Click"    />
                </StackPanel>
            </WrapPanel>
        </DockPanel>
        <!--<GridSplitter Grid.Row="1" Grid.RowSpan="1" ResizeDirection="Rows" Width="Auto" Height="10" HorizontalAlignment="Stretch" Margin="0" Name="GridSplitter1" />-->
        <Grid Grid.Row="1"  Margin="0" Background="AliceBlue" Name="Grid1">
            <StackPanel  >

                <Canvas x:Name="canvas"    HorizontalAlignment="Stretch" 
            MouseLeftButtonDown="CanvasMouseLeftButtonDown"
            MouseLeftButtonUp="CanvasMouseLeftButtonUp"
            MouseMove="CanvasMouseMove" Margin="0,0,31,0">
                    <Image x:Name="SpecialPhoto"    Source="IMG_0071.JPG" Height="586" Width="780"  
                     Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Center" />
                </Canvas>
            </StackPanel>


        </Grid>
    </Grid>
</Window>

SpecialEffects.cs Code:

public partial class SpecialEffects : Window
    {
        private string FileNmae;
        private int actualWidth;
        private int actualHeight;
        public SpecialEffects(string getTheFN) //Load the selected Image from ParentWindow
        {
            InitializeComponent();
             FileNmae = getTheFN;

            BitmapImage src = new BitmapImage();
            src.BeginInit();
            src.UriSource = new Uri(FileNmae, UriKind.Relative);
            src.CacheOption = BitmapCacheOption.OnLoad;
            src.EndInit();

            SpecialPhoto.Source = src;

        }

        private Image draggedImage;
        private Point mousePosition;
        bool captured = false;
        private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var image = e.Source as Image;

            if (image != null && canvas.CaptureMouse())
            {
                mousePosition = e.GetPosition(canvas);
                draggedImage = image;
                Panel.SetZIndex(draggedImage, 1); // in case of multiple images
            }
        }

        private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (draggedImage != null)
            {
                canvas.ReleaseMouseCapture();
                Panel.SetZIndex(draggedImage, 0);
                draggedImage = null;
                Mouse.Capture(null);
                captured = false;
            }
        }

        private void CanvasMouseMove(object sender, MouseEventArgs e)
        {
            if (draggedImage != null)
            {
                var position = e.GetPosition(canvas);
                var offset = position - mousePosition;
                mousePosition = position;
                double left = Canvas.GetLeft(draggedImage) + offset.X;
                double top = Canvas.GetTop(draggedImage) + offset.Y;
                if (left < 0)
                {
                    left = 0;
                }
                if (top < 0)
                {
                    top = 0;
                }
                if (left + draggedImage.ActualWidth > SpecialPhoto.ActualWidth)
                {
                    left = SpecialPhoto.ActualWidth - draggedImage.ActualWidth;
                }
                if (top + draggedImage.ActualHeight > SpecialPhoto.ActualHeight)
                {
                    top = SpecialPhoto.ActualHeight - draggedImage.ActualHeight;
                }
                Canvas.SetLeft(draggedImage, left);
                Canvas.SetTop(draggedImage, top);
            }
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void bSave_Click(object sender, RoutedEventArgs e)
        {
            string fileLocation = System.IO.Path.GetDirectoryName(FileNmae);// get the selected file location
            string getFileName = System.IO.Path.GetFileName(FileNmae); //get the seleceted filename
            DateTime time = DateTime.Now;              // Use current time
            string format = "MMMddddHHmmssyyyy";
            string s2 = time.ToString(format) + getFileName; // add $ at front along with the folde name


            string filenamecombined = System.IO.Path.Combine(fileLocation, s2);//combine path. 

            RenderTargetBitmap renderTarget = new RenderTargetBitmap(
             (int)SpecialPhoto.Height,
             (int)SpecialPhoto.Width,
             96, 96, PixelFormats.Pbgra32);

            //renderTarget.Render(ViewedPhoto);
            ModifyPosition(canvas as FrameworkElement);
            renderTarget.Render(canvas);
            ModifyPositionBack(canvas as FrameworkElement);

            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderTarget));

            //string imagePath = System.IO.Path.GetTempFileName();
            using (FileStream stream = new FileStream(filenamecombined, FileMode.Create))
            {
                encoder.Save(stream);
                stream.Dispose();
            }
        }
        private void ModifyPosition(FrameworkElement fe)
        {
            /// get the size of the visual with margin
            System.Windows.Size fs = new System.Windows.Size(
                fe.ActualWidth +
                fe.Margin.Left + fe.Margin.Right,
                fe.ActualHeight +
                fe.Margin.Top + fe.Margin.Bottom);

            /// measure the visual with new size
            fe.Measure(fs);

            /// arrange the visual to align parent with (0,0)
            fe.Arrange(new Rect(
                -fe.Margin.Left, -fe.Margin.Top,
                fs.Width, fs.Height));
        }

        private void ModifyPositionBack(FrameworkElement fe)
        {
            /// remeasure a size smaller than need, wpf will
            /// rearrange it to the original position
            fe.Measure(new System.Windows.Size());
        }

        private void Button_Click(object sender, RoutedEventArgs e) // To load another image
        {
            var dialog = new Microsoft.Win32.OpenFileDialog();
            dialog.Filter =
                "Image Files (*.jpg;*.png; *.jpeg; *.gif; *.bmp)|*.jpg;*.png; *.jpeg; *.gif; *.bmp";

            if ((bool)dialog.ShowDialog())
            {
                BitmapImage src = new BitmapImage();
                src.BeginInit();
                src.UriSource = new Uri(dialog.FileName, UriKind.Relative);
                src.DecodePixelHeight = 120;
                src.DecodePixelWidth = 120;
                src.CacheOption = BitmapCacheOption.OnLoad;
                src.EndInit();

                var image = new Image { Source = src };
                Canvas.SetLeft(image, 0);
                Canvas.SetTop(image, 0);
                canvas.Children.Add(image);
            }
        }
}
Was it helpful?

Solution

Problem 1 - In your xaml for the Image, add IsEnabled="False". This will stop the clicking from hiding the child image.

<Image x:Name="SpecialPhoto" Source="IMG_0071.JPG" Height="586" Width="780"
        IsEnabled="False"
    Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Center" />

Problem 2 - I didn't experience this, maybe you have some sort of mouse acceleration turned on in windows?

Problem 3 - You are using the height for the width and the width for the height. Change:

RenderTargetBitmap renderTarget = new RenderTargetBitmap(
             (int)SpecialPhoto.Height,
             (int)SpecialPhoto.Width,
             96, 96, PixelFormats.Pbgra32);

To:

RenderTargetBitmap renderTarget = new RenderTargetBitmap(
             (int)SpecialPhoto.Width,
             (int)SpecialPhoto.Height,
             96, 96, PixelFormats.Pbgra32);

The code for the comment question you asked:

private void bSave_Click(object sender, RoutedEventArgs e)
{
    string fileLocation = System.IO.Path.GetDirectoryName(FileNmae);// get the selected file location
    string getFileName = System.IO.Path.GetFileName(FileNmae); //get the seleceted filename
    DateTime time = DateTime.Now;              // Use current time
    string format = "MMMddddHHmmssyyyy";
    string s2 = time.ToString(format) + getFileName; // add $ at front along with the folde name


    string filenamecombined = System.IO.Path.Combine(fileLocation, s2);//combine path. 

    #region Change the SpecialPhoto to be the size of its image and adjust the other images to match
    double w = SpecialPhoto.Width;
    double h = SpecialPhoto.Height;
    SpecialPhoto.Width = SpecialPhoto.Source.Width;
    SpecialPhoto.Height = SpecialPhoto.Source.Height;
    // Get the ratio of the change in width/height
    double rw = SpecialPhoto.Width / w;
    double rh = SpecialPhoto.Height / h;
    // Adjust the logos added to keep in the same relative position and size
    foreach (Image img in canvas.Children)
    {
        if (img == SpecialPhoto)
            continue;
        double left = Canvas.GetLeft(img);
        double top = Canvas.GetTop(img);
        Canvas.SetLeft(img, left * rw);
        Canvas.SetTop(img, top * rh);
        img.RenderTransform = new ScaleTransform(rw, rh);
    }
    #endregion

    RenderTargetBitmap renderTarget = new RenderTargetBitmap(
        (int)SpecialPhoto.Width,
        (int)SpecialPhoto.Height,
        96, 96, PixelFormats.Pbgra32);

    //renderTarget.Render(ViewedPhoto);
    ModifyPosition(canvas as FrameworkElement);
    renderTarget.Render(canvas);
    ModifyPositionBack(canvas as FrameworkElement);

    #region Undo the changes we did to the SpecialPhoto/logos
    SpecialPhoto.Width = w;
    SpecialPhoto.Height = h;
    foreach (Image img in canvas.Children)
    {
        if (img == SpecialPhoto)
            continue;
        double left = Canvas.GetLeft(img);
        double top = Canvas.GetTop(img);
        Canvas.SetLeft(img, left / rw);
        Canvas.SetTop(img, top / rh);
        img.RenderTransform = new ScaleTransform(1, 1);
    }
    #endregion

    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(renderTarget));

    //string imagePath = System.IO.Path.GetTempFileName();
    using (FileStream stream = new FileStream(filenamecombined, FileMode.Create))
    {
        encoder.Save(stream);
        stream.Dispose();
    }
}

Code for the 2nd comment question (keeping child image in the parent image):

We need to change two methods. The first method is the CanvasMouseMove:

private void CanvasMouseMove(object sender, MouseEventArgs e)
{
    if (draggedImage != null)
    {
        var position = e.GetPosition(canvas);
        var offset = position - mousePosition;
        mousePosition = position;
        double left = Canvas.GetLeft(draggedImage) + offset.X;
        double top = Canvas.GetTop(draggedImage) + offset.Y;

        Point tl = SpecialPhoto.TranslatePoint(new Point(0, 0), canvas);
        Point br = SpecialPhoto.TranslatePoint(new Point(SpecialPhoto.ActualWidth, SpecialPhoto.ActualHeight), canvas);
        if (left < tl.X)
        {
            left = tl.X;
        }
        if (top < tl.Y)
        {
            top = tl.Y;
        }
        if (left + draggedImage.ActualWidth > br.X)
        {
            left = br.X - draggedImage.ActualWidth;
        }
        if (top + draggedImage.ActualHeight > br.Y)
        {
            top = br.Y - draggedImage.ActualHeight;
        }
        Canvas.SetLeft(draggedImage, left);
        Canvas.SetTop(draggedImage, top);
    }
}

The 2nd method is the Button_Click:

private void Button_Click(object sender, RoutedEventArgs e) // To load another image
{
    var dialog = new Microsoft.Win32.OpenFileDialog();
    dialog.Filter =
        "Image Files (*.jpg;*.png; *.jpeg; *.gif; *.bmp)|*.jpg;*.png; *.jpeg; *.gif; *.bmp";

    if ((bool)dialog.ShowDialog())
    {
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.UriSource = new Uri(dialog.FileName, UriKind.Relative);
        src.DecodePixelHeight = 120;
        src.DecodePixelWidth = 120;
        src.CacheOption = BitmapCacheOption.OnLoad;
        src.EndInit();

        var image = new Image { Source = src };

        Point p = SpecialPhoto.TranslatePoint(new Point(0, 0), canvas);
        Canvas.SetLeft(image, p.X);
        Canvas.SetTop(image, p.Y);
        canvas.Children.Add(image);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top