I am developing a functionality that involves saving the fingerprint, for this function I have used the Digital Persona U 4500 reader.
Download and install the personal digital SDK and build a windows form c # application.
I added the control whose name: DigitalPersona Fingerprint Enrollment Control and in effect captures the fingerprint
The objective is to be able to visualize the footprint that has been placed in the reader to see in detail how it has been, for this purpose I added a picturebox to be displayed in it and additionally include the following:
public DPFP.Sample Sample = new DPFP.Sample();// instancia la muestra
DPFP.Capture.SampleConversion Convertor = new DPFP.Capture.SampleConversion();
Bitmap bitmap = null;
Convertor.ConvertToPicture(sample, ref bitmap);
PicBoxHuella.Image = bitmap;
With the previous action it should show the sample in the picture, but it is not. Valid and identified that the sample arrives in null.
I can't understand the Null value, if when putting a footprint I should capture the value, I would appreciate your guidance a bit on the subject.
On the OnCaptured event, you get the image data from the Fiv en Data.Views:
Note: pbFingerprint is an PictureBox where the image will display.
private void enrollment_OnCaptured(EnrollmentControl enrollmentControl, CaptureResult captureResult, int fingerPosition)
{
if (captureResult.ResultCode == Constants.ResultCode.DP_SUCCESS)
{
if (captureResult.Data != null)
{
foreach (Fid.Fiv fiv in captureResult.Data.Views)
{
pbFingerprint.Image = CreateBitmap(fiv.RawImage, fiv.Width, fiv.Height);
}
}
}
}
/// <summary>
/// Create a bitmap from raw data in row/column format.
/// </summary>
/// <param name="bytes"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
private Bitmap CreateBitmap(byte[] bytes, int width, int height)
{
byte[] rgbBytes = new byte[bytes.Length * 3];
for (int i = 0; i <= bytes.Length - 1; i++)
{
rgbBytes[(i * 3)] = bytes[i];
rgbBytes[(i * 3) + 1] = bytes[i];
rgbBytes[(i * 3) + 2] = bytes[i];
}
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
for (int i = 0; i <= bmp.Height - 1; i++)
{
IntPtr p = new IntPtr(data.Scan0.ToInt64() + data.Stride * i);
System.Runtime.InteropServices.Marshal.Copy(rgbBytes, i * bmp.Width * 3, p, bmp.Width * 3);
}
bmp.UnlockBits(data);
return bmp;
}
I am first time working on DirectX, I find difficulty in upgrading the code from DirectX9 to DirectX11. Unable to get the code similar in DirectX 11 since lot of changes from DirectX9 to 11.
Like below is my code for Direct3D9 of SlimDx
using SlimDX;
using SlimDX.Direct3D9;
private readonly Device m_Device;
private readonly Direct3D m_Direct3D;
private readonly PresentParameters m_presentParams;
//renderer
public Renderer() {
m_Direct3D = new Direct3D();
var createFlags = CreateFlags.SoftwareVertexProcessing | CreateFlags.FpuPreserve;
var caps = m_Direct3D.GetDeviceCaps(0, DeviceType.Hardware);
if ((caps.DeviceCaps & DeviceCaps.HWTransformAndLight) != 0) // HW processing supported
{
createFlags = CreateFlags.HardwareVertexProcessing | CreateFlags.FpuPreserve;
}
m_presentParams = new PresentParameters();
m_presentParams.BackBufferFormat = Format.A8R8G8B8;
m_presentParams.BackBufferCount = 1;
m_presentParams.Multisample = MultisampleType.None;
m_presentParams.SwapEffect = SwapEffect.Flip;
m_presentParams.EnableAutoDepthStencil = true;
m_presentParams.AutoDepthStencilFormat = Format.D16;
m_presentParams.PresentFlags = PresentFlags.DiscardDepthStencil;
m_presentParams.PresentationInterval = PresentInterval.One;
m_presentParams.Windowed = true;
m_presentParams.DeviceWindowHandle = handle;
m_Device = new Device(m_Direct3D,
0,
DeviceType.Hardware,
handle,
createFlags,
m_presentParams);
m_Device.Present();
System.Drawing.Rectangle oldBounds = m_Device.ScissorRect;
}
//begins the scene
public void BeginScene() {
m_Device.BeginScene();
}
//create texture
public Texture CreateTextureFromStream(Stream srcStream) {
srcStream.Seek(0, SeekOrigin.Begin);
return Texture.FromStream(m_Device, srcStream, 0, Pool.Managed);
}
//ends the scene
public void EndScene() {
m_Device.EndScene();
}
/// <summary>
/// Gets the size of the max texture.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public void GetMaxTextureSize(out int width, out int height) {
Capabilities c = m_Direct3D.GetDeviceCaps(0, DeviceType.Hardware);
width = c.MaxTextureHeight;
height = c.MaxTextureWidth;
}
//reset
public bool IsResetRequired() {
return m_Device.TestCooperativeLevel() == ResultCode.DeviceNotReset;
}
//render background
public void RenderBackground() {
m_Device.VertexFormat = VertexFormat.Position | VertexFormat.Diffuse;
m_Device.DrawUserPrimitives(PrimitiveType.TriangleList, m_backgroundRectBuffer.Count / 3, m_backgroundRectBuffer.ToArray());
m_backgroundRectBuffer.Clear();
}
//begin
public void RenderBegin() {
m_Device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb(0), 1.0f, 0);
}
Now, i want to move to DirectX 11. Can anyone help me out of this.
I've got the following problem. My intention is to move several images from the right to the left in a Windows Form. The code below works quite fine. What bothers me is the fact that every time a PictureBox object is created, this procedure eats up enormous amounts of memory. Each image follows the previous image uninterruptedly from the right to the left. The images display a sky moving from one side to another. It should look like a plane's flying through the air.
How is it possible to avoid using too much memory? Is there something I can do with PaintEvent and GDI? I'm not very familiar with graphics programming.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
public class Background : Form
{
private PictureBox sky, skyMove;
private Timer moveSky;
private int positionX = 0, positionY = 0, width, height;
private List<PictureBox> consecutivePictures;
public Background(int width, int height)
{
this.width = width;
this.height = height;
// Creating Windows Form
this.Text = "THE FLIGHTER";
this.Size = new Size(width, height);
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
// The movement of the sky becomes possible by the timer.
moveSky = new Timer();
moveSky.Tick += new EventHandler(moveSky_XDirection_Tick);
moveSky.Interval = 10;
moveSky.Start();
consecutivePictures = new List<PictureBox>();
skyInTheWindow();
this.ShowDialog();
}
// sky's direction of movement
private void moveSky_XDirection_Tick(object sender, EventArgs e)
{
for (int i = 0; i < 100; i++)
{
skyMove = consecutivePictures[i];
skyMove.Location = new Point(skyMove.Location.X - 6, skyMove.Location.Y);
}
}
private void skyInTheWindow()
{
for (int i = 0; i < 100; i++)
{
// Loading sky into the window
sky = new PictureBox();
sky.Image = new Bitmap("C:/MyPath/Sky.jpg");
sky.SetBounds(positionX, positionY, width, height);
this.Controls.Add(sky);
consecutivePictures.Add(sky);
positionX += width;
}
}
}
You seem to be loading the same bitmap 100 times. There's your memory problem right there, not the 100 PictureBoxs. A PictureBox should have a low memory overhead because they don't include the image in their memory consumption, it is the referenced Bitmap that is much more likely to consume large amounts of memory.
It's easily fixed - consider loading the bitmap once and then applying it to all your PictureBoxs.
Change:
private void skyInTheWindow()
{
for (int i = 0; i < 100; i++)
{
// Loading sky into the window
sky = new PictureBox();
sky.Image = new Bitmap("C:/MyPath/Sky.jpg");
sky.SetBounds(positionX, positionY, width, height);
this.Controls.Add(sky);
consecutivePictures.Add(sky);
positionX += width;
}
}
...to:
private void skyInTheWindow()
{
var bitmap = new Bitmap("C:/MyPath/Sky.jpg"); // load it once
for (int i = 0; i < 100; i++)
{
// Loading sky into the window
sky = new PictureBox();
sky.Image = bitmap; // now all picture boxes share same image, thus less memory
sky.SetBounds(positionX, positionY, width, height);
this.Controls.Add(sky);
consecutivePictures.Add(sky);
positionX += width;
}
}
You could just have a single PictureBox stretched to the width of the background but shift it over time. Of course you'll need to draw something on the edge where a gap would appear.
You might get a bit of flicker with repeated PictureBox though which is one of the things I'm worried about but it might still serve.
Or what I'd do is create a UserControl and override OnPaint and just turn it into a draw bitmap issue and not have PictureBoxs at all. Much faster and efficient and no flicker. :) This is purely optional
You have the potential to eliminate any flicker too if you draw first to an offscreen Graphics and Bitmap and "bitblit" the results to the visible screen.
Would you mind giving me some code which serves as a point of reference because for me it's hard to implement into code? I'm not very familiar in graphics programming and I really want to learn from one another. The code without flickering is better
As requested I have included the code below:
Flicker Free Offscreen Rendering UserControl
Essentially what this does is to create an offscreen bitmap that we will draw into first. It is the same size as the UserControl. The control's OnPaint calls DrawOffscreen passing in the Graphics that is attached to the offscreen bitmap. Here we loop around just rendering the tiles/sky that are visible and ignoring others so as to improve performance.
Once it's all done we zap the entire offscreen bitmap to the display in one operation. This serves to eliminate:
Flicker
Tearing effects (typically associated with lateral movement)
There is a Timer that is scheduled to update the positions of all the tiles based on the time since the last update. This allows for a more realistic movement and avoids speed-ups and slow-downs under load. Tiles are moved in the OnUpdate method.
Some important properties:
DesiredFps - desired frames/second. This directly controls how frequently the OnUpdate method is called. It does not directly control how frequently OnPaint is called
NumberOfTiles - I've set it to your 100 (cloud images)
Speed - the speed in pixels/second the bitmaps move. Tied to DesiredFps. This is a load-independent; computer-performance-independent value
Painting
If you note in the code for Timer1OnTick I call Invalidate(Bounds); after animating everything. This does not cause an immediate paint rather Windows will queue a paint operation to be done at a later time. Consecutive pending operations will be fused into one. This means that we can be animating positions more frequently than painting during heavy load. Animation mechanic is independent of paint. That's a good thing, you don't want to be waiting for paints to occur.
You will note that I override OnPaintBackground and essentially do nothing. I do this because I don't want .NET to erase the background and causing unnecessary flicker prior to calling my OnPaint. I don't even bother erasing the background in DrawOffscreen because we're just going to draw bitmaps over it anyway. However if the control was resized larger than the height of the sky bitmap and if it is a requirement then you may want to. Performance-hit is pretty negligible I suppose when you are arguably drawing multiple sky-bitmaps anyway.
When you build the code, you can plonk it on any Form. The control will be visible in the Toolbox. Below I have plonked it on my MainForm.
The control also demonstrates design-time properties and defaults which you can see below. These are the settings that seem to work well for me. Try changing them for different effects.
If you dock the control and your form is resizable then you can resize the app at runtime. Useful for measuring performance. WinForms is not particularly hardware-accelerated (unlike WPF) so I wouldn't recommend the window to be too large.
Code:
#region
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using SkyAnimation.Properties;
#endregion
namespace SkyAnimation
{
/// <summary>
/// </summary>
public partial class NoFlickerControl : UserControl
{
#region Fields
private readonly List<RectangleF> _tiles = new List<RectangleF>();
private DateTime _lastTick;
private Bitmap _offscreenBitmap;
private Graphics _offscreenGraphics;
private Bitmap _skyBitmap;
#endregion
#region Constructor
public NoFlickerControl()
{
// set defaults first
DesiredFps = Defaults.DesiredFps;
NumberOfTiles = Defaults.NumberOfTiles;
Speed = Defaults.Speed;
InitializeComponent();
if (DesignMode)
{
return;
}
_lastTick = DateTime.Now;
timer1.Tick += Timer1OnTick;
timer1.Interval = 1000/DesiredFps; // How frequenty do we want to recalc positions
timer1.Enabled = true;
}
#endregion
#region Properties
/// <summary>
/// This controls how often we recalculate object positions
/// </summary>
/// <remarks>
/// This can be independant of rendering FPS
/// </remarks>
/// <value>
/// The frames per second.
/// </value>
[DefaultValue(Defaults.DesiredFps)]
public int DesiredFps { get; set; }
[DefaultValue(Defaults.NumberOfTiles)]
public int NumberOfTiles { get; set; }
/// <summary>
/// Gets or sets the sky to draw.
/// </summary>
/// <value>
/// The sky.
/// </value>
[Browsable(false)]
public Bitmap Sky { get; set; }
/// <summary>
/// Gets or sets the speed in pixels/second.
/// </summary>
/// <value>
/// The speed.
/// </value>
[DefaultValue(Defaults.Speed)]
public float Speed { get; set; }
#endregion
#region Methods
private void HandleResize()
{
// the control has resized, time to recreate our offscreen bitmap
// and graphics context
if (Width == 0
|| Height == 0)
{
// nothing to do here
}
_offscreenBitmap = new Bitmap(Width, Height);
_offscreenGraphics = Graphics.FromImage(_offscreenBitmap);
}
private void NoFlickerControl_Load(object sender, EventArgs e)
{
SkyInTheWindow();
HandleResize();
}
private void NoFlickerControl_Resize(object sender, EventArgs e)
{
HandleResize();
}
/// <summary>
/// Handles the SizeChanged event of the NoFlickerControl control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
private void NoFlickerControl_SizeChanged(object sender, EventArgs e)
{
HandleResize();
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint" /> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs" /> that contains the event data. </param>
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
var rc = e.ClipRectangle;
if (_offscreenBitmap == null
|| _offscreenGraphics == null)
{
g.FillRectangle(Brushes.Gray, rc);
return;
}
DrawOffscreen(_offscreenGraphics, ClientRectangle);
g.DrawImageUnscaled(_offscreenBitmap, 0, 0);
}
private void DrawOffscreen(Graphics g, RectangleF bounds)
{
// We don't care about erasing the background because we're
// drawing over it anyway
//g.FillRectangle(Brushes.White, bounds);
//g.SetClip(bounds);
foreach (var tile in _tiles)
{
if (!(bounds.Contains(tile) || bounds.IntersectsWith(tile)))
{
continue;
}
g.DrawImageUnscaled(_skyBitmap, new Point((int) tile.Left, (int) tile.Top));
}
}
/// <summary>
/// Paints the background of the control.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs" /> that contains the event data.</param>
protected override void OnPaintBackground(PaintEventArgs e)
{
// NOP
// We don't care painting the background here because
// 1. we want to do it offscreen
// 2. the background is the picture anyway
}
/// <summary>
/// Responsible for updating/translating game objects, not drawing
/// </summary>
/// <param name="totalMillisecondsSinceLastUpdate">The total milliseconds since last update.</param>
/// <remarks>
/// It is worth noting that OnUpdate could be called more times per
/// second than OnPaint. This is fine. It's generally a sign that
/// rendering is just taking longer but we are able to compensate by
/// tracking time since last update
/// </remarks>
private void OnUpdate(double totalMillisecondsSinceLastUpdate)
{
// Remember that we measure speed in pixels per second, hence the
// totalMillisecondsSinceLastUpdate
// This allows us to have smooth animations and to compensate when
// rendering takes longer for certain frames
for (int i = 0; i < _tiles.Count; i++)
{
var tile = _tiles[i];
tile.Offset((float)(-Speed * totalMillisecondsSinceLastUpdate / 1000f), 0);
_tiles[i] = tile;
}
}
private void SkyInTheWindow()
{
_tiles.Clear();
// here I load the bitmap from my embedded resource
// but you easily could just do a new Bitmap ("C:/MyPath/Sky.jpg");
_skyBitmap = Resources.sky400x400;
var bounds = new Rectangle(0, 0, _skyBitmap.Width, _skyBitmap.Height);
for (var i = 0; i < NumberOfTiles; i++)
{
// Loading sky into the window
_tiles.Add(bounds);
bounds.Offset(bounds.Width, 0);
}
}
private void Timer1OnTick(object sender, EventArgs eventArgs)
{
if (DesignMode)
{
return;
}
var ellapsed = DateTime.Now - _lastTick;
OnUpdate(ellapsed.TotalMilliseconds);
_lastTick = DateTime.Now;
// queue cause a repaint
// It's important to realise that repaints are queued and fused
// together if the message pump gets busy
// In other words, there may not be a 1:1 of OnUpdate : OnPaint
Invalidate(Bounds);
}
#endregion
}
public static class Defaults
{
public const int DesiredFps = 30;
public const int NumberOfTiles = 100;
public const float Speed = 300f;
}
}
This isn't directly an answer to this question - I think that's primarily because of all the Bitmap images you're creating. You should only create one and then the problem goes away.
What I'm suggesting here is an alternative way of coding this that cuts the code enormously.
All of my code goes straight in your Background constructor after the line this.MaximizeBox = false;. Everything after that is removed.
So start with loading the image:
var image = new Bitmap(#"C:\MyPath\Sky.jpg");
Next, work out how many picture boxes do I need to tile the image across the form based on the width and height passed in:
var countX = width / image.Width + 2;
var countY = height / image.Height + 2;
Now create the actual picture boxes that will populate the screen:
var pictureBoxData =
(
from x in Enumerable.Range(0, countX)
from y in Enumerable.Range(0, countY)
let positionX = x * image.Width
let positionY = y * image.Height
let pictureBox = new PictureBox()
{
Image = image,
Location = new Point(positionX, positionY),
Size = new Size(image.Width, image.Height),
}
select new
{
positionX,
positionY,
pictureBox,
}
).ToList();
Next, add them all to the Controls collection:
pictureBoxData.ForEach(pbd => this.Controls.Add(pbd.pictureBox));
Finally, use Microsoft's Reactive Framework (NuGet Rx-WinForms) to create a timer that will update the Left position of the picture boxes:
var subscription =
Observable
.Generate(
0,
n => true,
n => n >= image.Width ? 0 : n + 1,
n => n,
n => TimeSpan.FromMilliseconds(10.0))
.ObserveOn(this)
.Subscribe(n =>
{
pictureBoxData
.ForEach(pbd => pbd.pictureBox.Left = pbd.positionX - n);
});
Finally, before launching the dialog, we need a way to cleanup all of the above so that the form closes cleanly. Do this:
var disposable = new CompositeDisposable(image, subscription);
this.FormClosing += (s, e) => disposable.Dispose();
Now you can do the ShowDialog:
this.ShowDialog();
And that's it.
Apart from nugetting Rx-WinForms, you need to add the following using statements to the top of the code:
using System.Reactive.Linq;
using System.Reactive.Disposables;
It all worked nicely for me:
The variables and names haven't been translated into English. I nevertheless hope that it's understandable for all of you.
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
/// <summary>
/// Scrolling Background - Bewegender Hintergrund
/// </summary>
public class ScrollingBackground : Form
{
/* this = fremde Attribute und Methoden,
* ohne this = eigene Attribute und Methoden
*/
private PictureBox picBoxImage;
private PictureBox[] listPicBoxAufeinanderfolgendeImages;
private Timer timerBewegungImage;
private const int constIntAnzahlImages = 2,
constIntInterval = 1,
constIntPositionY = 0;
private int intPositionX = 0,
intFeinheitDerBewegungen,
intBreite,
intHoehe;
private string stringTitel,
stringBildpfad;
// Konstruktor der Klasse Hintergrund
/// <summary>
/// Initialisiert eine neue Instanz der Klasse Hintergrund unter Verwendung der angegebenen Ganzzahlen und Zeichenketten.
/// Es wird ein Windows-Fenster erstellt, welches die Möglichkeit hat, ein eingefügtes Bild als bewegenden Hintergrund darzustellen.
/// </summary>
/// <param name="width">Gibt die Breite des Fensters an und passt den darin befindlichen Hintergrund bzgl. der Breite automatisch an.</param>
/// <param name="height">Gibt die Höhe des Fensters an und passt den darin befindlichen Hintergrund bzgl. der Höhe automatisch an.</param>
/// <param name="speed">Geschwindigkeit der Bilder</param>
/// <param name="title">Titel des Fensters</param>
/// <param name="path">Pfad des Bildes, welches als Hintergrund dient</param>
public ScrollingBackground(int width, int height, int speed, string title, string path)
{
// Klassennutzer können Werte setzen
intBreite = width;
intHoehe = height;
intFeinheitDerBewegungen = speed;
stringTitel = title;
stringBildpfad = path;
// Windows-Fenster wird erschaffen
this.Text = title;
this.Size = new Size(this.intBreite, this.intHoehe);
this.StartPosition = FormStartPosition.CenterScreen;
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
// Die Bewegung des Bildes wird durch den Timer ermöglicht.
timerBewegungImage = new Timer();
timerBewegungImage.Tick += new EventHandler(bewegungImage_XRichtung_Tick);
timerBewegungImage.Interval = constIntInterval;
timerBewegungImage.Start();
listPicBoxAufeinanderfolgendeImages = new PictureBox[2];
imageInWinFormLadenBeginn();
this.ShowDialog();
}
// Bewegungsrichtung des Bildes
private void bewegungImage_XRichtung_Tick(object sender, EventArgs e)
{
for (int i = 0; i < constIntAnzahlImages; i++)
{
picBoxImage = listPicBoxAufeinanderfolgendeImages[i];
// Flackerreduzierung - Minimierung des Flackerns zwischen zwei Bildern
this.DoubleBuffered = true;
// Bilder werden in X-Richtung bewegt
picBoxImage.Location = new Point(picBoxImage.Location.X - intFeinheitDerBewegungen, picBoxImage.Location.Y);
// Zusammensetzung beider gleicher Bilder, welche den Effekt haben, die Bilder ewig fortlaufend erscheinen zu lassen
if (listPicBoxAufeinanderfolgendeImages[1].Location.X <= 0)
{
imageInWinFormLadenFortsetzung();
}
}
}
// zwei PictureBoxes mit jeweils zwei gleichen Bildern werden angelegt
private void imageInWinFormLadenBeginn()
{
Bitmap bitmapImage = new Bitmap(stringBildpfad);
for (int i = 0; i < constIntAnzahlImages; i++)
{
// Bild wird in Fenster geladen
picBoxImage = new PictureBox();
picBoxImage.Image = bitmapImage;
// Bestimmung der Position und Größe des Bildes
picBoxImage.SetBounds(intPositionX, constIntPositionY, intBreite, intHoehe);
this.Controls.Add(picBoxImage);
listPicBoxAufeinanderfolgendeImages[i] = picBoxImage;
// zwei PictureBoxes mit jeweils zwei gleichen Bildern werden nebeneinander angefügt
intPositionX += intBreite;
}
}
// Wiederholte Nutzung der PictureBoxes
private void imageInWinFormLadenFortsetzung()
{
// erste PictureBox mit Image wird wieder auf ihren Anfangswert "0" gesetzt - Gewährleistung der endlos laufenden Bilder
picBoxImage = listPicBoxAufeinanderfolgendeImages[0];
picBoxImage.SetBounds(intPositionX = 0, constIntPositionY, intBreite, intHoehe);
// zweite PictureBox mit Image wird wieder auf ihren Anfangswert "intBreite" gesetzt - Gewährleistung der endlos laufenden Bilder
picBoxImage = listPicBoxAufeinanderfolgendeImages[1];
picBoxImage.SetBounds(intPositionX = intBreite, constIntPositionY, intBreite, intHoehe);
}
}
Regards,
Lucky Buggy
I am facing an issue regarding saving the whole webpage as image. I have a web application and all the controls used are 'user controls'. I have one page in my application and using that I grab the webpage image and saving to one folder in the solution. i got the image but the issue is the height of the image is not correct . Ie: the page height that I am receiving is not correct. When I debug , it shows 0px as height for the page.
My code is as follows:
protected void GetThumbnailWorker()
{
using (WebBrowser browser = new WebBrowser())
{
//browser.ClientSize = new Size(_width, _height);
//browser.ClientSize = new Size(960,2000);
browser.ScrollBarsEnabled = false;
browser.ScriptErrorsSuppressed = true;
browser.Navigate(_url);
// Wait for control to load page
while (browser.ReadyState != WebBrowserReadyState.Complete)
Application.DoEvents();
// Render browser content to bitmap
int imgaewidth = 0;
int imageheight=0;
imgaewidth=browser.Document.Body.ScrollRectangle.Width;
imageheight=browser.Document.Body.ScrollRectangle.Height;
if (imageheight <100)
{
imageheight = 1500;
}
if (imgaewidth == 0)
{
imgaewidth = 964;
}
browser.ClientSize = new Size(imgaewidth, imageheight);
_bmp = new Bitmap(imgaewidth, imageheight);
browser.DrawToBitmap(_bmp, new Rectangle(0, 0,
imgaewidth, imageheight));
}
}
I set the image height to 1500 due to this problem.
Can any one help me?
Updating the code:
public static Bitmap GetThumbnail(string url, int width, int height,
int thumbWidth, int thumbHeight)
{
WebsiteThumbnail thumbnail = new WebsiteThumbnail(url, width, height,
thumbWidth, thumbHeight);
return thumbnail.GetThumbnail();
}
/// <summary>
/// Protected constructor
/// </summary>
protected WebsiteThumbnail(string url, int width, int height,
int thumbWidth, int thumbHeight)
{
_url = url;
_width = width;
_height = height;
_thumbWidth = thumbWidth;
_thumbHeight = thumbHeight;
}
/// <summary>
/// Returns a thumbnail for the current member values
/// </summary>
/// <returns>Thumbnail bitmap</returns>
protected Bitmap GetThumbnail()
{
// WebBrowser is an ActiveX control that must be run in a
// single-threaded apartment so create a thread to create the
// control and generate the thumbnail
Thread thread = new Thread(new ThreadStart(GetThumbnailWorker));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return _bmp.GetThumbnailImage(_thumbWidth, _thumbHeight,
null, IntPtr.Zero) as Bitmap;
}
I want to compare an image of a document with a logo type or another picture to see if the logo is in the document.
The application to do this is going to use ASP.NET MVC 3 and C#.
After more searching i finded a solution with a extension of Bitmap that using AForge:
public static class BitmapExtensions
{
/// <summary>
/// See if bmp is contained in template with a small margin of error.
/// </summary>
/// <param name="template">The Bitmap that might contain.</param>
/// <param name="bmp">The Bitmap that might be contained in.</param>
/// <returns>You guess!</returns>
public static bool Contains(this Bitmap template, Bitmap bmp)
{
const Int32 divisor = 4;
const Int32 epsilon = 10;
ExhaustiveTemplateMatching etm = new ExhaustiveTemplateMatching(0.9f);
TemplateMatch[] tm = etm.ProcessImage(
new ResizeNearestNeighbor(template.Width / divisor, template.Height / divisor).Apply(template),
new ResizeNearestNeighbor(bmp.Width / divisor, bmp.Height / divisor).Apply(bmp)
);
if (tm.Length == 1)
{
Rectangle tempRect = tm[0].Rectangle;
if (Math.Abs(bmp.Width / divisor - tempRect.Width) < epsilon
&&
Math.Abs(bmp.Height / divisor - tempRect.Height) < epsilon)
{
return true;
}
}
return false;
}
}
I think that you want to use template matching functionalities. I would suggest using opencv for that. This is similar to this question