Is it possible to change an ImageBrush color inside WPF? - wpf

I'm trying to do something quite simple, but I'm not sure if it's possible. I have this image:
Inside my board game project, I use this to indicate the mouse position in the board and stuff like that (being the board a 8x8 grid with a rectangle inside). I'm also setting the grid cell background brush as, say, a SolidColorBrush with Blue color and .25 opacity, while the rectangle that lies above it with the target, or vice-versa, because I couldn't achieve my desired effect, which is, the part that is black to turn full blue, as my brush, while the rest remains with the opacity and etc. The way I did, it was possible to make the black part become blueish, with a transluscent background, but the color in the border isn't quite right yet:
I don't know if I was able to make myself clear, but I guess the picture shows what is my goal.
The code:
ImageBrush targetBrush = new ImageBrush();
targetBrush.ImageSource = new BitmapImage(new Uri("Resources/GameScreen/selectedTile.png", UriKind.Relative));
targetBrush.Opacity = 1;
SolidColorBrush backBrush = new SolidColorBrush(Colors.Blue);
backBrush.Opacity = .25;
tile.Children.Add(new Rectangle());
foreach (object target in tile.Children)
{
if (target.GetType() == typeof(Rectangle))
{
((Rectangle)target).Fill = backBrush;
}
}
tile.Background = targetBrush;
Thanks in advance.

As the image is just a mask you could use a Rectangle with a blue Fill and an OpacityMask set to your image.

Related

Move (zoom and pan) around a large Canvas

I have a lot of images placed on a canvas (~150 pages converted PDF).
I would like to be able to move around from one region to another of this canvas by animating the movement (zoom and pan).
My animation keys are in a listbox. I have a "play" button to play all.
When I click an animation key, my "camera" automatically moves to the defined location.
It's a kind of "Prezi wall".
This is only half or three quarters of an answer really, but hopefully you can fill in the gaps. You could try using the VisualBrush Class. First you set up the visual that the VisualBrush will paint using your full Canvas:
VisualBrush visualBrush = new VisualBrush();
visualBrush.Visual = yourCanvasElement;
You then paint with the Brush onto, let's say, a Rectangle element:
Rectangle rectangle = new Rectangle();
...
rectangle.Fill = visualBrush;
You can then use the VisualBrush.Viewbox property to move the content about. Now I think that there is some way of zooming in and out, but I can't remember at the moment.
Alternatively, you could use the ViewBox class. You can get your zooming effect by changing the size of the content and the ViewBox and get your panning effect by using a ScrollViewer. There's a post on StackOverflow that demonstrates this, so please take a look at the Zooming To Mouse Point With ScrollView and ViewBox in Wpf post for more help with this method.

Can't see stroke

I derive from shape, this is what is in the DefiningGeometry
protected override Geometry DefiningGeometry
{
get
{
topLeft.X = Math.Min(Start.X, End.X);
topLeft.Y = Math.Min(Start.Y, End.Y);
width.X = Math.Abs(Start.X - End.X);
width.Y = Math.Abs(Start.Y - End.Y);
rectBounds.X = topLeft.X;
rectBounds.Y = topLeft.Y;
rectBounds.Width = width.X;
rectBounds.Height = width.Y;
rectGeo.Rect = rectBounds;
return rectGeo;
}
}
I see the fill, but not the stroke, since the sroke is additional to the width and height I tried to make some room for it by setting:
Width = width.X + StrokeThickness;
//same for height.
But then nothing gets drawn, does anyone know what I am doing wrong? By the way the background and the stroke brush are different color.
Stroke is always on top of Fill. Thicknesses below 1.0 are no problem at all, although very thin strokes naturally tend to become invisible.
Fill exactly fills the Shape's geometry. Stroke renders the geometry's outline, half of the stroke lying inside, half outside the shape.
Never add StrokeThickness to your Shape's width (which would only work as you expect on rectangles anyway). See the MSDN for how the Shape's properties behave.
Do not derive from Shape to create simple geometric objects. Use the predefined Rectangle, Ellipse, Line etc. Use Path for more complex geometries and set Path.Data.
Also consult the Shapes and Basic Drawing in WPF Overview and maybe the Geometry Overview in the MSDN.
StrokeThickness for some reason should be larger than 1 (I am guessing the Fill brush is covering it), or don't set the Fill property, and StrokeThickness 1 works.

How to set Transparency color for the output of RenderTargetBitmap?

I'm trying to save a Visual object, which has a transparent background, to a bitmap using RenderTargetBitmap...
public static RenderTargetBitmap RenderToBitmap(this Visual Source, int Width, int Height)
{
var Result = new RenderTargetBitmap(Width, Height, 96, 96, PixelFormats.Default);
Result.Render(Source);
return Result;
}
It works, but the transparent pixels are rendered with black color.
What the simplest way to change these transparent pixels to another color?
If you are saving the image as a JPG, transparent will appear black since JPG does not support transparent channel AFAIK. Possible solution: save as a PNG, or paint with a reasonable background color.
I haven't tested this, but in theory it should work.
Use the CopyPixels() method to extract all the pixel data from your RenderTargetBitmap to an array.
Then query the Alpha channel of all those pixels and where they are equal to 0x00 (fully transparent), set the color to whatever you'd like in the background. If you want to be more elegant, you'd have to do the "color math" to properly set the colors in semi-transparent pixels.
Finally, after you have an adjusted array of pixels, create a new BitmapSource from them.
To save that to disk, you'll probably have to create an Image in memory and set its Source to your new Bitmapsource and run your RenderToBitmap again.
Hope it helps.
EDIT:
After posting this, I had
another thought that may be easier.
If you take a clone or snapshot of the
visual element you're trying to save
and put it into a new in-memory panel
(such as a grid or a canvas), you
could simply change the background of
the panel to be the color you want.
Then you'd use the panel as your
source for RenderTargetBitmap.

Draw custom pushpin in code without using an image

I need to draw a pushpin for the Bing Silverlight control that can have the head be a variable color. I can draw a nice dot like this:
Dim marker As Ellipse = New Ellipse
marker.Fill = New SolidColorBrush(Color.FromArgb(255, 11, 255, 0))
marker.Stroke = New SolidColorBrush(Colors.Gray)
marker.Width = 10
marker.Height = 10
I'll be making dozens of pushpins, each with a slightly different color for the Fill. How can I add the pointy part? I would like to have some amount of flaring out at the top so that it looks more like a pushpin and less like a lollipop.
Examples in C# are welcome as well.
Maybe there's a reason you need it to be a custom one rather than using the built-in pushpin objects, but if not, you can set the background color on those pushpins like so:
myPushpin.Background = new SolidColorBrush(Colors.Gray);
As far as actually drawing your own, I'm not as sure. Could you draw some sort of a triangle?

Image Flipping in WPF

How do you get an image to be reflected in wpf without using the xaml? I have a rectangle with a BitmapImageBrush as its fill. I want to be able to regularly flip this image (X-axis) back and forth at will in C#. I've read about using the ScaleTransform property but this only seems to work in the xaml and that's not what I want.
This is how the image is created:
ImageBrush l = new ImageBrush(new BitmapImage(new Uri(uriPath, UriKind.Relative)));
_animation.Add(l);
_visual = new Rectangle();
_visual.Fill = _animation[0];
_visual.Width = width;
_visual.Height = height;
_visual.Visibility = Visibility.Visible;
_window.GameCanvas.Children.Add(_visual);
_animation is a list of ImageBrushes.
This is really simple, yet I can't seem to figure out how to do it. Please help.
You can still add a scale transform programmatically, rather than using xaml.
For instance, in this article.
To do the flip, set your scale transform to be negative in the direction you want to flip (ie, if horizontal, set x to -1, or -desiredScale if you also want to resize).

Resources