I have a Canvas having width=200000,height=200000.My screensize height and width is 700 and 1400 respectively.If I display the canvas it won't show entire canvas.So i have used pointerWheelChanged event of canvas and I had calculate how much it was scrolled when scrolling the wheel of mouse.i.e.,new (x,y)coordinates of canvas.Still this it worked fine.But i Don't know how to show the canvas from my new coordinates.
Canvas c=new Canvas();
Image img1=new Image();
Image img2=new Image();
c.Children.Add(img1);
c.Children.Add(img2);
Canvas.SetLeft(img1,100);
Canvas.SetTop(img1,200);
Canvas.SetLeft(img2,2000);
Canvas.SetTop(img2,1500);
My Canvas has two Images ,one at (100,200) and the other at (2000,1500).If my screen height and width are 700 and 1400 respectively.When I run it ,it shows only the first image in the screen ,because second image was in some other place .i.e.,out of screen(It was hidden).How can I show second image ,based on the data calculate from the mousewheelchanged event.I had calculated it,but i don't know how to show canvas from the calculated value??
In PointerWheelChangedEvent i have added it,
Canvas layout = sender as Canvas;
int wheelDelta = e.GetCurrentPoint(layout).Properties.MouseWheelDelta;
Boolean isHorizontalSwipe =
e.GetCurrentPoint(layout).Properties.IsHorizontalMouseWheel;
Point scrollPoint = e.GetCurrentPoint(layout).Position;
The wheelDelta is added or subracted from current canvas Point based on horizontal or vertical swipe.
what I'm trying to do is?
You can assign a new Translation to Canvas to update position of the Canvas based on the wheelDelta. For example:
private void Canvas_PointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
Canvas layout = sender as Canvas;
int wheelDelta = e.GetCurrentPoint(layout).Properties.MouseWheelDelta;
Boolean isHorizontalSwipe =
e.GetCurrentPoint(layout).Properties.IsHorizontalMouseWheel;
if (horizontal swipe)
{
layout.Translation = new Vector3(layout.Translation.X + wheelDelta, layout.Translation.Y, layout.Translation.Z);
}
else
{
layout.Translation = new Vector3(layout.Translation.X, layout.Translation.Y + wheelDelta, layout.Translation.Z);
}
}
Related
Here is what I am trying to do. I have an Image that is 1920X1080. I am showing that image in a PictureBox and allowing a user to draw an ellipse on the screen. Once they finish that I will need to save that image off with the image and ellipse in 1 photo.
So I have tried several ways:
1. Just trying to save the image and ellipse from the PictureBox. No success doing that.
2. To store the location of the ellipse on the picture box and then redraw that ellipse on a new copy of the image using a graphics object. The problem with this one is that when it saves off the ellipse is not in the right place due to the size of the PictureBox and the original image difference.
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
pictureBox1.Cursor = Cursors.Default;
if (isMoving)
{
Circles.Add(mouseDownPosition, mouseMovePosition);
}
isMoving = false;
}
Bitmap newImage = new Bitmap(new Bitmap(#"C:\Personal\test\Sample.jpg"));
Graphics g = Graphics.FromImage(newImage);
foreach (var circle in Circles)
{
g.DrawEllipse(new Pen(Color.Red, 3), new Rectangle(circle.Key, new Size(circle.Value.X - circle.Key.X, circle.Value.Y - circle.Key.Y)));
}
newImage.Save(#"C:\Projects\Projects\SampleCombine.jpg");
I am really just looking for a way to take exactly what I see on the PictureBox and save it as its own jpg.
My take is that I need to figure out how to reposition the "Circle" based on where it was drawn and where it should be drawn on a larger file.
Any ideas?
I have an application in Xamarin Forms, and I need that the user can choose one image from below and drag anywhere he wants to in the top view, the idea is: The below view with the images are the home rooms, and the top view is the Houseplant, the user can create his houseplant by dragging and rotating the images, and then finally save the top view as a jpg or png image.
I've searched here and 2 3 pages of google about drag and etc, but I haven't found anything that could help me with that, I tried pan gesture, tap gesture, but no success =[
Sorry if it is duplicated or something, this is my first post, and I really couldn't find anything.
How can I get this working in Xamarin.Forms or at least with custom renderers and etc?
Thank you guys.
Sample image of what I need
For your image in XAML:
<Image Source="plant.png" x:Name="image"/>
You can actually use pan gesture recognizers to drag and drop images in C#:
Define variables:
double x; // totalX for the pan gesture
double y; // totalY for the pan gesture
Initialize pan gesture and add it to the image:
PanGestureRecognizer panGesture = new PanGestureRecognizer();
panGesture.PanUpdated += PanUpdated;
image.GestureRecognizers.Add(panGesture);
The event handler for the gesture:
void PanUpdated(object sender, PanUpdatedEventArgs args)
{
if (args.StatusType.Equals(GestureStatus.Running)) {
x = args.TotalX;
y = args.TotalY;
image.TranslateTo(x, y, 1);
}
else if (args.StatusType.Equals(GestureStatus.Completed)) {
// set the layout bounds of the image to the new position
// method varies depending on what type of layout you are using for the image
// eg. assume the image is in an absolute layout
// where the layout height is the screen height
// and the layout width is the screen width
Task.Run(() => {
Device.BeginInvokeOnMainThread(async () => // run UI task on main thread
{
await Task.Delay(50); // avoid flickering
var screenWidth = Application.Current.MainPage.Width;
var screenHeight = Application.Current.MainPage.Height;
var b = image.Bounds;
var newBounds = new Rectangle(b.X + x, b.Y + y, b.Width, b.Height);
var newAbsoluteBound =
new Rectangle(newBounds.X / (screenWidth - newBounds.Width),
newBounds.Y / (screenHeight - newBounds.Height),
newBounds.Width / screenWidth,
newBounds.Height / screenHeight);
// set new absolute bounds so a new TranslateTo can be applied
AbsoluteLayout.SetLayoutBounds(image, newAbsoluteBound);
await image.TranslateTo(0, 0, 0);
});
});
}
}
Make sure your page or Image is not in a scrollView.
If ScrollView is enabled for both orientations, Pan-Gesture wont work.
.
.
Have C# forms application with PictureBox embedded in Panel, to take advantage of Panel AutoScroll as suggested in other posts when image and thus PictureBox need to be scrolled horizontally or vertically. Want to zoom the image and recompute AutoScrollPosition to keep same Point visible after zooming. Can double size of PictureBox, then recopy source image, accomplishing zoom. But AutoScrollPosition remains unchanged, thus what was visible before zoom has moved off screen.
How to recompute AutoScrollPosition to keep image focus after zoom?
There are three typical types of zooming:
zoom into the center, triggered by zoom buttons
zoom into the mouse position, triggered by clicking or scroll-wheeling
zoom into a rectangle, by drawing a rectangle
I assume the typical setup: A PictureBox set to SizeMode=Zoom nested in a Panel with AutoScroll=true and zooming that takes care to keep the aspect ratios of Image and PictureBox equal.
Let's start by introducing terminology:
There is an Image we call bitmap and
it is displayed by a PictureBox; let's call it canvas..
.. which is nested in a Panel we call frame
User-friendly zooming needs a fixed point, that is a point that shall stay put.
For 1) it is the center of the frame, for 2) it is the mouse location and for 3) it is the center of the rectangle.
Before zooming we calculate the old zoom ratio, the fixed point in the frame, the fixed point in the canvas and finally the fixed point in the bitmap.
After zoming we calculate the new zoom ratio and the new fixed point in the canvas. Finally we use it to move the canvas to bring the fixed canvas point to the fixed frame point.
Here is an example for zooming into the (current) center; it is a common click event for two buttons and it only doubles and halves the zoom ratio.
Much finer grained factors are of course simple to implement; even better is a fixed list of zoom levels, like Photoshop has!
private void zoom_Click(object sender, EventArgs e)
{
PictureBox canvas = pictureBox1;
Panel frame = panel1;
// Set new zoom level, depending on the button
float zoom = sender == btn_ZoomIn ? 2f : 0.5f;
// calculate old ratio:
float ratio = 1f * canvas.ClientSize.Width / canvas.Image.Width;
// calculate frame fixed pixel:
Point fFix = new Point( frame.Width / 2, frame.Height / 2);
// calculate the canvas fixed pixel:
Point cFix = new Point(-canvas.Left + fFix.X, -canvas.Top + fFix.Y );
// calculate the bitmap fixed pixel:
Point iFix = new Point((int)(cFix.X / ratio),(int)( cFix.Y / ratio));
// do the zoom
canvas.Size = new Size( (int)(canvas.Width * zoom), (int)(canvas.Height * zoom) );
// calculate new ratio:
float ratio2 = 1f * canvas.ClientSize.Width / canvas.Image.Width;
// calculate the new canvas fixed pixel:
Point cFix2 = new Point((int)(iFix.X * ratio2),(int)( iFix.Y * ratio2));
// move the canvas:
canvas.Location = new Point(-cFix2.X + fFix.X, -cFix2.Y + fFix.Y);
}
Note that while one can try to restore the relative AutoScrollValues this is not only hard, because their values are a little quirky but it is also won't be adaptable to the other zoom types.
Here's what I have:
var rand = new Random();
var files = Directory.GetFiles("C:/Projects/MOMENTUM/MOMENTUM/pics/", "*.jpg");
Image bgimage = new Bitmap(files[rand.Next(files.Length)]);
BackgroundImage = bgimage;
Rectangle UsedScreen = Screen.FromControl(this).Bounds;
if (UsedScreen.Height / UsedScreen.Width > bgimage.Height / bgimage.Width)
{
//SET IMAGE HEIGHT TO SCREEN HEIGHT
}
else
{
//SET IMAGE WIDTH TO SCREEN WIDTH
}
As you see, I first choose a random image from a specific folder and then set this as background image.
I want this application to run in full screen. However, if i set the bgimage ImageLayout property to Zoom, there will be this ugly borders and if I set it to stretch, it will look awful.
I want to achieve the following:
I get the current used screensize via screen bounds, and then adjust the image to fit the screen without being distorted.
Part of the image will be cut away but the main aim is, that the entire screen is always filled out by the image (See the comments in if). I don't know how to do this because if I try
bgimage.Height = UsedScreen.Height
I cant overwrite the image height.
Any ideas?
I have a WPF Image control already working in my application. Using ScaleTransform and TranslateTransform, the Image control has zooming and panning functionality working very well.
I was wondering if there is any way to display certain rectangle area of the image source in the Image control using ScaleTransform and TranslateTransform. In order to do that, I think I need to get/set rectangle coordinates of the image source in view port of the Image control. But it seems that I can't find any reference on this.
I think CroppedBitmap can help you:
<CroppedBitmap x:Key="croppedImage"
Source="{StaticResource masterImage}" SourceRect="30 20 105 50"/>
Lucky for me, the rectangles have all the same size so I could find easily a fixed scale value for ScaleTrensformation such as 5.0 which will fit each rectangle into the view port. Once that determined, I could come up with following function to calculate values for TranslateTransform in terms of coordinate in the image. Hope it may help people in a similar situation.
public void SetImageCoordinate(double x, double y)
{
TransformGroup transformGroup = (TransformGroup)image.RenderTransform;
ScaleTransform transform = (ScaleTransform)transformGroup.Children[0];
ImageSource imageSource = image.Source;
BitmapImage bitmapImage = (BitmapImage) imageSource ;
//Now since you got the image displayed in Image control. You can easily map the mouse position to the Pixel scale.
var pixelMousePositionX = -(x ) / bitmapImage.PixelWidth * transform.ScaleX * image.ActualWidth;
var pixelMousePositionY = -(y) / bitmapImage.PixelHeight * transform.ScaleY * image.ActualHeight;
//MessageBox.Show("X: " + pixelMousePositionX + "; Y: " + pixelMousePositionY);
var tt = (TranslateTransform)((TransformGroup)image.RenderTransform).Children.First(tr => tr is TranslateTransform);
tt.X = pixelMousePositionX;
tt.Y = pixelMousePositionY;
}