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.
Related
I am currently using ZXing.Net to generate a CODE_128 (which in the documentation says is compliant with GS1-128 barcodes). The code I am using is down below:
BarcodeWriterPixelData writer = new BarcodeWriterPixelData()
{
Format = BarcodeFormat.CODE_128,
Options = new ZXing.Common.EncodingOptions
{
Width = 280,
Height = 80
}
};
var pixelData = writer.Write(packageModel.TrackingId.PrintValue);
using (var bitmap = new Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb))
{
using (var ms = new System.IO.MemoryStream())
{
var bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, pixelData.Width, pixelData.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try
{
// we assume that the row stride of the bitmap is aligned to 4 byte multiplied by the width of the image
System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length);
}
finally
{
bitmap.UnlockBits(bitmapData);
}
// PNG or JPEG or whatever you want
bitmap.SetResolution(100F, 100F);
drawing.DrawImage(bitmap, new Rectangle(10, 255, 280, 80));
}
}
This creates the image below
For some reason my barcode is coming out blurry and with grey shadows on it. I am even setting the barcode resolution to be 100DPI x 100DPI to make it printer friendly.
My question:
What can I add to my code to make the barcode look crisp and blur free?
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);
}
When I create one like this:
WriteableBitmap wb = new WriteableBitmap(1200, 1600, 90, 90, PixelFormats.Bgr24, null);
Its filled with black when I want it to be transparent. I tried Clear(from WriteableBitmapEx library) but I get a Attempted to read or write protected memory. This is often an indication that other memory is corrupt."} System.Exception {System.AccessViolationException}
wb.Clear(Colors.Transparent);
Any ideas how I could accomplish this?
Edit:
List<FormattedText> text = new List<FormattedText>();
WriteableBitmap wb = new WriteableBitmap(1200, 1600, 96, 96, PixelFormats.Bgr32, null);
wb.Clear(Colors.Transparent);
TransformedBitmap tb = new TransformedBitmap(wb, new RotateTransform(0));
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawImage(tb, new Rect(0, 0, tb.PixelWidth, tb.PixelHeight));
for (int i = 0; i < text.Count; i++)
{
drawingContext.DrawText(text[i], points[i]);
drawingContext.DrawEllipse(null, new Pen(new SolidColorBrush(Colors.Aqua), 3), points[i], 10, 10);
}
drawingContext.Close();
System.Windows.Media.Imaging.RenderTargetBitmap bmp = new System.Windows.Media.Imaging.RenderTargetBitmap(tb.PixelWidth, tb.PixelHeight, 96, 96, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
Image = bmp;
Create the WriteableBitmap with a PixelFormat that has an alpha channel and thus allows for transparency, e.g. PixelFormats.Bgra32:
var wb = new WriteableBitmap(1200, 1600, 96, 96, PixelFormats.Bgra32, null);
Now you have four bytes per pixel, one for blue, one for green, one for red, and one for the alpha value.
Note also that you would usually use a value of 96 for the DPI parameters.
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);
}
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.