How to show a specific frame of a GIF image in C#? - c#

I want to show a frame of a gif image. I searched and found that the following code should work, but it doesn't work. it detects the number of frames correctly but it shows the whole frames of gif instead of the specified frame. thanks everybody.
Image[] frames = new Image[36];
Image GG = Image.FromFile(#"C:\Users\Administrator\TEST C#\TEST2frame2\chef.gif");
FrameDimension dimension = new FrameDimension(GG.FrameDimensionsList[0]);
// Number of frames
int frameCount = GG.GetFrameCount(dimension);
label1.Text = frameCount.ToString();
// Return an Image at a certain index
GG.SelectActiveFrame(dimension, 1);
frames[1] = ((Image)GG.Clone());
pictureBox1.Image = frames[1];

Use your own code up until the call of SelectActiveFrame() and after that change to this lines:
frames[0] = new Bitmap(GG);
pictureBox1.Image = frame[0];
This should do the trick. Please do not forget do dispose the created Images.

Oh it works, but not as you expect it to.
When you set an active frame of a gif image it actually restarts its animation from that frame. You have to stop it when you change a frame, by setting the pictureBox.IsEnabled to false, for instance. Try the following code
private Image img;
public Form1()
{
InitializeComponent();
img = Image.FromFile(#"C:\Users\Administrator\TEST C#\TEST2frame2\chef.gif");
pictureBox1.Image = img;
}
private void button1_Click(object sender, EventArgs e)
{
var dim = new FrameDimension(img.FrameDimensionsList[0]);
img.SelectActiveFrame(dim, 1);
pictureBox1.Enabled = false;
}
Try pressing the button in different moments and you will see that the active image frame will change.

Related

C# PictureBox with animated GIF skips Frames

i have the Problem that my animated gif i used as IMAGE Value in my PictureBox Control is shown slower than showing in Explorer.
I'm using C# Winforms.
Problem here should be that some frames are skipped in execution.
Can someone confirm this issue and maybe have a solution for that?
My Picture Box is for Preloading and works fully in Background Thread.
Is it maybe possible to read the Frames one by one from the gif and animate it selfmade to picturebox?
Thanks!
Use this code. Since 25 frames per second is displayed, I set the timer to 40, which means one frame every 40 milliseconds. (1000ms / 25 frames = 40ms)
step 1. This method shows how to use
static Image[] images;
int frameCount = 0;
private void Btn_Click(object sender, EventArgs e)
{
//get gif image
object ezgif_com_video_to_gif = Resources.ResourceManager.GetObject("ezgif_com_video_to_gif");
images = getFrames((Image)ezgif_com_video_to_gif);//convert to frames array
//show frames
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 40;
timer.Elapsed += Timer_Elapsed;
timer.Start();
}
step 2. add timer tick
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
pictureBox1.Image = images[frameCount];
frameCount++;
if (frameCount > images.Length - 1)
frameCount = 0;
}
step 3. convert gif to frames
Image[] getFrames(Image originalImg)
{
int numberOfFrames = originalImg.GetFrameCount(FrameDimension.Time);
Image[] frames = new Image[numberOfFrames];
for (int i = 0; i < numberOfFrames; i++)
{
originalImg.SelectActiveFrame(FrameDimension.Time, i);
frames[i] = ((Image)originalImg.Clone());
}
return frames;
}

Print high quality Tiff documents from picturebox C#

I'm using WinForms. My program opens .Tiff image documents into a picturebox. The problem I'm having is printing high quality tiff images from the picturebox. I've tried and tested printing many times. When the document prints the words are not crisp/clear its a little blurry. I tested my printer also to check if there was a problem with my printer. I printed a regular text document using Microsoft word and it printed out clearly, so its an issue with my code.
Can someone provide me with the code to print in high quality .tiff images in my picturebox? Would I need to increase my DPI programmatically to increase the quality of the image?
This is my code.
private void DVPrintDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
e.Graphics.DrawImage(pictureBox1.Image, 25, 25, 800, 1050);
}
private void Print_button_Click(object sender, EventArgs e)
{
PrintPreviewDialog.Document = PrintDocument;
PrintPreviewDialog.ShowDialog();
}
After analyzing my code further, I think I figured out why my pictures are turning out blurry. When I open a Tiff document, I have in my form a back, and forward button for the multiple tiff pages. In the RefreshImage method, I think that’s where my images are turning blurry.
Here is my code:
private int intCurrPage = 0; // defining the current page (its some sort of a counter)
bool opened = false; // if an image was opened
//-------------------------------------Next and Back Button-------------------------------------------------
private void btn_Back_Click(object sender, EventArgs e)
{
if (opened) // the button works if the file is opened. you could go with button.enabled
{
if (intCurrPage == 0) // it stops here if you reached the bottom, the first page of the tiff
{ intCurrPage = 0; }
else
{
intCurrPage--; // if its not the first page, then go to the previous page
RefreshImage(); // refresh the image on the selected page
}
}
}
private void btn_Next_Click(object sender, EventArgs e)
{
if (opened) // the button works if the file is opened. you could go with button.enabled
{
if (intCurrPage == Convert.ToInt32(lblNumPages.Text)) // if you have reached the last page it ends here
// the "-1" should be there for normalizing the number of pages
{ intCurrPage = Convert.ToInt32(lblNumPages.Text); }
else
{
intCurrPage++;
RefreshImage();
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
var bm = new Bitmap(pictureBox1.Image);
bm.SetResolution(600, 600);
Image image1 = new Bitmap(bm);
pictureBox1.Image = image1;
pictureBox1.Refresh();
}
public void RefreshImage()
{
Image myImg; // setting the selected tiff
Image myBmp; // a new occurance of Image for viewing
myImg = System.Drawing.Image.FromFile(#lblFile.Text); // setting the image from a file
int intPages = myImg.GetFrameCount(System.Drawing.Imaging.FrameDimension.Page); // getting the number of pages of this tiff
intPages--; // the first page is 0 so we must correct the number of pages to -1
lblNumPages.Text = Convert.ToString(intPages); // showing the number of pages
lblCurrPage.Text = Convert.ToString(intCurrPage); // showing the number of page on which we're on
myImg.SelectActiveFrame(System.Drawing.Imaging.FrameDimension.Page, intCurrPage); // going to the selected page
myBmp = new Bitmap(myImg, pictureBox1.Width, pictureBox1.Height); // setting the new page as an image
// Description on Bitmap(SOURCE, X,Y)
pictureBox1.Image = myBmp; // showing the page in the pictureBox1
}
myBmp = new Bitmap(myImg, pictureBox1.Width, pictureBox1.Height);
pictureBox1.Image = myBmp;
Look no further, you are rescaling the image to fit the picture box. That throws away lots of pixels in the source image, the picture box is a lot smaller than the image. The aspect ratio is only correct by accident btw.
Simplest way is to just not rescale it yourself and leave it up to the PictureBox control to do it. Albeit that it makes painting slow. The other way is to simply keep a reference to the original image. Just use a variable instead of the PictureBox.Image property.
Try this code which transforms the context of the PictureBox into Bitmap image and let you choose in which device the printing may occur:
private void myPrintDocument_PrintPage(System.Object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap myBitmap1 = new Bitmap(myPicturebox.Width, myPicturebox.Height);
myPicturebox.DrawToBitmap(myBitmap1, new Rectangle(0, 0, myPicturebox.Width, myPicturebox.Height));
e.Graphics.DrawImage(myBitmap1, 0, 0);
myBitmap1.Dispose();
}
private void btnPrintPicture_Click(object sender, EventArgs e)
{
System.Drawing.Printing.PrintDocument myPrintDocument1 = new System.Drawing.Printing.PrintDocument();
PrintDialog myPrinDialog1 = new PrintDialog();
myPrintDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(myPrintDocument2_PrintPage);
myPrinDialog1.Document = myPrintDocument1;
if (myPrinDialog1.ShowDialog() == DialogResult.OK)
{
myPrintDocument1.Print();
}
}

Select an image from rectangle using writeablebitmap

I have written an application in silverlight, I am placing a rectangle on the image and want to select the part of image covered by rectangle and show it on a image control on click of a button.
I am not good at handling ratios and image manipulation things, so I am unable to get it right way.
The code for the same goes as below, and would appreciate, if anyone could suggest me a way or solution to get around with this.
public void CaptureImage(object sender, RoutedEventArgs e)
{
BitmapImage bitmapImage = new BitmapImage();
//// bitmapImage.CreateOptions = BitmapCreateOptions.None;
bitmapImage = NewImage;
////calculate bounding box
int originalWidth = bitmapImage.PixelWidth;
int originalHeight = bitmapImage.PixelHeight;
int newSmallWidth = (int)SquareBlue.Width;
int newSmallHeight = (int)SquareBlue.Height;
////generate temporary control to render image
Image temporaryImage = new Image { Source = bitmapImage, Width = newSmallWidth, Height = newSmallHeight };
////create writeablebitmap
WriteableBitmap wb = new WriteableBitmap(newSmallWidth, newSmallHeight);
TranslateTransform t = new TranslateTransform();
t.X = -5;
t.Y = -5;
wb.Render(temporaryImage, t);
wb.Invalidate();
myImage.Source = wb;
}
Whenever this code gets executed, whole image gets snapped, instead of the part selected by rectangle. Could anyone, guide me as what I am doing wrong here.
I'd recommend that you use the Crop method the WriteableBitmapEx library provides.

Image Slider in C#?

I want to create a simple image slideshow, when the timer switch, it will switch to the next index of the picturebox (and will loop) but with a fade effect. How can it be done in C#?
Current Code doesn't switch images? And also - how can I create the fade ffect?
I created a simple timer with 5,000ms interval, enabled it on start.
private void timerImage_Tick(object sender, EventArgs e)
{
if (pictureBox1.Image.Equals(InnovationX.Properties.Resources._1))
{
pictureBox1.Image = InnovationX.Properties.Resources._2;
}
else if (pictureBox1.Image.Equals(InnovationX.Properties.Resources._2))
{
pictureBox1.Image = InnovationX.Properties.Resources._3;
}
else
{
pictureBox1.Image = InnovationX.Properties.Resources._1;
}
}
You can't compare Bitmap loaded from resource in this manner. Every time you get image from resource (in your case using property InnovationX.Properties.Resources._1) you will get new instance of Bitmap class. Comparing two different instances of Bitmap classes will always result in false, even if they contains same image.
Bitmap a = InnovationX.Properties.Resources._1; // create new bitmap with image 1
Bitmap b = InnovationX.Properties.Resources._1; // create another new bitmap with image 1
bool areSameInstance = a == b; // will be false
If you load you images from resources to member variables (e.g. in Load event).
// load images when you create a form
private Bitmap image1 = InnovationX.Properties.Resources._1;
private Bitmap image2 = InnovationX.Properties.Resources._2;
private Bitmap image3 = InnovationX.Properties.Resources._3;
// assing and compare loaded images
private void timerImage_Tick(object sender, EventArgs e)
{
if (pictureBox1.Image == image1)
{
pictureBox1.Image = image2;
}
else if (pictureBox1.Image == image2)
{
pictureBox1.Image = image3;
}
else
{
pictureBox1.Image = image1;
}
}
And after that, rewrite that code using array :)
Image[] images = new {
InnovationX.Properties.Resources._1,
InnovationX.Properties.Resources._2,
InnovationX.Properties.Resources._3
};

c# using Microsoft.DirectX.AudioVideoPlayback how to play next video after one is finished

i am able to put a video in my windows form.
my question is how do i make it when it finishes playing the video,it starts to play another video? meaning like in a sequence. after it finishes, play another video.
so far i have manage to play a video and it just loops the video.
any ideas?
this is my code so far:
public partial class Form1 : Form
{
Video video;
public Form1()
{
InitializeComponent();
Initializevid1();
}
public void Initializevid1()
{
// store the original size of the panel
int width = viewport.Width;
int height = viewport.Height;
// load the selected video file
video = new Video("C:\\Users\\Dave\\Desktop\\WaterDay1.wmv");
// set the panel as the video object’s owner
video.Owner = viewport;
// stop the video
video.Play();
video.Ending +=new EventHandler(BackLoop);
// resize the video to the size original size of the panel
viewport.Size = new Size(width, height);
}
private void BackLoop(object sender, EventArgs e)
{
//video.CurrentPosition = 0;
}
When playing video sequences in AudioVideoPlayback:
Create a list of videos to be displayed (using file paths), preferably in a listbox.
Use an integer to get file path from the listbox.items index.
Ensure video is disposed before loading next video.
Increment integer every time a video is played.
Use an if statement to see if it is the end of the sequence.
As a personal preference (not sure how much difference it makes) I would resize video before playing
So from your code: (haven't tested this, but in theory, I think it should work)
public partial class Form1 : Form
{
Video video;
Int SeqNo = 0;
public Form1()
{
InitializeComponent();
Initializevid1();
}
public void Initializevid1()
{
// store the original size of the panel
int width = viewport.Width;
int height = viewport.Height;
// load the selected video file
video = new Video(listbox1.Items[SeqNo].Text);
// set the panel as the video object’s owner
video.Owner = viewport;
// resize the video to the size original size of the panel
viewport.Size = new Size(width, height);
// stop the video
video.Play();
// start next video
video.Ending +=new EventHandler(BackLoop);
}
private void BackLoop(object sender, EventArgs e)
{
// increment sequence number
SeqNo += 1; //or '++SeqNo;'
//check video state
if (!video.Disposed)
{
video.Dispose();
}
//check SeqNo against listbox1.Items.Count -1 (-1 due to SeqNo is a 0 based index)
if (SeqNo <= listbox1.Items.Count -1)
{
// store the original size of the panel
int width = viewport.Width;
int height = viewport.Height;
// load the selected video file
video = new Video(listbox1.Items[SeqNo].Text);
// set the panel as the video object’s owner
video.Owner = viewport;
// resize the video to the size original size of the panel
viewport.Size = new Size(width, height);
// stop the video
video.Play();
// start next video
video.Ending +=new EventHandler(BackLoop);
}
}
You can use the same video object created earlier to open the second video file in the BackLoop() function.
So, the code should look like something this:
private void BackLoop(object sender, EventArgs e)
{
video.Open("C:\\Users\\Dave\\Desktop\\WaterDay2.wmv", true);
}
I used this post to adapt it to my needs and this was my solution:
Video _SegaVideo;
Video _IntroVideo;
public _FrmMain()
{
InitializeComponent();
_SegaVideo = new Video(#"video\SEGA.AVI");
_SegaVideo.Owner = _VideoPanel;
_SegaVideo.Play();
_SegaVideo.Ending += new EventHandler(_SegaVideoEnding);
}
private void _SegaVideoEnding(object sender, EventArgs e)
{
_IntroVideo = new Video(#"video\INTRO.AVI");
_IntroVideo.Owner = _VideoPanel;
_IntroVideo.Play();
}

Categories