Cut out part of an image - c#

I want to cut out a Part of an image.
My plan was to create a layer with a Image, but the image overflows the layer.
It should look like this example:
Any ideas? Thanks.
using (CGLayer starLayer = CGLayer.Create (g, rect.Size)) {
// set fill to blue
starLayer.Context.SetFillColor (0f, 0f, 1f, 0.4f);
starLayer.Context.AddLines (myStarPoints);
starLayer.Context.AddQuadCurveToPoint(this.points [3].X, this.points [3].Y, this.points [2].X, this.points [2].Y);
starLayer.Context.AddQuadCurveToPoint(this.points [5].X, this.points [5].Y, this.points [4].X, this.points [4].Y);
starLayer.Context.FillPath ();
double width = Math.Abs((double)(this.points [1].X - this.points [0].X));
float prop = this.tmpimage.Size.Width / (float)width;
float height = (this.tmpimage.Size.Height / prop);
double centerteeth = (Math.Sqrt (Math.Pow ((this.points [4].X - this.points [2].X), 2.0) + Math.Pow ((this.points [4].Y - this.points [2].Y), 2.0))) / 2 - (width/2);
starLayer.Context.DrawImage (new RectangleF ((float)centerteeth + this.points[2].X, this.points [2].Y, (float)width, height), this.imagerotated.CGImage);
// draw the layer onto our screen
float starYPos = 5;
float starXPos = 5;
g.DrawLayer (starLayer, new PointF (starXPos, starYPos));
}

If you are looking for a quick solution to get it done, can you use two images to accomplish what you need? (A black image, then the background) Put one UIImageView on top of another?
I usually only drop into using CoreGraphics for two reasons:
There is no other way to accomplish my goal
Using plain UIViews are not performant enough

Now I found a solution that worked for me, thank you for help anyway.
The imagesublayer is movable in the mainlayer.
Thats my solution:
CALayer imageLayer = new CALayer (Layer);
imageLayer.Frame = Layer.Bounds;
imageLayer.BackgroundColor = UIColor.Black.CGColor;
CAShapeLayer maskLayer = new CAShapeLayer();
maskLayer.FillRule = CAShapeLayer.FillRuleEvenOdd;
maskLayer.Frame = Frame;
double width = Math.Abs((double)(this.points [1].X - this.points [0].X));
float prop = this.tmpimage.Size.Width / (float)width;
float height = (this.tmpimage.Size.Height / prop);
CALayer lay = new CALayer ();
lay.Bounds = new RectangleF (0, 0, (float)width, height);
lay.Position = this.points[6];
lay.Contents = this.tmpimage.CGImage;
layers [6] = lay;
imageLayer.AddSublayer (lay);
CGPath p1 = new CGPath();
p1.MoveToPoint (this.points [2]);
p1.AddQuadCurveToPoint(this.points [3].X, this.points [3].Y, this.points [4].X, this.points [4].Y);
p1.AddQuadCurveToPoint(this.points [5].X, this.points [5].Y, this.points [2].X, this.points [2].Y);
maskLayer.Path = p1;
imageLayer.Mask = maskLayer;
Layer.AddSublayer (imageLayer);
CAShapeLayer pathLayer1 = new CAShapeLayer ();
pathLayer1.Path = maskLayer.Path;
pathLayer1.LineWidth = 0f;
pathLayer1.StrokeColor = UIColor.Clear.CGColor;
pathLayer1.FillColor = UIColor.Clear.CGColor;
Layer.AddSublayer (pathLayer1);

Related

How to use DataGridViewImageColumn to display images using zoom and also keeping the aspect ratio?

My code
Building the column
IconColumn = new DataGridViewImageColumn()
{
Name = "Icon",
HeaderText = "Icon",
SortMode = DataGridViewColumnSortMode.NotSortable,
Width = 50,
ImageLayout = DataGridViewImageCellLayout.Stretch,
Resizable = DataGridViewTriState.False
};
IconColumn.DefaultCellStyle.NullValue = null;
IconColumn.CellTemplate = new ClockDataGridViewIconCell();
Setting an icon
float maxHeight = 200;
float maxWidth = 200;
var r = new Rectangle(0,
0,
(int)Math.Round(maxWidth),
(int)Math.Round(maxHeight)
);
MyClockData.Icon = Utils.ResizeToFitBoundingBox(
new Bitmap(fd.FileName),
r);
The ResizeToFitBoundingBox method
internal static Bitmap ResizeToFitBoundingBox(Image image, in Rectangle box)
{
float maxHeight = box.Width;
float maxWidth = box.Height;
float x = Math.Min(maxWidth / image.Width,
maxHeight / image.Height);
float newW = (float)image.Width * x;
float newH = (float)image.Height * x;
var bmp = new Bitmap((int)Math.Round(maxWidth),
(int)Math.Round(maxHeight));
bmp.MakeTransparent();
using (Graphics gr = Graphics.FromImage(bmp))
{
gr.DrawImage(image, (bmp.Width - newW) / 2,
(bmp.Height - newH) / 2, newW, newH);
}
return bmp;
}
Example icon
I have tried all the 4 possible values for DataGridViewImageColumn.ImageLayout and the cell looks the same:
Normal
Not Set
Stretch
Zoom
None of them Works for what I wish. The official documentation is here. I would like the same behaviour as Forms.ImageLayout.Zoom.
Note: I use .NET Framework v4.6.1.
I solved the problem by adding this line:
IconColumn.ImageLayout = DataGridViewImageCellLayout.Zoom;
after each statement which adds or updates an icon in the DataGridView.
It seems that setting this property to the same value as before repaints the icons in the column in the way the value of the property suggests.

Draw a circle on the MapControl

I am aware of technique to draw a circle by generating points by basic math and then use the points to create a MapPolygon.
Is there another way?
For example, I see there is a class for circles:
public sealed class Geocircle : IGeocircle, IGeoshape
But I don't know how to use it, there doesn't seem to be any MapLayer for it.
Geocircle is used to create a geographic circle object for the given position and radius. It often use to make map Geofence, but not to display the cycle on the map.
There many way that draw a circle on the map
generating points by basic math
for (var i = 0; i < 360; i++)
{
//draw a cycle
BasicGeoposition point = new BasicGeoposition()
{ Latitude = centerLatitude + ri * Math.Cos(3.6 * i * 3.14 / 180), Longitude = centerLongitude + ri * Math.Sin(3.6 * i * 3.14 / 180) };
list.Add(point);
}
Add Ellipse to map
private void MyMap_Loaded(object sender, RoutedEventArgs e)
{
// Specify a known location.
BasicGeoposition snPosition = new BasicGeoposition { Latitude = 47.620, Longitude = -122.349 };
Geopoint snPoint = new Geopoint(snPosition);
// Create a XAML border.
var ellipse1 = new Ellipse();
ellipse1.Fill = new SolidColorBrush(Windows.UI.Colors.Coral);
ellipse1.Width = 200;
ellipse1.Height = 200;
// Center the map over the POI.
MyMap.Center = snPoint;
MyMap.ZoomLevel = 14;
// Add XAML to the map.
MyMap.Children.Add(ellipse1);
MapControl.SetLocation(ellipse1, snPoint);
MapControl.SetNormalizedAnchorPoint(ellipse1, new Point(0.5, 0.5));
}
You can create XAML shapes and add them as a child to the MapControl. Then you set their location using SetLocation:
var circle = new Ellipse() {
Height = 20,
Width = 20,
Fill = new SolidColorBrush(Colors.Blue)
};
map.Children.Add(circle);
var location = new Geopoint(new BasicGeoposition()
{
Latitude = 51.1789,
Longitude = -1.8261
});
map.SetLocation(circle, location);
The Geocircle class is used for geofencing, so it is not applicable here.

Usage of a Picture instead of Rectangle Shape in C#

Background: I am currently busy with showing position of a Vehicle on a Zoomable Canvas based on the Position (X,Y) and Orientation (for Rotation). I use Rectangle for visualizing the vehicle. Everything works well but I got a bit greedy and now I want to replace the Rectangle with Top View Picture of the Vehicle, so it looks that the vehicle itself is moving instead a Rectangle.
Code Below:
private void PaintLocationVehicle(VehicleClass vc)
{
IEnumerable<Rectangle> collection = vc.ZoomableCanvas.Children.OfType<Rectangle>().Where(x => x.Name == _vehicleobjectname);
List<Rectangle> listE = collection.ToList<Rectangle>();
for (int e = 0; e < listE.Count; e++)
vc.ZoomableCanvas.Children.Remove(listE[e]);
// Assign X and Y Position from Vehicle
double drawingX = vc.gCurrentX * GlobalVar.DrawingQ;
double drawingY = vc.gCurrentY * GlobalVar.DrawingQ;
// Scale Length and Width of Vehicle
double tractorWidthScaled = vc.tractorWidth * GlobalVar.DrawingQ;
double tractorLengthScaled = vc.tractorLength * GlobalVar.DrawingQ;
// Get Drawing Location
double _locationX = drawingX - (tractorLengthScaled / 2);
double _locationY = drawingY - ((tractorWidthScaled / 2));
RotateTransform rotation = new RotateTransform();
// Angle in 10th of a Degree
rotation.Angle = vc.gCurrentTheeta/10 ;
double i = 0;
//paint the node
Rectangle _rectangle = new Rectangle();
_rectangle.Stroke = new SolidColorBrush((Color)ColorConverter.ConvertFromString(vc.VehicleColor == "" ? "Black" : vc.VehicleColor));
_rectangle.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString(vc.VehicleColor == "" ? "Black" : vc.VehicleColor));
i += 0;
_rectangle.Width = tractorLengthScaled ;
_rectangle.Height = tractorWidthScaled;
rotation.CenterX = _rectangle.Width / 2;
rotation.CenterY = _rectangle.Height / 2;
_rectangle.RenderTransform = rotation;
Canvas.SetTop(_rectangle, _locationY + i);
Canvas.SetLeft(_rectangle, _locationX + i);
_rectangle.SetValue(ZoomableCanvas.ZIndexProperty, 2);
string _tooltipmsg = "Canvas: " + vc.ZoomableCanvas.Name;
// Assign ToolTip Values for User
_tooltipmsg += "\nX: " + vc.gCurrentX;
_tooltipmsg += "\nY: " + vc.gCurrentY;
_rectangle.ToolTip = _tooltipmsg;
_rectangle.Name = _vehicleobjectname;
//add to the canvas
vc.ZoomableCanvas.Children.Add(_rectangle);
}
Note: VehicleClass holds all the Values for a certain Vehicle. DrawingQ holds the transformation scale from Reality to Zoomable Canvas.
So the issues I forsee:
How to append the Size of a Jpeg file to get the size same as
Rectangle?
What kind of Shape object shall I use? Please
suggest.
If i undrestand you correctly. you wanted to show an image of the vechicle inside the rectangle. in order to do that you can use
ImageBrush and assign to the Rectangle Fill property
something like this
Rectangle rect = new Rectangle();
rect.Width = 100;
rect.Height = 100;
ImageBrush img = new ImageBrush();
BitmapImage bmp = new BitmapImage();
bmp.BeginInit();
bmp.UriSource = new Uri("vehicle image path");
bmp.EndInit();
img.ImageSource = bmp;
rect.Fill = img;
I hope that helps

Add Point to Canvas

I'm coding in Microsoft Visual Studio 2010 Express for Windows Phone. I need to add a point onto a Canvas, but I can't...
for (float x = x1; x < x2; x += dx)
{
Point poin = new Point();
poin.X = x;
poin.Y = Math.Sin(x);
canvas1.Children.Add(poin);
}
Studio says:
Error 2 Argument 1: cannot convert from 'System.Windows.Point' to 'System.Windows.UIElement'
My question is: how do I add a point onto a Canvas?
From your code snippet I assume you're trying to draw a curve. To do this, you can look into GraphicsPath. Instead of drawing individual points, you can use the points as coordinates, which you connect through lines. Then, in your code, you can create a GraphicsPath using the AddLine method.
This could then be drawn onto a bitmap, for example.
EDIT
Sample (not tested):
GraphicsPath p = new GraphicsPath();
for (float x = x1; x < x2; x += dx)
{
Point point = new Point();
point.X = x;
point.Y = Math.Sin(x);
Point point2 = new Point();
point2.X = x+dx;
point2.Y = Math.Sin(x+dx);
p.AddLine(point, point2);
}
graphics.DrawPath(p);
Another way would be to use the WPF Path class, which would work about the same, but is a real UI element which you can add to the children of a Canvas.
EDIT
People have pointed out that the above code is Windows Forms code. Well, here's what you can do in WPF:
myPolygon = new Polygon();
myPolygon.Stroke = System.Windows.Media.Brushes.Black;
myPolygon.Fill = System.Windows.Media.Brushes.LightSeaGreen;
myPolygon.StrokeThickness = 2;
myPolygon.HorizontalAlignment = HorizontalAlignment.Left;
myPolygon.VerticalAlignment = VerticalAlignment.Center;
PointCollection points = new PointCollection();
for (float x = x1; x < x2; x += dx)
{
Point p = new Point(x, Math.Sin(x));
points.Add(p);
}
myPolygon.Points = points;
canvas1.Children.Add(myPolygon);
If it is 'just a single point you want to add, you can add a tiny rectangle or ellipse to the canvas.
If you want to set a lot of points or a couple points many times, I suggest you create an array of pixel data (colors) and write those to a WriteableBitmap
The Point you used is not a UIElement but a struct, please use Line instead.
Line lne = new Line();
lne.X1 = 10;
lne.X2 = 11;
lne.Y1 = 10;
lne.Y2 = 10;
canvas1.Children.Add(lne);
You get the idea...
Edit
changed:
lne.X2 = 10 to lne.X2 = 11
As per the error, the children of the Canvas control must be derivatives of the System.Windows.UIElement class: System.Windows.Point is not. To achieve what you are doing, you would be best looking into using the geometry within WPF. See here for an article on how to do so.
Try adding a ellipse
Ellipse myEllipse = new Ellipse();
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
myEllipse.Fill = mySolidColorBrush;
myEllipse.StrokeThickness = 2;
myEllipse.Stroke = Brushes.White;
myEllipse.Width = 200;
myEllipse.Height = 100;
Canvas.SetTop(myEllipse,50);
Canvas.SetLeft(myEllipse,80);
myCanvas.Children.Add(myEllipse);

How do I scale image in DirectX device?

I have a control (picturebox), in which I want to draw an 2D image with the help of DirectX.
I have a display and sprite, and it works fine.
// Some code here...
_device = new Device(0, DeviceType.Hardware, pictureBox1,
CreateFlags.SoftwareVertexProcessing,
presentParams);
_sprite = new Sprite(_device);
// ...
_sprite.Draw(texture, textureSize, _center, position, Color.White);
The problem is that texture size is much larger than picturebox, and I just want to find the way to fit it there.
I tried to set device.Transform property but it doesn't help:
var transform = GetTransformationMatrix(textureSize.Width, textureSize.Height);
_device.SetTransform(TransformType.Texture0, transform);
Here is GetTransform method:
Matrix GetTransformationMatrix(float width, float height)
{
var scaleWidth = pictureBox1.Width /width ;
var scaleHeight = pictureBox1.Height / height;
var transform = new Matrix();
transform.M11 = scaleWidth;
transform.M12 = 0;
transform.M21 = 0;
transform.M22 = scaleHeight;
return transform;
}
Thanks for any solution || help.
The solution was just to use this:
var transformMatrix = Matrix.Scaling(scaleWidth, scaleHeight, 0.0F);
instead of hand-made method.

Categories

Resources