I have the following code:
LinearGradientBrush linGrBrush = new LinearGradientBrush();
linGrBrush.StartPoint = new Point(0,0);
linGrBrush.EndPoint = new Point(1, 0);
linGrBrush.GradientStops.Add(new GradientStop(Colors.Red, 0.0));
linGrBrush.GradientStops.Add(new GradientStop(Colors.Yellow, 0.5));
linGrBrush.GradientStops.Add(new GradientStop(Colors.White, 1.0));
Rectangle rect = new Rectangle();
rect.Width = 1000;
rect.Height = 1;
rect.Fill = linGrBrush;
rect.Arrange(new Rect(0, 0, 1, 1000));
rect.Measure(new Size(1000, 1));
If I do
myGrid.Children.Add(rect);
Then the gradient is drawn fine on the window.
I want to use this gradient for an intensity map somewhere else, so I need to get the pixels out of it. To do this, I understand I can convert it to a bitmap, using RenderTargetBitmap. Here's the next part of the code:
RenderTargetBitmap bmp = new RenderTargetBitmap(
1000,1,72,72,
PixelFormats.Pbgra32);
bmp.Render(rect);
Image myImage = new Image();
myImage.Source = bmp;
To test this, I do:
myGrid.Children.Add(myImage);
But nothing appears on the window. What am I doing wrong?
Arrange has to be called after Measure, and the Rect values should be passed correctly.
Instead of
rect.Arrange(new Rect(0, 0, 1, 1000)); // wrong width and height
rect.Measure(new Size(1000, 1));
you should do
var rect = new Rectangle { Fill = linGrBrush };
var size = new Size(1000, 1);
rect.Measure(size);
rect.Arrange(new Rect(size));
var bmp = new RenderTargetBitmap(1000, 1, 96, 96, PixelFormats.Pbgra32);
bmp.Render(rect);
Related
Using a sliced strock as a timer
I already have the use of a running sliced strock like a timer. I wanted to do the same with a picture with rounded corners, but it didn't work and it was cropped for a round one.
Real and
Cropped after slice
This is the code I used:
for (int i = 0; i <= 100; i++)
{
Bitmap bitmap2 = Pie(bitmap, i);
var ms = new MemoryStream();
bitmap2.Save(ms, ImageFormat.Png);
RendererManager.LoadImage("NewVisuals.roundedRect" + i, ms);
}
public static Bitmap Pie(System.Drawing.Image source, int pct)
{
Bitmap bitmap = new Bitmap(source.Width, source.Height);
using GraphicsPath graphicsPath = new GraphicsPath();
graphicsPath.AddArc(0, 0, source.Width, source.Height, -90f, 3.6f * (float)pct);
using Graphics graphics = Graphics.FromImage(bitmap);
graphics.SetClip(graphicsPath);
graphics.DrawImage(source, 0, 0, source.Width, source.Height);
return bitmap;
}
How can I avoid cutting corners, but just slice the picture as shown in the example?
Example what i need
Find out how you can slice the outline for later use
I am trying to insert an image 800x500 inside a blank bitmap of 850x610 in the center. The inner image should be in the center and It also has a title on the top. I am attaching an image to illustrate my idea:
public static Bitmap AddBorder(Bitmap srcImage)
{
Bitmap bmp = new Bitmap(srcImage.Width + 45, srcImage.Height + 100);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(srcImage, 0, 0);
g.DrawImage(srcImage, new Rectangle(bmp.Width - 1, 0, 1, bmp.Height));
g.DrawImage(srcImage, new Rectangle(0, bmp.Height - 1, bmp.Width, 1));
return bmp;
}
I have tried to draw it using drawRectangle, drawImage etc. But, I cannot pad it properly as illustrated in the above image. I also cannot add the border to inner image.
I want to get an idea about how to do that.
The below sample sets the new bitmap size, it fills it with a background (black), draws the image in the center and finally after measuring the text will align it in the center (width check only).
public static Bitmap AddBorder(Bitmap srcImage, string text)
{
Bitmap bmp = new Bitmap(850, 610);
using(Graphics g = Graphics.FromImage(bmp))
{
// Background
g.FillRectangle(Brushes.White, new Rectangle(0, 0, bmp.Width, bmp.Height));
// Source Image
Rectangle rect = new Rectangle(25, 55, 800, 500);
g.DrawImage(srcImage, rect);
// Border
int borderThickness = 2;
using(Pen pen = new System.Drawing.Pen(Brushes.Black, borderThickness))
{
pen.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;
g.DrawRectangle(pen, new Rectangle(rect.X - borderThickness, rect.Y - borderThickness, rect.Width + borderThickness, rect.Height + borderThickness));
}
// Text String
using (Font font = new Font("Arial", 16))
{
SizeF size = g.MeasureString(text, font);
g.DrawString(text, font, Brushes.Black, new PointF((bmp.Width / 2) - (size.Width / 2), rect.Top - (size.Height + borderThickness)));
}
}
return bmp;
}
Updated based on comments (Added also text above the centered image)!
Under Windows Forms, I take a full size screenshot of a specific window that has a specific window size, I save it into a Bitmap object, then, I declared a Rectangle structure to crop a region of that Bitmap, because later I need to manipulate only a very specific part/region of the screenshot...
To make things simpler for this question, lets say the window and bitmap size is 640x480, the Rectangle's X,Y is: 436,150 and the Width,Height is: 146,170, and what I crop from the screenshot (the bitmap) is a balloon image. The window is a videogame.
The problem is that when the window size increase, the balloon image increase too, as obvious, so the x,y and width/height of my rectangle for a window size of 640x480 will not properly capture/crop the entire balloon image when the window of the game has a bigger size...
I need to know how can I calculate the x,y width/height that my rectangle should have to properly crop the balloon image when the window size changes. I need to adapt the rectangle.
So, if this is the predefined size and rectangle I have:
{ new Size(640, 480), new Rectangle(436, 150, 146, 170) }
From that, the approximated adapted values that the rectangle should have to properly crop the same equivalent area in a window size of 800x600 and 1280x768 it would be more or less these:
{ new Size(800, 600), new Rectangle(546, 186, 186, 212) }
{ new Size(1280, 768), new Rectangle(830, 232, 240, 274) }
...are just approximated values, but not perfect, because I did it manually since Im not sure which is the way to calculate and automate this math operation.
I hope my question and problem was understood. Thankyou in advance.
Maybe you're over-thinking it, but all you need to do is capture the percentage change between the original size and the new size (for both X and Y), and then apply that percentage to the properties of the original rectangle to get the new rectangle.
For example:
public static Rectangle GetNewRectangle(Size oldSize, Rectangle oldRectangle,
Size newSize)
{
var percentChangeX = (double)newSize.Width / oldSize.Width;
var percentChangeY = (double)newSize.Height / oldSize.Height;
return new Rectangle
{
X = (int)(oldRectangle.X * percentChangeX),
Y = (int)(oldRectangle.Y * percentChangeY),
Width = (int)(oldRectangle.Width * percentChangeX),
Height = (int)(oldRectangle.Height * percentChangeY)
};
}
Example usage:
// Helper method to display size and rectangle properties
private static string GetDisplayValues(Size size, Rectangle rect)
{
return $" - size: {size.Width} x {size.Height}\n" +
$" - rect: {rect.X}, {rect.Y} : {rect.Width} x {rect.Height}\n";
}
private static void Main()
{
var size = new Size(640, 480);
var rect = new Rectangle(436, 150, 146, 170);
Console.WriteLine($"Original:\n{GetDisplayValues(size, rect)}");
var newSize = new Size(800, 600);
var newRect = GetNewRectangle(size, rect, newSize);
Console.WriteLine($"Resized:\n{GetDisplayValues(newSize, newRect)}");
GetKeyFromUser("\nDone! Press any key to exit...");
}
Output
Try this:
if width 640:
X = 436 / 640 = 0.68125 (68.125%)
W = 146 / 640 = 0.22125 (22.125%)
if heigth 480:
Y = 150 / 480 = 0.3125 (31.25%)
H = 170 / 480 = 0.3541666666666666666666666667 (35.41666666666666666666666667%)
Considering the size of the form as this.Width, and the height as this.Height:
decimal pX = 0.68125;
decimal pW = 0.22125;
decimal pY = 0.3125;
decimal pH = 0.3541666666666666666666666667;
Rectangle rect = new Rectangle(this.Width * pX, this.Height * pY, this.Width * pW, this.Height * pH);
Given a source Bitmap and a selection Rectangle inside its boundaries:
RectangleF SourceRect = new Rectangle(Point.Empty, SourceBitmap.Size);
Rectangle SelectionRect = new Rectangle([Point], [Size]);
When the SourceBitmap changes its size, the new size of the selection rectangle is calculated using the scale factor given by the relation between the old size and the new size of the SourceBitmap:
RectangleF DestinationRect = new RectangleF(Point.Empty, InflatedBitmap.Size);
SizeF ScaleFactor = new SizeF(DestinationRect.Width / SourceRect.Width,
DestinationRect.Height / SourceRect.Height);
PointF NewPosition = new PointF(SelectionRect.X * ScaleFactor.Width, SelectionRect.Y * ScaleFactor.Height);
SizeF NewSize = new SizeF(SelectionRect.Width * ScaleFactor.Width, SelectionRect.Height * ScaleFactor.Height);
RectangleF InflatedSelection = new RectangleF(NewPosition, NewSize);
With a SourceBitmap and a selection rectangle sized as:
RectangleF SourceRect = new RectangleF(0, 0, 640, 480);
RectangleF SelectionRect = new RectangleF(436, 150, 146, 170);
If the inflated bitmaps are sized as:
RectangleF DestinationRect1 = new RectangleF(0, 0, 800, 600);
RectangleF DestinationRect2 = new RectangleF(0, 0, 1280, 768);
The Inflated selection with a scale factor of (1.25, 1.25) and (2, 1.6) will be (rounded down):
RectangleF InflatedSelection1 = new RectangleF(545, 187, 182, 212);
RectangleF InflatedSelection2 = new RectangleF(872, 240, 292, 272);
I try to programmatically draw a rectangle with rounded corners in my WPF project. I'm pretty new to WPF and trying to figure out how drawing works since it's much different than WinForms. I'm using >this< link for the rounded rectangle method (my method is the same as on that website). Here is my code:
Rect rect = new Rect();
rect.Width = Width - BorderSize;
rect.Height = Height - BorderSize;
DrawingVisual drawingVisual = new DrawingVisual();
using (var draw = drawingVisual.RenderOpen())
{
DrawRoundedRectangle(draw, new SolidColorBrush(Color.FromRgb(0, 0, 0)),
new Pen(new SolidColorBrush(Color.FromRgb(0, 0, 0)), BorderSize), rect, new CornerRadius(5, 5, 5, 5));
}
ContentPresenter content = new ContentPresenter();
content.Content = drawingVisual;
previewcanvas.Children.Add(content);
This is my output on the canvas:
Not really what I'm expecting ;) there shouldn't be any text in there to begin with.
Hope someone can help me to draw the rounded rectangle!
edit
Some extra info, I need to be able to set each individual corner.
Rect rect = new Rect();
rect.Width = Width - BorderSize;
rect.Height = Height - BorderSize;
DrawingVisual drawingVisual = new DrawingVisual();
using (var draw = drawingVisual.RenderOpen())
{
DrawRoundedRectangle(draw, new SolidColorBrush(Color.FromRgb(0, 0, 0)),
new Pen(new SolidColorBrush(Color.FromRgb(0, 0, 0)), BorderSize), rect, new CornerRadius(5, 5, 5, 5));
}
RenderTargetBitmap rtb = new RenderTargetBitmap(rect.Width, rect.Height, 96, 96, PixelFormats.Default);
rtb.Render(drawingVisual);
Image image = new Image();
image.Source = rtb;
previewcanvas.Children.Add(image);
Use RadiusX and RadiusY:
rect = new Rectangle
{
Stroke = Brushes.Red,
StrokeThickness = 2,
Width = 100,
Height = 100,
RadiusX = 25,
RadiusY = 25
};
Canvas.SetLeft(rect, startPoint.X);
Canvas.SetTop(rect, startPoint.X);
canvas.Children.Add(rect);
Xaml:
<Canvas x:Name="canvas"/>
After searching I found a much easier solution:
Border border = new Border();
border.BorderThickness = new Thickness(2);
border.CornerRadius = new CornerRadius(5,15,25,35);
border.BorderBrush = (SolidColorBrush)(new BrushConverter().ConvertFrom("#000"));
border.Background = (SolidColorBrush)(new BrushConverter().ConvertFrom("#000"));
border.Width = 100;
border.Height = 100;
border.Margin = new Thickness(10);
previewcanvas.Children.Add(border);
It's kind of a cheat (since its not a Rectangle), but it works. Here's my result:
I want to resize the image coming through file uploader. For that I was referred to the following:
How to set Bitmap.Width and Bitmap.height
(Javed Akram's Answer)
Made following code:
Dim imgSmall As Bitmap = New Bitmap(FUpload.PostedFile.InputStream, False)
imgSmall.Size = New Size(250, 300)
But giving me error:
Size is read-only property.
How can I resize the image in this case?
It is read-only; you'll have to create a new bitmap from it. Try this: -
internal static Image ScaleByPercent(Image image, Size size, float percent)
{
int sourceWidth = image.Width,
sourceHeight = image.Height;
int destWidth = (int)(sourceWidth * percent),
destHeight = (int)(sourceHeight * percent);
if (destWidth <= 0)
{
destWidth = 1;
}
if (destHeight <= 0)
{
destHeight = 1;
}
var resizedImage = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb);
resizedImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
// get handle to new bitmap
using (var graphics = Graphics.FromImage(resizedImage))
{
InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// create a rect covering the destination area
var destRect = new Rectangle(0, 0, destWidth, destHeight);
var brush = new SolidBrush(drawing.Color.White);
graphics.FillRectangle(brush, destRect);
// draw the source image to the destination rect
graphics.DrawImage(image,
destRect,
new Rectangle(0, 0, sourceWidth, sourceHeight),
GraphicsUnit.Pixel);
}
return resizedImage;
}
This is from a site I have in production; if you want I can send you the code that works out how to keep the correct aspect ratio when resizing (i.e. what gets passed in the 'size' parameter)
Hope that helps