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
};
Related
I am using a UltraExpandableGroupBox in my WinForms application. And I am using the Office2003 style with it. However, I would like to reverse the Expanded and Collapsed Indicator images used. I tried to export the images from the .isl file, but these images don't seems to be among the images exported. How do I access these images?
When the ViewStyle property for the UltraExpandableGroupBox control is set to the GroupBoxViewStyle.Office2003 the Expanded/Collapsed indicator uses an embedded bitmap.
Code below demonstrates how this bitmap can be obtained from the assembly on the runtime and can be used to reverse the current Expanded/Collapsed indicators:
private void ReverseImage_Click(object sender, EventArgs e)
{
var imageName = "GroupBox.ExpansionIndicator_Chevron.bmp";
System.IO.Stream stream = typeof(UltraExpandableGroupBox).Module.Assembly.GetManifestResourceStream(typeof(UltraExpandableGroupBox), imageName);
if (stream != null)
{
// The source bitmap has 7x10px size.
var image = Bitmap.FromStream(stream);
// Converting the image to 16x16 pixels
ultraExpandableGroupBox1.ExpansionIndicatorExpanded = ResizeImage(image, 16, 16);
// Rotation
using (var bmp = new Bitmap(image))
{
bmp.RotateFlip(RotateFlipType.Rotate180FlipNone);
image = bmp.Clone() as Image;
// Exporting bitmap to a file
bmp.Save(#".\" + imageName, ImageFormat.Bmp);
}
ultraExpandableGroupBox1.ExpansionIndicatorCollapsed = ResizeImage(image, 16, 16);
}
}
public static Image ResizeImage(Image image, int new_height, int new_width)
{
var dest = new Bitmap(new_width, new_height);
var g = Graphics.FromImage(dest);
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(image, (dest.Width - image.Width)/2, (dest.Height-image.Height)/2);
return dest;
}
Exported to a file the Expanded/Collapsed indicator bitmap looks like on the picture below:
You can achieve this with simple DrawFilter. Set to your UltraExpandableGroupBox DraFilter property like this:
this.myUltraExpandableGroupBox.DrawFilter = new MyDrawFilter(expandedIndicator, collapsedInidcator);
Then create a new class named MyDrawFilter and let it inherit IUIElementDrawFilter. Your draw filter class may look like this:
public class MyDrawFilter : IUIElementDrawFilter
{
Image expandedIndicator;
Image collapsedIndicator;
public MyDrawFilter(Image expandedIndicator, Image collapsedInidcator)
{
this.expandedIndicator = expandedIndicator;
this.collapsedIndicator = collapsedInidcator;
}
public bool DrawElement(DrawPhase drawPhase, ref UIElementDrawParams drawParams)
{
if (drawParams.Element is GroupBoxExpansionIndicatorUIElement)
{
// if groupbox is expanded change the image with one provided in the constructor
// as expandedIndicator
if ((drawParams.Element.Control as UltraExpandableGroupBox).Expanded)
{
(drawParams.Element.ChildElements[0] as ImageUIElement).Image = this.expandedIndicator;
}
// else gropbox is collapsed change the image with one provided in the constructor
// as collapsedIndicator
else
{
(drawParams.Element.ChildElements[0] as ImageUIElement).Image = this.collapsedIndicator;
}
}
return false;
}
public DrawPhase GetPhasesToFilter(ref UIElementDrawParams drawParams)
{
// filter when GroupBoxExpansionIndicatorUIElement should be drawn. This element has
// one child UIElement of ImageUIElement type. This UIElement holds the expansion
// indicator image.
if (drawParams.Element is GroupBoxExpansionIndicatorUIElement)
{
// we return BeforeDrawChildeElements in order to be able to change the image
return DrawPhase.BeforeDrawChildElements;
}
return DrawPhase.None;
}
}
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();
}
}
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.
Is there any way to determine if two images are identical?
I want to change an image every time my timer ticks (animation).
But, I need to see which image is displaying, so is there any way to compare 2 images
to do what I want?
if (myImage.Flags == (Image.FromFile(#"Images/Enemy.png").Flags))
{
myImage = Image.FromFile(#"Images/Enemy2.png");
}
else
{
myImage = Image.FromFile(#"Images/Enemy.png");
}
Don't compare the images, just maintain the index of the current image in a variable.
Here's an example that works for any number of images:
private int _currentImageIndex;
private string[] _imagePaths =
{
"Images/Enemy.png",
"Images/Enemy2.png",
"Images/Enemy3.png",
};
...
void NextImage()
{
// Dispose the current image
Image img = pictureBox1.Image;
pictureBox1.Image = null;
if (img != null)
img.Dispose();
// Show the next image
_currentImageIndex = (_currentImageIndex + 1) % _imagePaths.Length;
string path = _imagePaths[_currentImageIndex];
pictureBox1.Image = Image.FromFile(path);
}
I'd try to compare ImageLocation. Although it doesn't work if you have your pictures as resources.
if (PictureBox1.ImageLocation == PictureBox2.ImageLocation)
{
}
See my question:
Dynamically changing image in a picturebox
Here goes simple answer.
In case of just 2 images, use flag
// field, true if enemy2.png is loaded
bool _image2;
// somewhere
if(_image2)
{
myImage = Image.FromFile(#"Images/Enemy.png");
_image2 = false;
}
else
{
myImage = Image.FromFile(#"Images/Enemy2.png");
_image2 = true;
}
I have a PictureBox on my Windows Forms application.
I load a picture in it and I have enabled the Paint event in my code. It draws a rectangle.
Like this:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics gr = e.Graphics;
Pen p = new Pen(Color.Red);
p.Width = 5.0f;
gr.DrawRectangle(p, 1, 2, 30, 40);
}
And I click the "save" button:
private void button2_Click(object sender, EventArgs e)
{
pictureBox1.Image.Save(#"C:\Documents and Settings\tr1g3800\Desktop\WALKING\30P\100000test.jpg",ImageFormat.Jpeg);
}
But the saved file never contains the rectangle that I drew.
Does anyone have any idea?
Thanks.Your anwers all helped.
This worked
private void button1_Click(object sender, EventArgs e)
{
pictureBox1.ImageLocation=#"C:\Documents and Settings\tr1g3800\Desktop\WALKING\30P\100000.jpg" ;
}
private void button2_Click(object sender, EventArgs e)
{
pictureBox1.Image.Save(#"C:\Documents and Settings\tr1g3800\Desktop\WALKING\30P\100000test.jpg",ImageFormat.Jpeg);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Image);
Graphics gr = Graphics.FromImage(bmp);
Pen p = new Pen(Color.Red);
p.Width = 5.0f;
gr.DrawRectangle(p, 1, 2, 30, 40);
pictureBox1.Image = bmp;
}
You probably shouldn't draw directly on the PictureBox.
You need to use a Bitmap instead. Try putting the bitmap in the PictureBox.Image and then call Save().
Check this for more details
Here is my solution with additional support to various file types:
public void ExportToBmp(string path)
{
using(var bitmap = new Bitmap(pictureBox.Width, pictureBox.Height))
{
pictureBox.DrawToBitmap(bitmap, pictureBox.ClientRectangle);
ImageFormat imageFormat = null;
var extension = Path.GetExtension(path);
switch (extension)
{
case ".bmp":
imageFormat = ImageFormat.Bmp;
break;
case ".png":
imageFormat = ImageFormat.Png;
break;
case ".jpeg":
case ".jpg":
imageFormat = ImageFormat.Jpeg;
break;
case ".gif":
imageFormat = ImageFormat.Gif;
break;
default:
throw new NotSupportedException("File extension is not supported");
}
bitmap.Save(path, imageFormat);
}
}
Here is a small example that clarified a few things for me (I was struggling with this a bit too).
pBox is a PictureBox on Form1, make it at least 50x50
appPath was derived from System.Reflection but use any path you like
There are two buttons, one for drawing, one for saving, their click events are in the code below.
Things I learned:
(1) "pBox.Image =" doesn't do anything but initialize the pBox image, it DOES NOT have to be a filename as EVERY example I found used (had problem saving to that same file because it was share locked). Also, if your goal is to see things on the entire control's surface, you'll probably like setting the size at initialize time to the size you need. I used the pBox's size in this example but normally I use the bitmap size (because I typically begin with a real picture file).
(2) I always had problems either seeing my draws show up on the control or seeing my changes saved in the output file (or both). In my prior attempts I would duplicate the draws both on the control and on the bitmap. Of course that isn't necessary but the edited bitmap DOES need to be reloaded into the control.image... and THAT was the piece of this puzzle I was missing.
(A) Create a bitmap from the control.image and draw on the bitmap
(B) Load the bitmap into the control.Image (so you can see the changes caused by the draw)
(C) Save the control.Image
(2-option) You have a global (or passed) bitmap (probably from a real file)
(A) Draw on the bitmap
(B) Load the bitmap into the control.Image (so you can see the changes)
(C) Save the bitmap
public Form1()
{
InitializeComponent();
pBox.Image = new Bitmap(pBox.Width, pBox.Height);
}
private void DrawStuff1_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(pBox.Image);
Graphics g = Graphics.FromImage(bmp);
g.FillRectangle(Brushes.Red, 5, 5, 25, 25); //hard-coded size to reduce clutter
pBox.Image = bmp; //this makes your changes visible
}
private void Save_Click(object sender, EventArgs e)
{
pBox.Image.Save(appPath + "SavedImage.bmp");
}
You need paint to image of picture, not to the Graphics control on Paint event.
EDIT:
using( Graphics g = Graphics.FromImage( pictureBox1.Image ) ) {
// there you will be do, what you do in Paint event
}
// ... somewhere else ...
pictureBox1.Save( _required_parameters_ );