I need to apply a custom shape (this, a .jpg) to any image I load into my application, using Windows Forms if possible (since my whole project is made in Winforms), but I guess I can use WPF if it's needed.
So for example if I have a photo like this, the result should be like this (I made this with Photoshop for you to see), maybe even without the white borders if possible (please note that the image was resized and centered to fit the custom shape, and that's how it should be).
I can't figure out how to do this, but from what I've searched I suppose it has something to do with brushes (TextureBrush, ImageBrush, etc).
Regards.
it seems to me that you want to apply a mask, you could do it with something like this (using /unsafe code):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace testImageBlender
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Bitmap imBase;
Bitmap imMask,imMask2;
Bitmap blendedImage;
private void Form1_Load(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
imBase = new Bitmap(openFileDialog1.FileName);
imMask = new Bitmap(openFileDialog2.FileName);
blendedImage = new Bitmap(openFileDialog2.FileName);
blendImage();
}
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (imBase != null)
{
if (imMask != null)
{
if (blendedImage != null)
{
e.Graphics.DrawImage(blendedImage, e.ClipRectangle);
}
}
}
}
private void blendImage()
{
Rectangle mRec = new Rectangle(0, 0, imMask.Width, imMask.Height);
float intensity = 0;
//playing around with images to get pixel format 24bpp RGB, most probably a very bad way of doing it, but I don't know enough about image format and lockbits to do it nice and clean yet
imMask2 = new Bitmap(imMask);
Graphics.FromImage(imBase).DrawImage(imBase, 0, 0, imMask.Width, imMask.Height);
Graphics.FromImage(blendedImage).DrawImage(imMask, 0, 0, imMask.Width, imMask.Height);
Graphics.FromImage(imMask2).DrawImage(imMask, 0, 0, imMask.Width, imMask.Height);
BitmapData imageData = imBase.LockBits(mRec, ImageLockMode.ReadOnly, imBase.PixelFormat);
BitmapData maskData = imMask2.LockBits(mRec, ImageLockMode.ReadOnly, imMask.PixelFormat);
BitmapData blendedData = blendedImage.LockBits(mRec, ImageLockMode.WriteOnly, blendedImage.PixelFormat);
unsafe
{
byte* imagePointer = (byte*)imageData.Scan0;
byte* maskPointer = (byte*)maskData.Scan0;
byte* blendedPointer = (byte*)blendedData.Scan0;
for (int i = 0; i < mRec.Height; i++)
{
for (int j = 0; j < mRec.Width; j++)
{
intensity = 1-((float)(maskPointer[0] + maskPointer[1] + maskPointer[2])) / ((float)3 * 255);
for (int k = 0; k < 3; k++)
{
blendedPointer[k] = (intensity>0.8)?(byte)((float)imagePointer[k]):(byte)255;
}
// 3 bytes per pixel
imagePointer += 3;
maskPointer += 3;
blendedPointer += 3;
}
// Moving the pointers to the next pixel row
imagePointer += imageData.Stride - (mRec.Width * 3);
maskPointer += maskData.Stride - (mRec.Width * 3);
blendedPointer += blendedData.Stride - (mRec.Width * 3);
}
}
imBase.UnlockBits(imageData);
imMask2.UnlockBits(maskData);
blendedImage.UnlockBits(blendedData);
}
}
}
this is very much inspired by Balazs Tihanyi answers on Draw image on top of another image with blending mode color
Here is an example tuned for the image you linked to:
using (var source = (Bitmap) Image.FromFile(#"image filename"))
{
using (var target = new Bitmap(source.Width, source.Height))
{
using (var graphics = Graphics.FromImage(target))
{
using (var path = new GraphicsPath())
{
path.StartFigure();
path.AddLine(161, 665, 223, 624);
path.AddLine(223, 624, 252, 568);
path.AddLine(252, 568, 239, 525);
path.AddLine(239, 525, 200, 432);
path.AddLine(200, 432, 178, 343);
path.AddLine(178, 343, 156, 198);
path.AddLine(156, 198, 161, 131);
path.AddLine(161, 131, 248, 38);
path.AddLine(248, 38, 366, 4);
path.AddLine(366, 4, 657, 10);
path.AddLine(657, 10, 735, 70);
path.AddLine(735, 70, 741, 195);
path.AddLine(741, 195, 746, 282);
path.AddLine(746, 282, 762, 410);
path.AddLine(762, 410, 730, 498);
path.AddLine(730, 498, 686, 582);
path.AddLine(686, 582, 727, 669);
path.CloseFigure();
graphics.Clip = new Region(path);
}
graphics.DrawImage(source, 0, 0);
}
this.PictureBox.Image = new Bitmap(target);
}
}
Related
I have written a function which changes the alpha coefficient of an image. I use setpixel and getpixel,which is very slow. I found out that Lockbits method is faster.How can I do it with Lockbits?
Here is my current code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
private static Image Tran(Image s,int alpha)
{
int x = 0, y = 0;
Bitmap tImage = new Bitmap(s);
for (x = 0; x < tImage.Width; x++)
{
for (y = 0; y < tImage.Height; y++)
{
tImage.SetPixel(x, y, Color.FromArgb(alpha, tImage.GetPixel(x, y).R, tImage.GetPixel(x, y).G, tImage.GetPixel(x, y).B));
}
}
return tImage;
}
public Form1()
{
InitializeComponent();
trackBar1.TickStyle = TickStyle.Both;
trackBar1.Orientation = Orientation.Vertical;
trackBar1.Minimum = 0;
trackBar1.Maximum = 255;
trackBar1.Height = 101;
trackBar1.Value = 255;
pictureBox1.Image = Image.FromFile("C:\\Users\\rati\\Desktop\\water.jpg");
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
pictureBox1.Image = ChangeAlpha(pictureBox1.Image, trackBar1.Value);
textBox1.Text = trackBar1.Value.ToString();
}
}
}
You can change the opacity of your image by drawing it in a new bitmap using a new ColorMatrix and assigning a float value between 0 and 1 to its Matrix33 as its new alpha value:
public Image ChangeAlpha(Image img, int value)
{
if (value < 0 || value > 255)
throw new Exception("value must be between 0 and 255");
Bitmap bmp = new Bitmap(img.Width, img.Height); // Determining Width and Height of Source Image
Graphics graphics = Graphics.FromImage(bmp);
ColorMatrix colormatrix = new ColorMatrix();
colormatrix.Matrix33 = value / 255f;
ImageAttributes imgAttribute = new ImageAttributes();
imgAttribute.SetColorMatrix(colormatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
graphics.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttribute);
graphics.Dispose(); // Releasing all resource used by graphics
return bmp;
}
And here is a sample usage:
private void button1_Click(object sender, EventArgs e)
{
int opacityvalue = 127;
var img = ChangeAlpha(Image.FromFile(#"d:\1.png"), opacityvalue);
img.Save(#"d:\2.png");
}
Don't forget to add using System.Drawing; and using System.Drawing.Imaging;.
You can see before and after calling the function with value=127 below:
EDIT
If you want to see the result in a PictureBox you should pay attention to using 2 different picture boxes, one for original image, and one for changed image:
private void trackBar1_Scroll(object sender, EventArgs e)
{
this.pictureBox2.Image = ChangeAlpha(this.pictureBox1.Image, this.trackBar1.Value);
}
As I see in your code when you change the opacity, you set the result as image of your PictureBox1 again and apply opacity again on the result. In other word you apply opacity on an image that you applied opacity to it before over and over again.
public Form1()
{
...
originalImage = new Bitmap("C:\\Users\\rati\\Desktop\\water.jpg");
pictureBox1.Image = originalImage;
...
}
// Add an extra field to the Form class.
Bitmap originalImage;
void trackBar1_Scroll(object sender, EventArgs e)
{
pictureBox1.Image = ChangeAlpha((byte)trackBar1.Value);
textBox1.Text = trackBar1.Value.ToString();
}
Image ChangeAlpha(byte alpha)
{
Bitmap bmp = new Bitmap(originalImage);
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(ptr, rgbValues, 0, bytes);
// Set every fourth value to alpha. A 32bpp bitmap will change transparency.
for (int counter = 3; counter < rgbValues.Length; counter += 4)
rgbValues[counter] = alpha;
// Also you can try parallelize loop.
//int length = rgbValues.Length / 4;
//Parallel.For(3, length, counter => rgbValues[counter * 4 - 1] = alpha);
Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);
return bmp;
}
This seems like it should be simple, but I can't seem to find any way to do it. I have a custom WinForms control that has an overridden paint method that does some custom drawing.
I have a Bitmap in memory, and all I want to do is paint over the whole thing with a HashBrush, but preserve the alpha channel, so that the transparent parts of the bitmap don't get painted.
The bitmap in memory is not a simple shape, so it will not be feasible to define it as a set of paths or anything.
EDIT: In response to showing the code, there is a lot of code in the paint routine, so I'm only including a relevant snippet, which is the method in question. This method gets called from the main paint override. It accepts a list of images which are black transparency masks and combines them into one, then it uses a ColorMatrix to change the color of the combined image it created, allowing it to be overlayed on top of the background. All I want to accomplish is being able to also paint hashmarks on top of it.
private void PaintSurface(PaintEventArgs e, Image imgParent, List<Image> surfImgs, Rectangle destRect, ToothSurfaceMaterial material)
{
using (Bitmap bmp = new Bitmap(imgParent.Width, imgParent.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
{
using (Graphics g = Graphics.FromImage(bmp))
{
foreach (Image img in surfImgs)
{
g.DrawImage(img, System.Drawing.Point.Empty);
}
}
ColorMatrix matrix = new ColorMatrix(
new float[][] {
new float[] { 0, 0, 0, 0, 0},
new float[] { 0, 0, 0, 0, 0},
new float[] { 0, 0, 0, 0, 0},
new float[] { 0, 0, 0, 0.7f, 0},
new float[] { material.R / 255.0f,
material.G / 255.0f,
material.B / 255.0f,
0, 1}
});
ImageAttributes imageAttr = new ImageAttributes();
imageAttr.SetColorMatrix(matrix);
Rectangle r = GetSizedRect(imgParent, destRect);
e.Graphics.DrawImage(bmp,
r,
0,
0,
bmp.Width,
bmp.Height,
GraphicsUnit.Pixel, imageAttr);
}
}
The solution I ended up using was the following method. First I combine the individual masks into one, then create a new Bitmap and paint the whole thing with the HatchBrush, finally iterate through the mask and set the alpha values on the newly generated bitmap based on the mask.
private Bitmap GenerateSurface(Image imgParent, List<Image> surfImgs, ToothSurfaceMaterial material)
{
Bitmap mask = new Bitmap(imgParent.Width, imgParent.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
using (Graphics g = Graphics.FromImage(mask))
{
foreach (Image img in surfImgs)
{
g.DrawImage(img, System.Drawing.Point.Empty);
}
}
Bitmap output = new Bitmap(mask.Width, mask.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
using (Graphics g = Graphics.FromImage(output))
{
if (material.HatchStyle != null)
{
HatchBrush hb = new HatchBrush((HatchStyle)material.HatchStyle, material.FgColor, material.BgColor);
g.FillRectangle(hb, new Rectangle(0, 0, output.Width, output.Height));
}
else
{
SolidBrush sb = new SolidBrush(material.FgColor);
g.FillRectangle(sb, new Rectangle(0, 0, output.Width, output.Height));
}
}
var rect = new Rectangle(0, 0, output.Width, output.Height);
var bitsMask = mask.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var bitsOutput = output.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
int offset = 0;
for (int y = 0; y < mask.Height; y++)
{
byte* ptrMask = (byte*)bitsMask.Scan0 + y * bitsMask.Stride;
byte* ptrOutput = (byte*)bitsOutput.Scan0 + y * bitsOutput.Stride;
for (int x = 0; x < mask.Width; x++)
{
offset = 4 * x + 3;
ptrOutput[offset] = (byte)(ptrMask[offset] * 0.7);
}
}
}
mask.UnlockBits(bitsMask);
output.UnlockBits(bitsOutput);
return output;
}
I think you don't need any ColorMatrix which is overkill, you just need a ColorMap, here is the code which may not suit your requirement but should give you the idea. That's because I possibly don't understand your problem well, if you have any problem, just leave some comment and I'll try to improve the answer:
ImageAttributes imgA = new ImageAttributes();
ColorMap cm = new ColorMap();
cm.OldColor = Color.Black
cm.NewColor = Color.FromArgb((byte)(0.7*255), Color.Green);
imgA.SetRemapTable(new ColorMap[] {cm });
GraphicsUnit gu = GraphicsUnit.Pixel;
g.DrawImage(imageToDraw,new Point[]{Point.Empty,
new Point(backImage.Width/2,0),
new Point(0,backImage.Height/2)},
Rectangle.Round(imageToDraw.GetBounds(ref gu)),
GraphicsUnit.Pixel, imgA);
the new Point[] is an array of 3 Points used to locate the destination Rectangle.
The code above is used to Draw the imageToDraw on top of the backImage and convert and color of Black to the color Green with Opacity = 70%. That's what you want to fulfill your code.
UPDATE
This may be what you want, in fact your code doesn't show what you want, it just shows what you have which doesn't implement anything related to your problem now. I deduce this from your very first description in your question. The input is an image with background color (which will be made partially transparent later) being Black. Now the output you want is an image with all the non-Black region being painted with a HatchBrush. This output will then be processed to turn the Black background to a partially transparent background.
public void PaintHatchBrush(Bitmap input, HatchBrush brush){
using(Graphics g = Graphics.FromImage(input)){
g.Clip = GetForegroundRegion(input, Color.Black);
GraphicsUnit gu = GraphicsUnit.Pixel;
g.FillRectangle(brush, input.GetBounds(ref gu));
}
}
//This is implemented using `GetPixel` which is not fast, but it gives you the idea.
public Region GetForegroundRegion(Bitmap input, Color backColor){
GraphicsPath gp = new GraphicsPath();
Rectangle rect = Rectangle.Empty;
bool jumpedIn = false;
for (int i = 0; i < bm.Height; i++) {
for (int j = 0; j < bm.Width; j++) {
Color c = bm.GetPixel(j, i);
if (c != backColor&&!jumpedIn) {
rect = new Rectangle(j, i, 1, 1);
jumpedIn = true;
}
if (jumpedIn && (c == backColor || j == bm.Width - 1)) {
rect.Width = j - rect.Left;
gp.AddRectangle(rect);
jumpedIn = false;
}
}
}
return new Region(gp);
}
//Usage
HatchBrush brush = new HatchBrush(HatchStyle.Percent30, Color.Green, Color.Yellow);
PaintHatchBrush(yourImage, brush);
//then yourImage will have HatchBrush painted on the surface leaving the Black background intact.
//This image will be used in the next process to turn the Black background into 70%
//opacity background as you did using ColorMatrix (or more simply using ColorMap as I posted previously)
How can I create in .NET 4.5 / C# a font with a adaptive size to fit a specified rectangle ?
I have a resize based on the string length, the longer the string, the smaller the fontsize, but it does not work very well, if the string is too long the text gets very small. The problem with this method is that if I change the rectangle size all the font sizes are not good again.
It's been a while but I came across this issue.
MSDN offers a sample with a GetAdjustedFont method to help with this process:
(shamelessly stolen from https://msdn.microsoft.com/en-us/library/bb986765.aspx)
public Font GetAdjustedFont(Graphics g, string graphicString, Font originalFont, int containerWidth, int maxFontSize, int minFontSize, bool smallestOnFail)
{
Font testFont = null;
// We utilize MeasureString which we get via a control instance
for (int adjustedSize = maxFontSize; adjustedSize >= minFontSize; adjustedSize--)
{
testFont = new Font(originalFont.Name, adjustedSize, originalFont.Style);
// Test the string with the new size
SizeF adjustedSizeNew = g.MeasureString(graphicString, testFont);
if (containerWidth > Convert.ToInt32(adjustedSizeNew.Width))
{
// Good font, return it
return testFont;
}
}
// If you get here there was no fontsize that worked
// return minimumSize or original?
if (smallestOnFail)
{
return testFont;
}
else
{
return originalFont;
}
}
With Graphics.MeasureString you can measure the size of a string, so you can calculate what you need.
Sample from MSDN
private void MeasureStringMin(PaintEventArgs e)
{
// Set up string.
string measureString = "Measure String";
Font stringFont = new Font("Arial", 16);
// Measure string.
SizeF stringSize = new SizeF();
stringSize = e.Graphics.MeasureString(measureString, stringFont);
// Draw rectangle representing size of string.
e.Graphics.DrawRectangle(new Pen(Color.Red, 1), 0.0F, 0.0F, stringSize.Width, stringSize.Height);
// Draw string to screen.
e.Graphics.DrawString(measureString, stringFont, Brushes.Black, new PointF(0, 0));
}
You can measure the string width with whatever font size (e.g. 16), and then you can calculate your desired font size like this:
fontSize = (previouslyMeasuredFontSize * targetWidthOfString) / previouslyMeasuredStringWidth;
I also needed something similar. I created some code to answer the need of drawing text inside a defined rectangle with several auto font size options (see DrawMethod enum). It also supports auto warp with and without auto font size. My solution was inspired by the answers above.
Be sure to add WindowsBase and PresentationCore assemblies.
DrawTextToBitmap.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ReportPrepare
{
class TextDrawing
{
public enum DrawMethod
{
AutosizeAccordingToText, // create the smallest bitmap needed to draw the text without word warp
AutoFitInConstantRectangleWithoutWarp, // draw text with the biggest font possible while not exceeding rectangle dimensions, without word warp
AutoWarpInConstantRectangle, // draw text in rectangle while performing word warp. font size is a constant input. drawing may exceed bitmap rectangle.
AutoFitInConstantRectangleWithWarp // draw text with the biggest font possible while not exceeding rectangle dimensions, with word warp
}
private static void SetGraphicsHighQualityForTextRendering(Graphics g)
{
// The smoothing mode specifies whether lines, curves, and the edges of filled areas use smoothing (also called antialiasing). One exception is that path gradient brushes do not obey the smoothing mode. Areas filled using a PathGradientBrush are rendered the same way (aliased) regardless of the SmoothingMode property.
g.SmoothingMode = SmoothingMode.AntiAlias;
// The interpolation mode determines how intermediate values between two endpoints are calculated.
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Use this property to specify either higher quality, slower rendering, or lower quality, faster rendering of the contents of this Graphics object.
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
// This one is important
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
}
public static Size MeasureDrawTextBitmapSize(string text, Font font)
{
Bitmap bmp = new Bitmap(1, 1);
using (Graphics g = Graphics.FromImage(bmp))
{
SizeF size = g.MeasureString(text, font);
return new Size((int)(Math.Ceiling(size.Width)), (int)(Math.Ceiling(size.Height)));
}
}
public static int GetMaximumFontSizeFitInRectangle(string text, Font font, RectangleF rectanglef, bool isWarp, int MinumumFontSize=6, int MaximumFontSize=1000)
{
Font newFont;
Rectangle rect = Rectangle.Ceiling(rectanglef);
for (int newFontSize = MinumumFontSize; ; newFontSize++)
{
newFont = new Font(font.FontFamily, newFontSize, font.Style);
List<string> ls = WarpText(text, newFont, rect.Width);
StringBuilder sb = new StringBuilder();
if (isWarp)
{
for (int i = 0; i < ls.Count; ++i)
{
sb.Append(ls[i] + Environment.NewLine);
}
}
else
{
sb.Append(text);
}
Size size = MeasureDrawTextBitmapSize(sb.ToString(), newFont);
if (size.Width > rectanglef.Width || size.Height > rectanglef.Height)
{
return (newFontSize - 1);
}
if (newFontSize >= MaximumFontSize)
{
return (newFontSize - 1);
}
}
}
public static List<string> WarpText(string text, Font font, int lineWidthInPixels)
{
string[] originalLines = text.Split(new string[] { " " }, StringSplitOptions.None);
List<string> wrappedLines = new List<string>();
StringBuilder actualLine = new StringBuilder();
double actualWidthInPixels = 0;
foreach (string str in originalLines)
{
Size size = MeasureDrawTextBitmapSize(str, font);
actualLine.Append(str + " ");
actualWidthInPixels += size.Width;
if (actualWidthInPixels > lineWidthInPixels)
{
actualLine = actualLine.Remove(actualLine.ToString().Length - str.Length - 1, str.Length);
wrappedLines.Add(actualLine.ToString());
actualLine.Clear();
actualLine.Append(str + " ");
actualWidthInPixels = size.Width;
}
}
if (actualLine.Length > 0)
{
wrappedLines.Add(actualLine.ToString());
}
return wrappedLines;
}
public static Bitmap DrawTextToBitmap(string text, Font font, Color color, DrawMethod mode, RectangleF rectanglef)
{
StringFormat drawFormat = new StringFormat();
Bitmap bmp;
switch (mode)
{
case DrawMethod.AutosizeAccordingToText:
{
Size size = MeasureDrawTextBitmapSize(text, font);
if (size.Width == 0 || size.Height == 0)
{
bmp = new Bitmap(1, 1);
}
else
{
bmp = new Bitmap(size.Width, size.Height);
}
using (Graphics g = Graphics.FromImage(bmp))
{
SetGraphicsHighQualityForTextRendering(g);
g.DrawString(text, font, new SolidBrush(color), 0, 0);
return bmp;
}
}
case DrawMethod.AutoWarpInConstantRectangle:
{
Rectangle rect = Rectangle.Ceiling(rectanglef);
bmp = new Bitmap(rect.Width,rect.Height);
if (rect.Width == 0 || rect.Height == 0)
{
bmp = new Bitmap(1, 1);
}
else
{
bmp = new Bitmap(rect.Width, rect.Height);
}
using (Graphics g = Graphics.FromImage(bmp))
{
SetGraphicsHighQualityForTextRendering(g);
g.DrawString(text, font, new SolidBrush(color), rectanglef, drawFormat);
return bmp;
}
}
case DrawMethod.AutoFitInConstantRectangleWithoutWarp:
{
Rectangle rect = Rectangle.Ceiling(rectanglef);
bmp = new Bitmap(rect.Width, rect.Height);
if (rect.Width == 0 || rect.Height == 0)
{
bmp = new Bitmap(1, 1);
}
else
{
bmp = new Bitmap(rect.Width, rect.Height);
}
using (Graphics g = Graphics.FromImage(bmp))
{
int fontSize = GetMaximumFontSizeFitInRectangle(text, font, rectanglef, false);
SetGraphicsHighQualityForTextRendering(g);
g.DrawString(text, new Font(font.FontFamily, fontSize,font.Style, GraphicsUnit.Point), new SolidBrush(color), rectanglef, drawFormat);
return bmp;
}
}
case DrawMethod.AutoFitInConstantRectangleWithWarp:
{
Rectangle rect = Rectangle.Ceiling(rectanglef);
if (rect.Width == 0 || rect.Height == 0)
{
bmp = new Bitmap(1, 1);
}
else
{
bmp = new Bitmap(rect.Width, rect.Height);
}
using (Graphics g = Graphics.FromImage(bmp))
{
int fontSize = GetMaximumFontSizeFitInRectangle(text, font, rectanglef, true);
SetGraphicsHighQualityForTextRendering(g);
g.DrawString(text, new Font(font.FontFamily, fontSize, font.Style, GraphicsUnit.Point), new SolidBrush(color), rectanglef, drawFormat);
return bmp;
}
}
}
return null;
}
}
}
Usage Example:
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// add WindowsBase and PresentationCore assemblies
namespace ReportPrepare
{
public partial class Form1 : Form
{
PictureBox picbox = new PictureBox();
int i = 0;
Timer t = new Timer();
public Form1()
{
InitializeComponent();
this.Controls.Add(picbox);
picbox.Dock = DockStyle.Fill;
t.Interval = 5000;
t.Tick += t_Tick;
t.Enabled = true;
this.Shown += Form1_Shown;
this.SizeChanged += Form1_SizeChanged;
this.Size = new Size(812, 400);
this.StartPosition = FormStartPosition.CenterScreen;
}
void Form1_Shown(object sender, EventArgs e)
{
DrawText();
}
void t_Tick(object sender, EventArgs e)
{
i++;
if (i > 3)
{
i = 0;
}
DrawText();
}
private void DrawText()
{
// text and font
string text = "one two three four five six seven eight nine ten eleven twelve";
Font font = new System.Drawing.Font("Arial", 30, FontStyle.Regular, GraphicsUnit.Point);
switch (i)
{
case 0:
picbox.Image = TextDrawing.DrawTextToBitmap(text, font, Color.Red, TextDrawing.DrawMethod.AutosizeAccordingToText, new RectangleF(0, 0, picbox.Width, picbox.Height));
break;
case 1:
picbox.Image = TextDrawing.DrawTextToBitmap(text, font, Color.Red, TextDrawing.DrawMethod.AutoFitInConstantRectangleWithoutWarp, new RectangleF(0, 0, picbox.Width, picbox.Height));
break;
case 2:
picbox.Image = TextDrawing.DrawTextToBitmap(text, font, Color.Red, TextDrawing.DrawMethod.AutoWarpInConstantRectangle, new RectangleF(0, 0, picbox.Width, picbox.Height));
break;
case 3:
picbox.Image = TextDrawing.DrawTextToBitmap(text, font, Color.Red, TextDrawing.DrawMethod.AutoFitInConstantRectangleWithWarp, new RectangleF(0, 0, picbox.Width, picbox.Height));
break;
}
this.Text = ((TextDrawing.DrawMethod)(i)).ToString() + " Please resize window size by mouse to see drawing methods differences";
}
private void Form1_SizeChanged(object sender, EventArgs e)
{
t.Enabled = false;
t.Enabled = true;
DrawText();
}
}
}
The example toggles between drawing modes automatically once every 5 seconds. The picturebox is docked inside main form. Resizing of the form shows the user the difference between the drawing modes.
Let me start off by saying that I have indeed followed many tutorials such as the one located on EmguCv's main site in their entirety but get a TypeInitializationException thrown.
Now, listen closely because here comes the extremely weird part. I'll start by saying that there are three "levels" of my problem, however, the code in all "levels" is EXACTLY the same without even the slightest of change. This would naturally point to that I have a reference or linkage problem, but again I've attempted multiple attempts following different tutorials but to no avail.
Level 1 (this level produces a TypeInitializationException)
I create a new project, properly reference everything and such, then write my code in this new project. Upon debug, I get that exception thrown and my program exits. Here's a link to a picture of the problem: http://prntscr.com/uychc
Level 2 (this level runs completely fine and no exception is thrown)
In this level, I pretty much located one of EmguCv's example projects (VideoSurveilance in this case) then delete the default code and copy and paste all of my code in there. After adding a few more references that I needed, the program works fine. I cant post more than 3 links, but you'll have to trust me that the video picture displays correctly.
Level 3 (this level does not throw an exception but warns me of a "first chance" of one)
In this level, I copy and paste my whole Level 2 project into a different directory. After finding and relinking missing files/references, I am able to run the program but the pictures do not show and I get a "A first chance exception of type "System.TypeInitializationException" occurred in Emgu.CV.dll warning. http://prntscr.com/uycmn
I currently run Windows 7 x64 (yes I changed build options to x64 and x64 .dlls) and am running EmguCv 2.4.9 and 2.4.2 (tested on both) and Visual Studios 2010 and 2012 (tested on both).
Here's the code for what it may be worth:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using System.IO;
namespace VideoSurveilance
{
public partial class VideoSurveilance : Form
{
KinectSensor sensor;
WriteableBitmap depthBitmap;
WriteableBitmap colorBitmap;
DepthImagePixel[] depthPixels;
byte[] colorPixels;
int blobCount = 0;
public VideoSurveilance()
{
InitializeComponent();
}
private void VideoSurveilance_Load(object sender, System.EventArgs e)
{
foreach (var potentialSensor in KinectSensor.KinectSensors)
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
}
if (null != this.sensor)
{
this.sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength];
this.depthPixels = new DepthImagePixel[this.sensor.DepthStream.FramePixelDataLength];
this.colorBitmap = new WriteableBitmap(this.sensor.ColorStream.FrameWidth, this.sensor.ColorStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
this.depthBitmap = new WriteableBitmap(this.sensor.DepthStream.FrameWidth, this.sensor.DepthStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
WriteableBitmap bitmap;
bitmap = new WriteableBitmap(this.sensor.DepthStream.FrameWidth, this.sensor.DepthStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
byte[] retVal = new byte[bitmap.PixelWidth * bitmap.PixelHeight * 4];
bitmap.CopyPixels(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight), retVal, bitmap.PixelWidth * 4, 0);
Bitmap b = new Bitmap(bitmap.PixelWidth, bitmap.PixelHeight);
int k = 0;
byte red, green, blue, alpha;
for (int i = 0; i < bitmap.PixelWidth; i++)
{
for (int j = 0; j < bitmap.PixelHeight && k < retVal.Length; j++)
{
alpha = retVal[k++];
blue = retVal[k++];
green = retVal[k++];
red = retVal[k++];
System.Drawing.Color c = new System.Drawing.Color();
c = System.Drawing.Color.FromArgb(alpha, red, green, blue);
b.SetPixel(i, j, c);
}
}
Image<Bgr, Byte> temp = new Image<Bgr, byte>(b);
this.ibOriginal.Image = temp;
this.sensor.AllFramesReady += this.sensor_AllFramesReady;
try
{
this.sensor.Start();
}
catch (IOException)
{
this.sensor = null;
}
}
}
private void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
blobCount = 0;
BitmapSource depthBmp = null;
Image<Bgr, Byte> openCVImg;
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame != null)
{
blobCount = 0;
if (colorFrame != null)
{
byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels);
int stride = colorFrame.Width * 4;
BitmapSource color = BitmapImage.Create(colorFrame.Width, colorFrame.Height, 96, 96, PixelFormats.Bgr32, null, pixels, stride);
openCVImg = new Image<Bgr, byte>(color.ToBitmap());
}
else
{
return;
}
Image<Gray, byte> gray_image;
using (MemStorage stor = new MemStorage())
{
gray_image = openCVImg.InRange(new Bgr(0, 0, 150), new Bgr(200, 200, 255));
gray_image = gray_image.SmoothGaussian(9);
CircleF[] circles = gray_image.HoughCircles(new Gray(100),
new Gray(50),
2,
gray_image.Height / 4,
10,
400)[0];
foreach (CircleF circle in circles)
{
CvInvoke.cvCircle(openCVImg,
new System.Drawing.Point(Convert.ToInt32(circle.Center.X), Convert.ToInt32(circle.Center.Y)),
3,
new MCvScalar(0, 255, 0),
-1,
LINE_TYPE.CV_AA,
0);
openCVImg.Draw(circle,
new Bgr(System.Drawing.Color.Red),
3);
}
}
ibOriginal.Image = openCVImg;
ibProcessed.Image = gray_image;
}
}
}
}
}
}
using System;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Kinect;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Emgu.CV;
namespace VideoSurveilance
{
public static class Helper
{
private const int MaxDepthDistance = 4000;
private const int MinDepthDistance = 850;
private const int MaxDepthDistanceOffset = 3150;
public static BitmapSource SliceDepthImage(this DepthImageFrame image, int min = 20, int max = 1000)
{
int width = image.Width;
int height = image.Height;
//var depthFrame = image.Image.Bits;
short[] rawDepthData = new short[image.PixelDataLength];
image.CopyPixelDataTo(rawDepthData);
var pixels = new byte[height * width * 4];
const int BlueIndex = 0;
const int GreenIndex = 1;
const int RedIndex = 2;
for (int depthIndex = 0, colorIndex = 0;
depthIndex < rawDepthData.Length && colorIndex < pixels.Length;
depthIndex++, colorIndex += 4)
{
// Calculate the distance represented by the two depth bytes
int depth = rawDepthData[depthIndex] >> DepthImageFrame.PlayerIndexBitmaskWidth;
// Map the distance to an intesity that can be represented in RGB
var intensity = CalculateIntensityFromDistance(depth);
if (depth > min && depth < max)
{
// Apply the intensity to the color channels
pixels[colorIndex + BlueIndex] = intensity; //blue
pixels[colorIndex + GreenIndex] = intensity; //green
pixels[colorIndex + RedIndex] = intensity; //red
}
}
return BitmapSource.Create(width, height, 96, 96, PixelFormats.Bgr32, null, pixels, width * 4);
}
public static byte CalculateIntensityFromDistance(int distance)
{
// This will map a distance value to a 0 - 255 range
// for the purposes of applying the resulting value
// to RGB pixels.
int newMax = distance - MinDepthDistance;
if (newMax > 0)
return (byte)(255 - (255 * newMax
/ (MaxDepthDistanceOffset)));
else
return (byte)255;
}
public static System.Drawing.Bitmap ToBitmap(this BitmapSource bitmapsource)
{
System.Drawing.Bitmap bitmap;
using (var outStream = new MemoryStream())
{
// from System.Media.BitmapImage to System.Drawing.Bitmap
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(outStream);
bitmap = new System.Drawing.Bitmap(outStream);
return bitmap;
}
}
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
/// <summary>
/// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source
/// </summary>
/// <param name="image">The Emgu CV Image</param>
/// <returns>The equivalent BitmapSource</returns>
public static BitmapSource ToBitmapSource(IImage image)
{
using (System.Drawing.Bitmap source = image.Bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
}
}
I sincerely thank anyone who even attempts to help me and hope that anyone with similar problems can benefit from this long question.
Found 'brute force' solution:
you have to put the "cvextern.dll" file into your build directory (x64, debug, release, or whatever) manually.
this does the job. I can't believe I spent a whole day trying to figure this out.
As Oliver said you, your problem is very similar to this one : EmguCV TypeInitializationException
The exception is thrown by an impossibility to access some dll as opencv_highgui220.dll. In CvInvoke you will find DLLImports, maybe you should insert a break point and observe what it comes.
I suppose you have already read this from emgu website
So i have added the coding4fun and microsoft sources and even done what is in the kinect sdk for displaying the kinect image frame on the screen, but for some reason it wont show, i works on the sdk though
Code I've Written
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.Kinect.Nui;
using Coding4Fun.Kinect.Wpf;
using System.Net.Mail;
using System.IO;
using System.ComponentModel;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Runtime nui;
int PersonDetected = 0;
int totalFrames = 0;
int lastFrames = 0;
DateTime lastTime = DateTime.MaxValue;
Dictionary<JointID, Brush> jointColors = new Dictionary<JointID, Brush>() {
{JointID.HipCenter, new SolidColorBrush(Color.FromRgb(169, 176, 155))},
{JointID.Spine, new SolidColorBrush(Color.FromRgb(169, 176, 155))},
{JointID.ShoulderCenter, new SolidColorBrush(Color.FromRgb(168, 230, 29))},
{JointID.Head, new SolidColorBrush(Color.FromRgb(200, 0, 0))},
{JointID.ShoulderLeft, new SolidColorBrush(Color.FromRgb(79, 84, 33))},
{JointID.ElbowLeft, new SolidColorBrush(Color.FromRgb(84, 33, 42))},
{JointID.WristLeft, new SolidColorBrush(Color.FromRgb(255, 126, 0))},
{JointID.HandLeft, new SolidColorBrush(Color.FromRgb(215, 86, 0))},
{JointID.ShoulderRight, new SolidColorBrush(Color.FromRgb(33, 79, 84))},
{JointID.ElbowRight, new SolidColorBrush(Color.FromRgb(33, 33, 84))},
{JointID.WristRight, new SolidColorBrush(Color.FromRgb(77, 109, 243))},
{JointID.HandRight, new SolidColorBrush(Color.FromRgb(37, 69, 243))},
{JointID.HipLeft, new SolidColorBrush(Color.FromRgb(77, 109, 243))},
{JointID.KneeLeft, new SolidColorBrush(Color.FromRgb(69, 33, 84))},
{JointID.AnkleLeft, new SolidColorBrush(Color.FromRgb(229, 170, 122))},
{JointID.FootLeft, new SolidColorBrush(Color.FromRgb(255, 126, 0))},
{JointID.HipRight, new SolidColorBrush(Color.FromRgb(181, 165, 213))},
{JointID.KneeRight, new SolidColorBrush(Color.FromRgb(71, 222, 76))},
{JointID.AnkleRight, new SolidColorBrush(Color.FromRgb(245, 228, 156))},
{JointID.FootRight, new SolidColorBrush(Color.FromRgb(77, 109, 243))}
};
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (Runtime.Kinects.Count == 0)
{
MessageBox.Show("No Kinect Detected");
}
else
{
nui = Runtime.Kinects[0];
nui.Initialize(RuntimeOptions.UseColor | RuntimeOptions.UseSkeletalTracking);
lastTime = DateTime.Now;
nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_VideoFrameReady);
nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
//nui.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
//nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution640x480, ImageType.DepthAndPlayerIndex);
}
}
void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
{
//KinectImage.Source = e.ImageFrame.ToBitmapSource();
PlanarImage Image = e.ImageFrame.Image;
++totalFrames;
{
string bb1 = Convert.ToString(DateTime.Now);
string filename = "C:\\Kinected\\Kinect1_Image " + bb1 + ".jpg";
KinectImage.Source = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
BitmapSource image = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
if (PersonDetected == 1)
{
image.Save(filename, Coding4Fun.Kinect.Wpf.ImageFormat.Jpeg);
SendNotificationEmail();
PersonDetected = 0;
}
}
}
Skeletal Sample Code
using System;
using System.Net.Mail;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.Kinect.Nui;
using Coding4Fun.Kinect.WinForm;
using Coding4Fun.Kinect.Wpf;
using System.IO;
using System.ComponentModel;
namespace SkeletalViewer
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Runtime nui;
// public int ElevationAngle { get; set; }
// public static readonly int ElevationMaximum;
// public static readonly int ElevationMinimum;
//public static readonly int ElevationMedian;
//int ElevationMedian = ElevationAngle == 0;
int totalFrames = 0;
int totalFrames2 = 0;
int lastFrames = 0;
int PersonDetected = 0;
DateTime lastTime = DateTime.MaxValue;
// We want to control how depth data gets converted into false-color data
// for more intuitive visualization, so we keep 32-bit color frame buffer versions of
// these, to be updited whenever we receive and process a 16-bit frame.
const int RED_IDX = 2;
const int GREEN_IDX = 1;
const int BLUE_IDX = 0;
byte[] depthFrame32 = new byte[320 * 240 * 4];
Dictionary<JointID,Brush> jointColors = new Dictionary<JointID,Brush>() {
{JointID.HipCenter, new SolidColorBrush(Color.FromRgb(169, 176, 155))},
{JointID.Spine, new SolidColorBrush(Color.FromRgb(169, 176, 155))},
{JointID.ShoulderCenter, new SolidColorBrush(Color.FromRgb(168, 230, 29))},
{JointID.Head, new SolidColorBrush(Color.FromRgb(200, 0, 0))},
{JointID.ShoulderLeft, new SolidColorBrush(Color.FromRgb(79, 84, 33))},
{JointID.ElbowLeft, new SolidColorBrush(Color.FromRgb(84, 33, 42))},
{JointID.WristLeft, new SolidColorBrush(Color.FromRgb(255, 126, 0))},
{JointID.HandLeft, new SolidColorBrush(Color.FromRgb(215, 86, 0))},
{JointID.ShoulderRight, new SolidColorBrush(Color.FromRgb(33, 79, 84))},
{JointID.ElbowRight, new SolidColorBrush(Color.FromRgb(33, 33, 84))},
{JointID.WristRight, new SolidColorBrush(Color.FromRgb(77, 109, 243))},
{JointID.HandRight, new SolidColorBrush(Color.FromRgb(37, 69, 243))},
{JointID.HipLeft, new SolidColorBrush(Color.FromRgb(77, 109, 243))},
{JointID.KneeLeft, new SolidColorBrush(Color.FromRgb(69, 33, 84))},
{JointID.AnkleLeft, new SolidColorBrush(Color.FromRgb(229, 170, 122))},
{JointID.FootLeft, new SolidColorBrush(Color.FromRgb(255, 126, 0))},
{JointID.HipRight, new SolidColorBrush(Color.FromRgb(181, 165, 213))},
{JointID.KneeRight, new SolidColorBrush(Color.FromRgb(71, 222, 76))},
{JointID.AnkleRight, new SolidColorBrush(Color.FromRgb(245, 228, 156))},
{JointID.FootRight, new SolidColorBrush(Color.FromRgb(77, 109, 243))}
};
private void Window_Loaded(object sender, EventArgs e)
{
nui = new Runtime();
try
{
nui.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);
}
catch (InvalidOperationException)
{
System.Windows.MessageBox.Show("Runtime initialization failed. Please make sure Kinect device is plugged in.");
return;
}
try
{
nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
}
catch (InvalidOperationException)
{
System.Windows.MessageBox.Show("Failed to open stream. Please make sure to specify a supported image type and resolution.");
return;
}
if (Runtime.Kinects.Count < 2)
{
lastTime = DateTime.Now;
nui.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady2);
}
if (Runtime.Kinects.Count == 2)
{
lastTime = DateTime.Now;
nui.DepthFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_DepthFrameReady);
nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady2);
nui.VideoFrameReady += new EventHandler<ImageFrameReadyEventArgs>(nui_ColorFrameReady3);
}
}
// Converts a 16-bit grayscale depth frame which includes player indexes into a 32-bit frame
// that displays different players in different colors
byte[] convertDepthFrame(byte[] depthFrame16)
{
for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)
{
//
// System.Windows.MessageBox.Show(depthFrame16);
int player = depthFrame16[i16] & 0x07;
int realDepth = (depthFrame16[i16+1] << 5) | (depthFrame16[i16] >> 3);
// transform 13-bit depth information into an 8-bit intensity appropriate
// for display (we disregard information in most significant bit)
byte intensity = (byte)(255 - (255 * realDepth / 0x0fff));
depthFrame32[i32 + RED_IDX] = 0;
depthFrame32[i32 + GREEN_IDX] = 0;
depthFrame32[i32 + BLUE_IDX] = 0;
// choose different display colors based on player
switch (player)
{
case 0:
depthFrame32[i32 + RED_IDX] = (byte)(intensity / 2);
depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 2);
depthFrame32[i32 + BLUE_IDX] = (byte)(intensity / 2);
break;
case 1:
depthFrame32[i32 + RED_IDX] = intensity;
break;
case 2:
depthFrame32[i32 + GREEN_IDX] = intensity;
break;
case 3:
depthFrame32[i32 + RED_IDX] = (byte)(intensity / 4);
depthFrame32[i32 + GREEN_IDX] = (byte)(intensity);
depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
break;
case 4:
depthFrame32[i32 + RED_IDX] = (byte)(intensity);
depthFrame32[i32 + GREEN_IDX] = (byte)(intensity);
depthFrame32[i32 + BLUE_IDX] = (byte)(intensity / 4);
break;
case 5:
depthFrame32[i32 + RED_IDX] = (byte)(intensity);
depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 4);
depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
break;
case 6:
depthFrame32[i32 + RED_IDX] = (byte)(intensity / 2);
depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 2);
depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
break;
case 7:
depthFrame32[i32 + RED_IDX] = (byte)(255 - intensity);
depthFrame32[i32 + GREEN_IDX] = (byte)(255 - intensity);
depthFrame32[i32 + BLUE_IDX] = (byte)(255 - intensity);
break;
}
// file_dist.Close();
}
// Console.WriteLine(depthFrame32);
return depthFrame32;
}
void nui_ColorFrameReady(object sender, ImageFrameReadyEventArgs e)
{
// 32-bit per pixel, RGBA image
PlanarImage Image = e.ImageFrame.Image;
++totalFrames;
string bb1 = Convert.ToString(totalFrames);
// string file_name_3 = "C:\\Research\\Kinect\\Proposal\\Depth_Img" + bb1 + ".jpg"; xxx
string file_name_4 = "C:\\temp\\Video_Img" + bb1 + ".jpg";
video.Source = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
BitmapSource image4 = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
// image4.Save(file_name_4, Coding4Fun.Kinect.Wpf.ImageFormat.Jpeg);
}
void nui_ColorFrameReady2(object sender, ImageFrameReadyEventArgs e)
{
// 32-bit per pixel, RGBA image xxx
PlanarImage Image = e.ImageFrame.Image;
//int deltaFrames = totalFrames - lastFrameWithMotion;
//if (totalFrames2 <= stopFrameNumber & deltaFrames > 300)
{
++totalFrames2;
string bb1 = Convert.ToString(totalFrames2);
// string file_name_3 = "C:\\Research\\Kinect\\Proposal\\Depth_Img" + bb1 + ".jpg"; xxx
string file_name_4 = "C:\\Kinected\\Kinect1_Img" + bb1 + ".jpg";
video.Source = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
BitmapSource image4 = BitmapSource.Create(
Image.Width, Image.Height, 96, 96, PixelFormats.Bgr32, null, Image.Bits, Image.Width * Image.BytesPerPixel);
if (PersonDetected == 1)
{
if (totalFrames2 % 10 == 0)
{
image4.Save(file_name_4, Coding4Fun.Kinect.Wpf.ImageFormat.Jpeg);
SendNotificationEmail();
PersonDetected = 0;
// lastFrameWithMotion = totalFrames;
// topFrameNumber += 100;
}
}
}
}
Any ideas about why it isnt displaying the image on my application?
Do what benjgorman said, if your using an xbox kinect, it will still work with the new sdk. You can get it here. The code feels a bit different from the older programs, but you'll get used to it pretty fast. You can get the tutorials i used from here, or use the code i provided, make sure that you add the sources Microsoft.Kinect and add the project from the kinect explorer(you download that via the sdk) Microsoft.Samples.Kinect.WpfViewers and then add that as a source. I would reccomend watching the tutorials as they explain the classes and what you need in the SDK
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using System.Net.Mail;
using Coding4Fun.Kinect.Wpf;
using Microsoft.Samples.Kinect.WpfViewers;
using System.Diagnostics;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
kinectSensorChooser1.KinectSensorChanged += new DependencyPropertyChangedEventHandler(kinectSensorChooser1_KinectSensorChanged);
}
void kinectSensorChooser1_KinectSensorChanged(object sender, DependencyPropertyChangedEventArgs e)
{
KinectSensor oldSensor = (KinectSensor)e.OldValue;
StopKinect(oldSensor);
KinectSensor newSensor = (KinectSensor)e.NewValue;
newSensor.ColorStream.Enable();
newSensor.DepthStream.Enable();
newSensor.SkeletonStream.Enable();
newSensor.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(newSensor_AllFramesReady);
try
{
newSensor.Start();
}
catch (System.IO.IOException)
{
kinectSensorChooser1.AppConflictOccurred();
}
}
void StopKinect(KinectSensor sensor)
{
if (sensor != null)
{
sensor.Stop();
sensor.AudioSource.Stop();
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
StopKinect(kinectSensorChooser1.Kinect);
}
void newSensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (colorFrame == null)
{
return;
}
byte[] pixels = new byte[colorFrame.PixelDataLength];
colorFrame.CopyPixelDataTo(pixels);
int stride = colorFrame.Width * 4;
video.Source = BitmapSource.Create(
colorFrame.Width, colorFrame.Height, 96, 96,
PixelFormats.Bgr32, null, pixels, stride);
}
}
Hope this helps.