C# tinting an ImageBrush - c#

Is it somehow possible to change the hue of an imagebrush. I'm currently using an imagebrush to create a texture material in wpf 3d. To get selection and grouping effects, i need up to three materials per model. This results in quite the performance hit. Here is the current code:
DiffuseMaterial itemImageMaterial = new DiffuseMaterial(new ImageBrush(ItemTextures[nr]) { Stretch = Stretch.Fill });
var meshGeom = new MeshGeometry3D();
meshGeom.Positions = cubesPositions;
meshGeom.TriangleIndices = cubesIndeces;
GeometryModel3D geoMod = new GeometryModel3D();
geoMod.Geometry = meshGeom;
MaterialGroup mg = new MaterialGroup();
mg.Children.Add(itemImageMaterial);
if (applyGroupOverlay) mg.Children.Add(groupMaterials[groupNr]);
if (applyHighlight) mg.Children.Add(highlightMaterials[highlightNr]);
mg.Freeze();
geoMod.Material = mg;
(geoMod.Geometry as MeshGeometry3D).TextureCoordinates = cubesTextureCoords;
Visual3DModel = geoMod;
nb. ItemTextures[nr] is a freezed BitmapImage
Hopefully there is a solution so that the code can look something like this:
ImageBrush brush = new ImageBrush(ItemTextures[nr]) { Stretch = Stretch.Fill }
if (applyGroupOverlay){
//tint brush here
}
if (applyHighlight) {
//tint brush some more here
}
DiffuseMaterial itemImageMaterial = new DiffuseMaterial(brush);
var meshGeom = new MeshGeometry3D();
meshGeom.Positions = cubesPositions;
meshGeom.TriangleIndices = cubesIndeces;
GeometryModel3D geoMod = new GeometryModel3D();
geoMod.Geometry = meshGeom;
geoMod.Material = itemImageMaterial;
(geoMod.Geometry as MeshGeometry3D).TextureCoordinates = cubesTextureCoords;
This way, only a single material is needed to create the desired effects.

Related

How to bind Gradient color in collection view

I have to bind gradient colors in a collection view in a grid.
i have tried with xmal.cs side but it doesnot working.
foreach(var item in abc)
{
if ((item.index % 2) == 0)
{
GradientStopCollection gradientStops = new GradientStopCollection();
gradientStops.Add(new GradientStop() { Color = Color.FromHex("#840CA3"), Offset = (float)0.1 });
gradientStops.Add(new GradientStop() { Color = Color.FromHex("#F4B6BF"), Offset = (float)1.0 });
LinearGradientBrush linearGradientBrush = new LinearGradientBrush()
{
EndPoint = new Point(0, 1),
GradientStops = gradientStops
};
item.BackgroundColor = linearGradientBrush;
}
else
{
GradientStopCollection gradientStops = new GradientStopCollection();
gradientStops.Add(new GradientStop() { Color = Color.FromHex("#A30C42"), Offset = (float)0.1 });
gradientStops.Add(new GradientStop() { Color = Color.FromHex("#F4B6BF"), Offset = (float)1.0 });
LinearGradientBrush linearGradientBrush = new LinearGradientBrush()
{
EndPoint = new Point(0, 1),
GradientStops = gradientStops
};
item.BackgroundColor = linearGradientBrush;
}
}
MycollectionView.itemsource = abc;
Quick answer:
You need Background, not Background Color.
Actually, what you need to do is:
Avoid this terrible design. You need to use binding, and instead of adding VisualElements, you need to be using DataTriggers, Styles and ItemTemplates.
You manipulate the data of your models. You should not iterate and assign individualy the color of your visual elements.
Spend few days to learn how to design your app properly, and it will save you years of working on problems.

WPF custom effect animation programmatically

I try to use pixel shader effect animation programmatically in WPF, but below code uses a lot of CPU power.
Is there other method?
â– Call Method
Setting effect while doing sequence.
private void Button_Click(object sender, RoutedEventArgs e)
{
string path = System.IO.Path.GetFullPath(#"WateryEffect.ps");
var uri = new Uri(path);
WpfEffect wpfeffect = new WpfEffect(uri);
BitmapImage img1 = new BitmapImage(new Uri(System.IO.Path.GetFullPath(#"3a28168e68.jpg")));
ImageBrush imgbrush1 = new ImageBrush(img1);
wpfeffect.input1 = imgbrush1;
VisualBrush vbrush = new VisualBrush(text1);
wpfeffect.input1 = vbrush;
BitmapImage img2 = new BitmapImage(new Uri(System.IO.Path.GetFullPath(#"e98f58fa-2e58-4d38-9949-f3f40b6a2b13_7.jpg")));
ImageBrush imgbrush2 = new ImageBrush(img2);
wpfeffect.input2 = imgbrush2;
double i = 1;
do
{
wpfeffect.para0 = i;
image1.Effect = wpfeffect;
image2.Effect = wpfeffect;
image3.Effect = wpfeffect;
image4.Effect = wpfeffect;
DoEvents();
i = i - 0.0001;
} while (i > -1);
}
Doing a loop for this goes against the whole advantage of WPF. You need to run this effect update as a DoubleAnimation. I don't have your .ps file but I'm assuming that para01 is a DependencyProperty.
Try this code:
DoubleAnimation da =
new DoubleAnimation(0.0, 1.0, new Duration(new TimeSpan(0,0,1)); // adjust as needed
(image1.Effect as WpfEffect).BeginAnimation(WpfEffect.para01Property, da);
(image2.Effect as WpfEffect).BeginAnimation(WpfEffect.para01Property, da);
(image3.Effect as WpfEffect).BeginAnimation(WpfEffect.para01Property, da);
(image4.Effect as WpfEffect).BeginAnimation(WpfEffect.para01Property, da);

Apply transformation on an image on C# for a Windows Phone application

I'm working on a mini-game where I need to make images go from their initial position to another using a translation transformation.
The problem is: I don't know how to proceed to apply the translation.
So here's the code used to generate my images.
Image myImage1 = new Image();
myImage1.Source = new BitmapImage(new Uri("/Images/image1.png", UriKind.Relative));
myImage1.Name = "image" + index++.ToString();
myImage1.Tap += myImage_Tap;
Canvas.SetLeft(image, 200);
Canvas.SetTop(image, 600);
gameArea.Children.Add(image);
Thanks for your time.
You have two choices to move your image around. The first is using a Canvas like your code shows, but you have to make sure your element is actually within a Canvas. Is your "gameArea" a Canvas? If it's not, your code won't work. The other option is to use Transforms.
var myImage1 = new Image
{
Source = new BitmapImage(new Uri("/Images/image1.png", UriKind.Relative)),
Name = "image" + index++.ToString(),
Tap += myImage_Tap,
RenderTransform = new TranslateTransform
{
X = 200,
Y = 600
}
};
gameArea.Children.Add(image);
Now gameArea can be any type of Panel and it will work.
Note that when using a Canvas, your Top and Left will be from the upper left corner of the Canvas. When using a Transform, your X and Y will be relative to where the element would have originally be drawn.
UPDATE -- Helper class to do simple animations using a Canvas
public sealed class ElementAnimator
{
private readonly UIElement _element;
public ElementAnimator(UIElement element)
{
if (null == element)
{
throw new ArgumentNullException("element", "Element can't be null.");
}
_element = element;
}
public void AnimateToPoint(Point point, int durationInMilliseconds = 300)
{
var duration = new Duration(TimeSpan.FromMilliseconds(durationInMilliseconds));
var easing = new BackEase
{
Amplitude = .3
};
var sb = new Storyboard
{
Duration = duration
};
var animateLeft = new DoubleAnimation
{
From = Canvas.GetLeft(_element),
To = point.X,
Duration = duration,
EasingFunction = easing,
};
var animateTop = new DoubleAnimation
{
From = Canvas.GetTop(_element),
To = point.Y,
Duration = duration,
EasingFunction = easing,
};
Storyboard.SetTargetProperty(animateLeft, "(Canvas.Left)");
Storyboard.SetTarget(animateLeft, _element);
Storyboard.SetTargetProperty(animateTop, "(Canvas.Top)");
Storyboard.SetTarget(animateTop, _element);
sb.Children.Add(animateLeft);
sb.Children.Add(animateTop);
sb.Begin();
}
}
So here's what I did with your code, I took just this part and made it a function:
public void AnimateToPoint(UIElement image, Point point, int durationInMilliseconds = 300)
{
var duration = new Duration(TimeSpan.FromMilliseconds(durationInMilliseconds));
var sb = new Storyboard
{
Duration = duration
};
var animateTop = new DoubleAnimation
{
From = Canvas.GetTop(image),
To = point.Y,
Duration = duration
};
Storyboard.SetTargetProperty(animateTop, new PropertyPath("Canvas.Top")); // You can see that I made some change here because I had an error with what you gave me
Storyboard.SetTarget(animateTop, image);
sb.Children.Add(animateTop);
sb.Begin();
}
And then I made the call with:
Point myPoint = new Point(leftpos, 300); // leftpos is a variable generated randomly
AnimateToPoint(myImage, myPoint);
So now there is still a single error, and it's in the instruction "sb.Begin;".
And it says: Cannot resolve TargetProperty Canvas.Top on specified object.
I reaylly don't know how to proceed.
Thanks for your previous answer!

Attaching an image to an Ellipse programmatically

When I run this code, I get a black screen until i maximise the application? Also, I don't think its picking up the image file neither. Within Visual Studio, I made a new folder and added the image to this folder.
public MainWindow()
{
InitializeComponent();
Canvas canvas = new Canvas();
canvas.Width = 300;
canvas.Height = 300;
canvas1.Children.Add(canvas);
Ellipse hand = new Ellipse();
hand.Height = 30;
hand.Width = 30;
/*
BrushConverter bc = new BrushConverter();
Brush brush = (Brush)bc.ConvertFrom("Red");
hand.Fill = new SolidColorBrush(Colors.Red);
*/
ImageBrush myBrush = new ImageBrush();
myBrush.ImageSource =
new BitmapImage(new Uri(#"Images/Hand.png", UriKind.Relative));
hand.Fill = myBrush;
Canvas.SetLeft(hand, 100);
Canvas.SetTop(hand, 100);
canvas.Children.Add(hand);
}
Is there any particular reason that you are using TextureBrush?
Not really sure but maybe you should be using ImageBrush instead.
ImageBrush myBrush = new ImageBrush();
myBrush.ImageSource =
new BitmapImage(new Uri("pack://application:,,,/Images/image.jpg"));
myEllipse.Fill = myBrush;

Show image above SMFPlayer issue

An image (Image class) is placed above a SMFPlayer (both elements are created in code-behind). Z-index of the image is the Z-Index of SMFPlayer + 1. The image is resized (adjusting the width) according to the playing progress of SMFPlayer.
videoPlayer = new SMFPlayer();
videoPlayer.Width = 1920;
videoPlayer.Height = 1080;
videoPlayer.Margin = new Thickness(1920, 0, 0, 0);
PlaylistItem item = new PlaylistItem();
Random r = new Random();
item.MediaSource = new Uri("video.wmv");
item.DeliveryMethod = DeliveryMethods.ProgressiveDownload;
videoPlayer.Playlist.Add(item);
videoPlayer.AutoPlay = true;
videoPlayer.AutoLoad = true;
videoPlayer.IsControlStripVisible = false;
videoPlayer.PlaylistVisibility = FeatureVisibility.Disabled;
videoPlayer.MediaEnded += new EventHandler(player_MediaEnded);
LayoutRoot.Children.Add(videoPlayer);
bar_yellow3 = new Image();
bar_yellow3.Source = new BitmapImage(new Uri("/SMF_ProgressiveDownload1;component/assets/bar_y.png", UriKind.Relative));
bar_yellow3.Width = 775;
bar_yellow3.Height = 34;
bar_yellow3.Margin = new Thickness(2948,1034,0,0);
bar_yellow3.Stretch = Stretch.Fill;
bar_yellow3.VerticalAlignment = VerticalAlignment.Top;
bar_yellow3.HorizontalAlignment = HorizontalAlignment.Left;
LayoutRoot.Children.Add(bar_yellow3);
However, when the playing progress is less than 20%, the image blinks randomly. When the SMFPlayer is set to be invisible ( Visibility.Collapsed ) , the image is normal.
I have tried to call the update function of the Image, which is: bar_yellow3.UpdateLayout(); but the method does not solve the blinking issue.
Any solution?
Try use effects (Shazzam will help you) instead using Z order.

Categories