video thumbnail returns black image randomly - c#

I am working in WPF and creating a gallery folder where I want to show the video thumbnails of the videos in a folder present in the system. I wrote the following code in C# to get the video thumbnails.
private BitmapSource RenderThumb(Uri uri)
{
var player = new MediaPlayer { Volume = 0, ScrubbingEnabled = true };
player.Open(uri);
Thread.Sleep(3000);
player.Pause();
player.Position = player.NaturalDuration.HasTimeSpan
? TimeSpan.FromSeconds(player.NaturalDuration.TimeSpan.TotalSeconds / 2)
: TimeSpan.FromSeconds(2);
int width = player.NaturalVideoWidth;
int height = player.NaturalVideoHeight;
if (width == 0 || height == 0)
{
throw new InvalidOperationException("Width or Height cannot be 0");
}
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
var dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
dc.DrawVideo(player, new Rect(0, 0, width, height));
}
player.Close();
rtb.Render(dv);
Freezable frame = BitmapFrame.Create(rtb).GetCurrentValueAsFrozen();
Freezable smallerFrame =
BitmapFrame.Create(new TransformedBitmap(source: frame as BitmapSource, newTransform: new ScaleTransform(0.5, 0.5))).
GetCurrentValueAsFrozen();
return smallerFrame as BitmapSource;
}
however if I try to load thumbnails of 10 videos for example, then I get blank/black thumbnails for 2 3 videos everytime and all the others load fine. This behavior is random and sometimes I get blank thumbnails for last 3 videos and sometimes for the first 3 videos so I am not sure where to look for a solution to my issue. I have tried looking at the properties of BitmapSource but the properties of all 10 videos have the same info in the debugger.

Moving player.Close(); at the bottom of the function after rendering solved the problem for me.

Related

Take a screenshot of a WPF window with the predefined image size without losing quality

When I take a screenshot of a current WPF window, the image resolution is that of my monitor (if the app is maximized), which is ok. However, if I was to print that image to a much bigger format, the image would look blurry. I found the way to capture the current window, and save it as a png file, but it's not doing the trick. The image is saved with the resolution I set, but the actual wpf window takes only a small portion of the saved image. Example is taken from:
http://blogs.msdn.com/b/saveenr/archive/2008/09/18/wpf-xaml-saving-a-window-or-canvas-as-a-png-bitmap.aspx
var screen = System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
var rtb = new RenderTargetBitmap(4000, 4000, 96, 96, PixelFormats.Pbgra32);
rtb.Render(screen);
var enc = new System.Windows.Media.Imaging.PngBitmapEncoder();
enc.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(rtb));
using (var stm = System.IO.File.Create("ScreenShot.png"))
{
enc.Save(stm);
using (Image img = Image.FromStream(stm))
{
Rectangle dest = new Rectangle(0, 0, 6000, 4000);
using (Graphics imgG = Graphics.FromImage(img))
{
imgG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
imgG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
imgG.DrawImage(img, dest);
}
img.Save("NewScreenShot.png");
}
}
So basically, I'd like to capture the screenshot with the resolution of 4000 x 4000, if that's possible, without losing quality.
The above code produces an image of 4000 x 4000, however the screenshot only takes a small portion of it, its original resolution.
To scale your image, you can use a DrawingVisual and a ScaleTransform :
var w = 4000;
var h = 4000;
var screen = System.Windows.Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
var visual = new DrawingVisual();
using (var context = visual.RenderOpen())
{
context.DrawRectangle(new VisualBrush(screen),
null,
new Rect(new Point(), new Size(screen.Width, screen.Height)));
}
visual.Transform = new ScaleTransform(w / screen.ActualWidth, h / screen.ActualHeight);
var rtb = new RenderTargetBitmap(w, h, 96, 96, PixelFormats.Pbgra32);
rtb.Render(visual);
var enc = new PngBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(rtb));
using (var stm = File.Create("ScreenShot.png"))
{
enc.Save(stm);
}

How to Write strings on Bitmap Image wpf [duplicate]

I'm using a Kinect sensor to show a video feed on an image by setting the video feed as bitmap source like shown below. But my question is how would I add text to the image/bitmap for example a score counter, I added a picture below to show what I'm trying to achieve.
void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null) return;
byte[] colorData = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(colorData);
KinectVideo.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96,
PixelFormats.Bgr32, null, colorData, colorFrame.Width * colorFrame.BytesPerPixel);
}
}
You can achieve this using DrawingVisual and DrawingImage classes :
var random = new Random();
var pixels = new byte[256 * 256 * 4];
random.NextBytes(pixels);
BitmapSource bitmapSource = BitmapSource.Create(256, 256, 96, 96, PixelFormats.Pbgra32, null, pixels, 256 * 4);
var visual = new DrawingVisual();
using (DrawingContext drawingContext = visual.RenderOpen())
{
drawingContext.DrawImage(bitmapSource, new Rect(0, 0, 256, 256));
drawingContext.DrawText(
new FormattedText("Hi!", CultureInfo.InvariantCulture, FlowDirection.LeftToRight,
new Typeface("Segoe UI"), 32, Brushes.Black), new Point(0, 0));
}
var image = new DrawingImage(visual.Drawing);
Image1.Source = image;
Unfortunately you will have to create a new BitmapSource as there's currently no way I know of writing text directly to it.
Alternatively you could use WriteableBitmapEx : https://writeablebitmapex.codeplex.com/
create a WriteableBitmap from your frame using BitmapFactory (1)
create another WriteableBitmap and draw text on it using the above method (2)
blit the text bitmap (2) over your frame (1)
Same result but different approach, not sure whether approach 2 is better as it's cumbersome.
You don't need to draw the text into the image itself. In your XAML just add a TextBlock control at a higher Z order.

re-sizing image in c# doesn't work

I am trying to resize image to width=100 height=100
public ActionResult RegisterUser(userAuthModel user, HttpPostedFileBase userimage)
{
if (userimage.ContentLength > 0 && userimage != null)
{
string fname = userimage.FileName;
var path = Server.MapPath("~/Images/User_DP/" + userimage.FileName);
var image_100 = new System.Drawing.Bitmap(userimage, new Size(100, 100));
userimage.SaveAs(path);
}
.
.
.
.
.
}
Here I am using bitmap approach to resize imgae to some specific width and height.
But this shows me error in line-
var image_100 = new System.Drawing.Bitmap(userimage, new Size(100, 100));
of invalid arguments. How Do Ii resize image with using bitmap?
The System.Drawing.Bitmap class asks for two parameters in the constructor your are using:
System.Drawing.Image
System.Drawing.Size
In your code, you are passing the size correctly, but not the image. HttpPostedFileBase does not extend the Image class.
You will need to change that part of your code. If you are using the HttpPostedFileBase as a stream, then keep in mind that System.Drawing.Bitmap has no constructor asking for a Stream and a Size.
References:
System.Drawing.Image
System.Web.HttpPostedFileBase
you have to use mentioned method it may help you
private static BitmapFrame CreateResizedImage(ImageSource source, int width, int height, int margin)
{
var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2);
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
group.Children.Add(new ImageDrawing(source, rect));
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
drawingContext.DrawDrawing(group);
var resizedImage = new RenderTargetBitmap(
width, height, // Resized dimensions
96, 96, // Default DPI values
PixelFormats.Default); // Default pixel format
resizedImage.Render(drawingVisual);
return BitmapFrame.Create(resizedImage);
}

How to add text to a bitmap image programmatically? WPF

I'm using a Kinect sensor to show a video feed on an image by setting the video feed as bitmap source like shown below. But my question is how would I add text to the image/bitmap for example a score counter, I added a picture below to show what I'm trying to achieve.
void myKinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null) return;
byte[] colorData = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(colorData);
KinectVideo.Source = BitmapSource.Create(colorFrame.Width, colorFrame.Height, 96, 96,
PixelFormats.Bgr32, null, colorData, colorFrame.Width * colorFrame.BytesPerPixel);
}
}
You can achieve this using DrawingVisual and DrawingImage classes :
var random = new Random();
var pixels = new byte[256 * 256 * 4];
random.NextBytes(pixels);
BitmapSource bitmapSource = BitmapSource.Create(256, 256, 96, 96, PixelFormats.Pbgra32, null, pixels, 256 * 4);
var visual = new DrawingVisual();
using (DrawingContext drawingContext = visual.RenderOpen())
{
drawingContext.DrawImage(bitmapSource, new Rect(0, 0, 256, 256));
drawingContext.DrawText(
new FormattedText("Hi!", CultureInfo.InvariantCulture, FlowDirection.LeftToRight,
new Typeface("Segoe UI"), 32, Brushes.Black), new Point(0, 0));
}
var image = new DrawingImage(visual.Drawing);
Image1.Source = image;
Unfortunately you will have to create a new BitmapSource as there's currently no way I know of writing text directly to it.
Alternatively you could use WriteableBitmapEx : https://writeablebitmapex.codeplex.com/
create a WriteableBitmap from your frame using BitmapFactory (1)
create another WriteableBitmap and draw text on it using the above method (2)
blit the text bitmap (2) over your frame (1)
Same result but different approach, not sure whether approach 2 is better as it's cumbersome.
You don't need to draw the text into the image itself. In your XAML just add a TextBlock control at a higher Z order.

How do I print an Image from a Uri?

I am attempting to print a JPEG file that I reference using a Uri object and am having some difficulties. I found that while the image was printing, it was cropped slightly and was flipped and mirrored. I'm guessing that the crop was caused by a size not being set properly but have no idea why it's being flipped and rotated. Assuming that this was a natural oddity, I attempted to resolve the issue by applying a transform to the drawingContext object but this results a blank page being printed. Here is my code:
public void Print(List<Uri> ListToBePrinted)
{
XpsDocumentWriter writer =
PrintQueue.CreateXpsDocumentWriter(this.SelectedPrinter.PrintQueue);
PrintCapabilities printerCapabilities =
this.SelectedPrinter.PrintQueue.GetPrintCapabilities();
Size PageSize =
new Size(printerCapabilities.PageImageableArea.ExtentWidth,
printerCapabilities.PageImageableArea.ExtentHeight);
foreach (Uri aUri in ListToBePrinted)
{
BitmapImage anImage = new BitmapImage(aUri);
//create new visual which would be initialized by image
DrawingVisual drawingVisual = new DrawingVisual();
//create a drawing context so that image can be rendered to print
DrawingContext drawingContext = drawingVisual.RenderOpen();
// Flips along X and Y axis (flips and mirrors)
drawingContext.PushTransform(new ScaleTransform(-1, -1));
drawingContext.DrawImage(anImage, new Rect(PageSize));
drawingContext.Close();
writer.Write(drawingVisual);
}
}
Any help would be greatly appreciated - thank you!
Here's what I ended up with:
public void Print(List<Uri> ListToBePrinted)
{
XpsDocumentWriter writer =
PrintQueue.CreateXpsDocumentWriter(this.SelectedPrinter.PrintQueue);
PrintCapabilities printerCapabilities =
this.SelectedPrinter.PrintQueue.GetPrintCapabilities();
Size PrintableImageSize =
new Size(printerCapabilities.PageImageableArea.ExtentWidth,
printerCapabilities.PageImageableArea.ExtentHeight);
foreach (Uri aUri in ListToBePrinted)
{
DrawingVisual drawVisual = new DrawingVisual();
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = new BitmapImage(aUri);
imageBrush.Stretch = Stretch.Fill;
imageBrush.TileMode = TileMode.None;
imageBrush.AlignmentX = AlignmentX.Center;
imageBrush.AlignmentY = AlignmentY.Center;
using (DrawingContext drawingContext = drawVisual.RenderOpen())
{
// Flips along X and Y axis (flips and mirrors)
drawingContext.PushTransform(new ScaleTransform(-1, 1, PrintableImageSize.Width / 2, PrintableImageSize.Height / 2));
drawingContext.PushTransform(new RotateTransform(180, PrintableImageSize.Width / 2, PrintableImageSize.Height / 2)); // Rotates 180 degree
drawingContext.DrawRectangle(imageBrush, null, new Rect(25, -25, PrintableImageSize.Width, PrintableImageSize.Height));
}
writer.Write(drawVisual);
}
}
The image is a little fuzzy but is certainly acceptable. I'm still not sure why my image needed to be flipped or mirrored.
Could you do something like:
BitmapImage anImage = new BitmapImage(aUri);
Image image = new Image();
image.BeginInit();
image.Source = anImage;
image.EndInit();
image.Measure(PageSize);
image.InvalidateVisual();
Then just print the Image object since it derives from Visual...
You need to call InvalidateVisual so that OnRender will be called, if you didn't it would result in a blank image...

Categories

Resources