Faster image paint method - c#

My project consists of a video player and a image viewer, both fullscreen in a panel with only one visible at a time. When the video pauses I capture the frame, display it in the image viewer and swap which control is visible. The problem is, when the image viewer is shown you see the previous image for a brief second before the new image is painted.
Does anyone have any suggestions on how I can prevent this? Ideally I want it to be seemless when the controls swap.
I've already set the image viewer to be double buffered.
Edit:
Code, doesn't really show much here.
private void ShowImageView()
{
this.axWindowsMediaPlayer.Visible = false;
this.imageViewer.Visible = true;
}
private void ShowVideoView()
{
this.axWindowsMediaPlayer.Visible = true;
this.imageViewer.Visible = false;
}

I've managed to solve it, the image viewer had a Image Changed event that I hadn't spotted (I'd tried using the Image Loaded event). Subscribing to the image changed event and only showing the control then, seems to give me the transistion I was looking for.

Related

Failed to take photo with the webcam using the library AForge

I am making use of the AForge class library.
From this library I am using VideoSourcePlayer to take photos with the webcam.
My purpose is to create a function that allows the user to photograph images to establish them as company logo.
Not only can you choose images from the computer, but you can also capture images from the outside through the camera, since you may only want to transfer a logo of a physical support (paper) to the program.
As commented earlier in SO, (how to pause a video file played using videosourceplayer), VideoSourcePlayer does not have a Pause method or any function that allows to freeze the image.
Yes, it is true that it has the GetCurrentFrame() method, but that only gets a Bitmap from the current frame that must be passed to a PictureBox.
But I want that when the user clicks the button Capture the image of the VideoSourcePlayer simulate being frozen, and when the user presses the Delete button because he did not like the photo, then the image stops being frozen and recovers its movement.
Logic is like pausing or playing a video.
Well, there's no method for it, so I decided to look for another way to get this, and ...
If a picture is taken, use a PictureBox that contains the last frame and that is displayed on the VideoSourcePlayer, but if it is deleted, then the PictureBox is removed and the VideoSourcePlayer is returned with video.
private readonly Bitmap EmptyBitmap;
private void CaptureBtn_Click(object sender, EventArgs e)
{
Bitmap bitmap = this.VideoSource.GetCurrentVideoFrame();
ShowTakedFrame(bitmap, false);
}
private void ShowTakedFrame(Bitmap Frame, bool remove)
{
var picture = new System.Windows.Forms.PictureBox();
picture.Size = this.VideoSource.Size;
picture.Location = this.VideoSource.Location;
if (!remove)
{
this.VideoSource.Stop();
picture.Image = Frame;
this.Controls.Remove(VideoSource);
this.Controls.Add(picture);
}
else
{
this.Controls.Remove(picture);
this.Controls.Add(VideoSource);
this.VideoSource.VideoSource = this.CaptureDevice;
this.VideoSource.Start();
}
}
private void DeleteBtn_Click(object sender, EventArgs e)
{
ShowTakedFrame(EmptyBitmap, true);
}
My problem is that when capturing the photo, the image is a few seconds after the moment when you press the Capture button and when you delete the captured image, using the Delete button, the video of the VideoSourcePlayer is frozen.
Can someone help me with this?
The problem is that when you remove the PictureBox and add the VideoSourcePlayer, it creates a new object, that is, one that does not have the configuration properties of the previous one. My recommendation is that you create the capture in a different form.

Render pdf using wpf

I need to write my own pdf viewer (UserControl). I use pdfium.dll for that. The wrapper of it is PdfiumService. This service can render pages to BitmapSource.
PdfViewer displays pages in VirtualizingStackPanel in ScrollViewer.
Any ideas how can I do lazy render for pdf? The problem is if pdf is about 20mb (1000 pages), rendered pages take about 2gb RAM.
Can VirtualizingStackPanel help me? I didn't find any events for "BeginVirtualizing" or something else. Any easy ways to know what item is displaying now?
Maybe something like that:
Calculate how many pages can be displayed at once.
See ScrollViewer's offset.
Calculate the index of page is now displaying.
Render 5 pages next to current.
Are there any ready solutions, or some tips, or ideas for this?
well, i had a bit of that with images from books....the trouble is not really the gui where you put the bitmap, but how you get the images from the library...is it one by one, sequentially or randomly ?
In fact, if you use a VirtualizingStackPanel it will only manage the gui element to create or destroy, but if you have a full collection of bitmaps in memory you are dead.
One way is to create Page object whitout the bitmap, and create the image when needed + add a timer that will clear all "oldest images"
I do something like that in CBR; and i use a custom control to display pages
private BitmapImage _Image = null;
/// <summary>
/// the image
/// </summary>
public BitmapImage Image
{
get
{
if (_Image == null)
_Image = (DocumentFactory.Instance.GetService(Parent) as BookService).GetImageFromStream(Parent.FilePath, FilePath);
ImageLastAcces = DateTime.Now;
return _Image;
}
set { _Image = value; }
}

Save Image in PictureBox with overlapping Controls

I am developing an application in which user can select an image in a picture box.
After that he can right click on the image and add a user control which will again display an Image along with some text. This user control can be added any number of times.
User can also re-position the user controls as per need.
All this functionality has been implemented and is working fine.
Now, the requirement is to save the Image along with the user control.
Above you can see the complete image which needs to be saved. Back image is the picture box image and the user control (small images with text).
When user will click on save button the image should get saved on his disk as a single image.
This is a windows application developed in C#.
I want to know that whether this functionality can be achieved or not. If yes, then please guide me in the right direction.
If you create a copy of the bitmap then with the Graphics.DrawImage() you can draw those images onto it. You need to calculate the position of those controls.
Look here for DrawImage: http://msdn.microsoft.com/en-us/library/42807xh1.aspx
example:
Bitmap copy = new Bitmap(OriginalBitmap);
Graphics g = Graphics.FromImage(copy);
g.DrawImage(arrowBitmap, new Point(..));
copy.Save(...);
A very simple and straight forward solution exists, has been thought of by Microsoft and includes these steps:
Instead of PictureBox use a Panel and instead of using the Image property of the PictureBox use the BackgroundImage property of the Panel
note: By using also the BackgroundImageLayout property you can quite easily instruct the Panel to stretch, center or zoom the image (I'm presuming the default value which is tile is not a good option in your case)
Instead of placing the other user controls at higher Z order but alongside the previous PictureBox place them inside the Panel
Use the Control.DrawToBitmap method like so:
private void button1_Click(object sender, EventArgs e) {
var bmp = new Bitmap(this.panel1.Width, this.panel1.Height);
this.panel1.DrawToBitmap(bmp, new Rectangle(Point.Empty, bmp.Size));
bmp.Save(#"D:\test.png", ImageFormat.Png);
}
That will result in your controls begin rendered along with the picture:
Furthermore, and if your scenario allows it, you could simply use the DrawToBitmap method with any control which contains all of the actors you wish to render, for instance the actual Form.

Picture Box size expanded when program runs

i am currently learning on webcam based qr code decoder i have taken an example from https://zxingnet.svn.codeplex.com/svn/trunk/Clients/AForgeDemo/ . i have manage to get it working however i have a problem which baffle me. it is regarding to the picture box in my GUI.
the image above is before i press the start/ continue button. the image after is as below
is there any setting in the picture box property which could prevent the picturebox from expanding or do i need to type a source code to. it would be great if anyone could highlight what i need to do to prevent the expending of the picture box. thank you
Set the MaximumSize property of the picture box to however big you want it to be. You can also set MinimumSize while you're at it.
Hey Try This Code on click of Start Button
private void Button1_Click(System.Object sender, System.EventArgs e)
{
// Set the SizeMode property to the StretchImage value. This
// will enlarge the image as needed to fit into
// the PictureBox.
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
Hope it will helps you
Seems like you have to set PictureBox.SizeMode to everithing else than AutoSize.

Switching between animated image and static image in winforms button

So I have a custom Button class in a Winforms app written in C# 4.0. The button holds a static image normally, but when a refresh operation takes place it switches to an animated AJAX-style button. In order to animate the image I have a timer set up that advances the image animation on every tick and sets that as the button image. That's the only way I can get it to work. The solution I have isn't that efficient; any advice would be helpful.
So two questions:
1. Is there an easier way - as in am I overlooking some feature I should be using?
2. Is there a better way to manually animate the image?
Find code below of what I'm doing on each tick. The first area of improvement: maybe copy each frame of the image to a list? Note the _image.Dispose(); failing to dispose of a local Image was causing memory leaks.
Thanks for any advice here. I will post something online and link it once I have an efficient solution.
private void TickImage()
{
if (!_stop)
{
_ticks++;
this.SuspendLayout();
Image = null;
if(_image != null)
_image.Dispose();
//Get the animated image from resources and the info
//required to grab a frame
_image = Resources.Progress16;
var dimension = new FrameDimension(_image.FrameDimensionsList[0]);
int frameCount = _image.GetFrameCount(dimension);
//Reset to zero if we're at the end of the image frames
if (_activeFrame >= frameCount)
{
_activeFrame = 0;
}
//Select the frame of the animated image we want to show
_image.SelectActiveFrame(dimension, _activeFrame);
//Assign our frame to the Image property of the button
Image = _image;
this.ResumeLayout();
_activeFrame++;
_ticks--;
}
}
I guess Winforms is not so reach in animation capabilities on its own. If you want more advanced animation use may consider some third-party solutions.
I think you should not load image from resource every tick. The better way is to preload image frames one and hold the reference. Then use it to set appropriate frame every tick.
As I've recently tested, animated gifs are animating well without any additional coding, at least on standard buttons. But if you still need to aminate frames manually, you may try something like this:
// put this somewhere in initialization
private void Init()
{
Image image = Resources.Progress16;
_dimension = new FrameDimension(image.FrameDimensionsList[0]);
_frameCount = image.GetFrameCount(_dimension);
image.SelectActiveFrame(_dimension, _activeFrame);
Image = image;
}
private void TickImage()
{
if (_stop) return;
// get next frame index
if (++_activeFrame >= _frameCount)
{
_activeFrame = 0;
}
// switch image frame
Image.SelectActiveFrame(_dimension, _activeFrame);
// force refresh (NOTE: check if it's really needed)
Invalidate();
}
Another option is to use ImageList property with preloaded static frames and cycle ImageIndex propery just as you do it with SelectActiveFrame above.

Categories