Detecting which image is used in an imagebox - c#

I'm trying too make a memory game.
In this game when a button is klicked the button and an picturebox will be send into a List.
I want too use the images inside the pictureboxes as a way too use this code. But even when the two images are the same the code wont work. Is there a way too check the image used like Name.jpg.
if(buttonCount == 2)
{
if(pictureList[0].Image == pictureList[1].Image)
{
buttonCount = 0;
buttonList.RemoveAt(0)
buttonList.RemoveAt(0);
pictureList.RemoveAt(0);
pictureList.RemoveAt(0);
}
}

You could save an Id of the image (or e.g. the filename like you suggested) in the Tag.
So when loading the image into the picture box:
string path = "PATH";
pictureBox.Image = Image.FromFile(path);
pictureBox.Tag = path;
Then you could compare the Tag.
BUT I think (show us how you load the images please) this is not working as it is, because you load the image twice from the disk like:
pictureBox1.Image = Image.FromFile(path);
pictureBox2.Image = Image.FromFile(path);
Because then you have differen instances and so the equals returns false.
If you do it like the following it should also work:
var image = Image.FromFile(path);
pictureBox1.Image = image;
pictureBox2.Image = image;

In your current application, you do not have enough information associated with the image object to identify it. As such, you need to possibly extend the Image class to include this information or store it in some other way for comparison.
Extending Image class
public class GameImage : Image
{
public static GameImage GetImage(string filename)
{
GameImage img = (GameImage)Image.FromFile(filename);
img.FileName = filename;
return img;
}
public string FileName { get; private set; }
}
Then the comparison becomes
if(buttonCount == 2)
{
if(((GameImage)pictureList[0].Image).FileName == ((GameImage)pictureList[1].Image).FileName)
{
buttonCount = 0;
buttonList.RemoveAt(0)
buttonList.RemoveAt(0);
pictureList.RemoveAt(0);
pictureList.RemoveAt(0);
}
}
Note: Note tested!

Related

How to get the width of a photo taken in Xamarin

I have the following code to take a picture in Xamarin:
MediaFile photo = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions()
{
SaveToAlbum = true,
Name = fileName
});
However, after I've taken the picture, I want to retrieve the width of the image. I thought there might be a:
photo.Width
But there is not. There is a PhotoSize property on the StoreCameraMediaOptions, but that appears to be a way to dictate the size, rather than retrieve it.
Is there a way to do this in Xamarin, or an existing plug-in that will accomplish it?
Using FFImageLoading the ImageInformation class gives you the original height & width,
you could assign a mediafile to an image then get the width of that image that rendered the mediafile
var image = new CachedImage()
{
Source = ImageSource.FromStream(() => photo.GetStream())
};
image.Success += (sender, e) =>
{
var h = e.ImageInformation.OriginalHeight;
var w = e.ImageInformation.OriginalWidth;
};
Hope this one might helps.
Here you go this might help you...
public static Size GetImageSize(string fileName)
{
#if __IOS__
UIImage image = UIImage.FromFile(fileName);
return new Size((double)image.Size.Width, (double)image.Size.Height);
#endif
return Size.Zero;
}

How to check the image property of an pictureBox within a form in another form.

I have create a image box which changes the image within it when it is click. It is stored in form A. I now have a form b. I would like to check in form b. if the image in the picture box in form A is equal to a specific image then change the image in a picturebox in form B.
I am have problems accessing the pic box in form A due to I think it being private.
Despite the apparent simple nature of the problem, the correct way to accomplish this is deceptively complex. You may want to rethink the architecture of your application to perform this check another way, such as with an associated ID number or UUID. However, if you do in fact need to perform a content equality check on images in this manner, as follows is a basic solution that I have tested.
Since it would be painfully inefficient for us to directly compare two images to determine their equality, the best solution is to implement a simple hashing algorithm and check that instead. This is the most complicated part of the solution. To perform this automatically and abstract this step away, we can create a simple wrapper class around the standard Image object as follows:
public class ComparableImage
{
public Image Image
{
get { return this.image; }
set { SetImage(value); }
}
public string SHA1
{
get { return this.sha1; }
}
private Image image = null;
private string sha1 = string.Empty;
// This is the important part that lets us
// efficiently compare two images:
public override bool Equals(object image)
{
if ((image != null) && (image is ComparableImage) )
{
return (sha1.Equals(((ComparableImage)image).sha1));
}
else return false;
}
public override int GetHashCode()
{
return sha1.GetHashCode();
}
private void SetImage(Image image)
{
this.image = image;
this.sha1 = ComputeSHA1(image);
}
private static string ComputeSHA1(Image image)
{
if (image != null)
{
var bytes = GetBytes(image);
using (SHA1Managed SHA1 = new SHA1Managed())
{
return Convert.ToBase64String(SHA1.ComputeHash(bytes));
}
}
else return string.Empty;
}
private static byte[] GetBytes(Image image)
{
using (var stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Bmp);
return stream.ToArray();
}
}
}
Using the above class, we can simply call the Equals method to find out if two images are equal in content, without ever having to worry about anything further other than creating ComparableImage objects.
The next issue is exposing a public Image property from each of the forms which enables us to access an instance of ComparableImage. We can easily accomplish this using the following pattern:
public class ComparableImageForm : Form
{
// This is the property we need to expose:
public ComparableImage Image
{
get { return this.image; }
set { SetImage(value); }
}
private ComparableImage image;
private PictureBox pictureBox = new PictureBox()
{
Dock = DockStyle.Fill
};
public ComparableImageForm()
{
this.Controls.Add(pictureBox);
}
// For clarity, we are also setting a picture box image
// from the ComparableImage when it is assigned:
private void SetImage(ComparableImage image)
{
this.image = image;
pictureBox.Image = image.Image;
}
}
Finally, we are ready to load some images do some test comparisons:
// Load two images from file to compare.
// In practice, images can be loaded from anywhere,
// even from the designer.
var image1 = new ComparableImage()
{
Image = Image.FromFile("bitmap1.bmp")
};
var image2 = new ComparableImage()
{
Image = Image.FromFile("bitmap2.bmp")
};
// Create two forms that have picture boxes:
var formA = new ComparableImageForm()
{
Image = image1
};
var formB = new ComparableImageForm()
{
Image = image2
};
// Perform the check to see if they are equal:
if (formA.Image.Equals(formB.Image))
{
MessageBox.Show("The images are indeed equal.");
}
else
{
MessageBox.Show("The images are NOT equal.");
}
// Since images are compared based on their SHA1 hash,
// it does not matter where the image comes from as long
// as the data is the same. Here, we are loading another
// copy of 'bitmap1.bmp':
var anotherImage = new ComparableImage()
{
Image = Image.FromFile("bitmap1.bmp")
};
// The following statement will evaluate as true:
bool isEqual = (anotherImage.Equals(image1));
Thats it!
You should make an instance from your form B. search in controls of that form, find picturebox and change its properties. and show that instance everytime you want to show that form.
It's not a good idea to compare images to detect if they are the same.
It would be better to give every picture an unique ID and store that in a variable. Make sure both forms haven access to that variable, so you can compare it with the ID of the image in form2.

Image Control in Wpf showing previous image which was deleted

I have an image control which is showing the preview image. If the user delete the image (which resides in folder) it should show the newly taken image.
but the image control shows the deleted image instead of showing new image.
// clear the image source before deleting the image.
// save image in the directory
public string globalFilePath;
int imageCount = Directory.GetFiles(imgDir, "*", SearchOption.TopDirectoryOnly).Length;
string filePath = Path.Combine(imgDir, "IMAGE_" + ++imageCount + ".jpeg");
globalFilePath = filePath;
// setting image control source
var strUri = new Uri(WebCamControl.globalFilePath, UriKind.Relative);
previewImage.Source = BitmapFromUri(strUri);
//Method
public static ImageSource BitmapFromUri(Uri source)
{
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = source;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
return bitmap;
}
// delete image
previewImage.Source = null;
if (System.IO.File.Exists(WebCamControl.globalFilePath))
{
System.IO.File.Delete(WebCamControl.globalFilePath);
}
else
{
MessageBox.Show("File Not Exists");
}
After deleting the image in the directory file the image image control should show the new image, but my Image control shows the deleted image. please give me the solution.
In WPF, we generally don't need to use actual BitMapImage objects to display an Image. It's far easier to let the .NET Framework convert our string file paths to the images to the actual Image elements.
Also, it is far better to data bind the Image.Source to a property that implements the INotifyPropertyChanged interface (or a DepenedencyProperty):
<Image Source="{Binding YourImageFilePath}" ... />
Then, whenever a file path of a new image is set to the YourImageFilePath property, your displayed image will update immediately.
YourImageFilePath = filePath;
Try This one:
string path = ((BitmapImage)img.Source).UriSource.LocalPath;
img.SetValue(System.Windows.Controls.Image.SourceProperty, null);
File.Delete(path);
OR
string path = ((BitmapImage)img.Source).UriSource.LocalPath;
img.Source = null;
File.Delete(path)

How to get image file name in a textbox?

I have a problem about C# file name. I show some pictures with PictureBox. Also I want to write picture's name in a TextBox. I search fileinfo, directoryinfo, but it doesnt work.
List<Image> images = new List<Image>();
images.Add(Properties.Resources.baseball_bat);
images.Add(Properties.Resources.bracelet);
images.Add(Properties.Resources.bride);
pictureBox1.Image = images[..];
and i want to write baseball_bat, bride, bracelet etc. in a TextBox. What can I do? any offer?
Well, one of the simplest methods is saving both the name and the image in a List<KeyValuePair<string,Image>> or IDictionary<string,image>.
Here's an example using a IDictionary<string,image>
(I decided for SortedList<> because of the indexing) :
var images = new SortedList<string, Image>();
images.Add("baseball_bat", Properties.Resources.baseball_bat);
images.Add("bracelet", Properties.Resources.bracelet);
...
// when you show the first image...
pictureBox1.Image = images.Values[0];
textBox1.Text = images.Keys[0];
// when you show the nth image...
pictureBox1.Image = images.Values[n];
textBox1.Text = images.Keys[n];
For a List<KeyValuePair<string,Image>> would be:
var images = new List<KeyValuePair<string, Image>>();
images.Add(new KeyValuePair<string,Image>("baseball_bat", Properties.Resources.baseball_bat));
images.Add(new KeyValuePair<string,Image>("bracelet", Properties.Resources.bracelet));
...
// when you show the first image...
pictureBox1.Image = images[0].Values;
textBox1.Text = images[0].Keys;
// when you show the nth image...
pictureBox1.Image = images[n].Values;
textBox1.Text = images[n].Keys;
This functionality is already built in...
Image lists store their images in a way that you can reference them by name and return the image.
Single use :
private string GetImageName(ImageList imglist, int index)
{
return imglist.Images.Keys[index].ToString();
}
This returns the name of the image at the passed index
Store values for later on :
private Dictionary<int, string> GetImageNames(ImageList imglist)
{
var dict = new Dictionary<int, string>();
int salt = 0;
foreach (var item in imglist.Images.Keys)
{
dict.Add(salt, item.ToString());
salt++;
}
return dict;
}
This returns a dictionary that references the index of picture to their string name in the image list.
Once again this is built in there is no need to try to extend funct. to it...
You can get all the resources along with their keys (names of the resources) by using reflection:
//a helper dictionary if you want to save the images and their names for later use
var namesAndImages = new Dictionary<String, Image>();
var resourcesSet = Properties.Resources.ResourceManager.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
foreach (System.Collections.DictionaryEntry myResource in resourcesSet)
{
if (myResource.Value is Image) //is this resource is associated with an image
{
String resName = myResource.Key.ToString(); //get resource's name
Image resImage = myResource.Value as Image; //get the Image itself
namesAndImages.Add(resName, resImage);
}
}
//now you can use the values saved in the dictionary and easily get their names
...
Update: I've updated the code to save the values in a dictionary, so you can conveniently use them later.

Saving a scrollable panel as PDF using .NET

I have a Panel filled with a lot of controls for users to fill. These include textboxes, checkboxes, radiobuttons etc. It is a long form to fill so the controls are in a scrollable panel. What I need is to save the whole panel as pdf. I think PDFsharp is a good library to be able to save any text or image as a pdf file but I don't want to write code for every single control inside the panel. I once wrote a class to create a pdf file from a Control object. It was iterating all inner controls (and their inner controls until no inner control is left) of the given control and write their Text property (yes/no for chekable controls) to pdf using their Location and Size properties. I could not find it now but I remember it was having issues with some of the DevExpress controls I use so I didn't bother writing it again. (Edit: I had to, you can find it below.) I think taking a screenshot and save that image as pdf would be nice but I couldn't find out how to achieve it. This question seems like it but there is no satisfying answer to that.
So, screenshot or not I'm open for any advice. There should be many occasions where users must fill long forms and be able to keep it as pdf. Again, any advice or workaround would be appreciated. (I think about creating the form using html, displaying it in a WebBrowser control and using an html to pdf library but I really prefer using my existent form)
Many Thanks.
Edit:
I had to write something iterates inner controls of a container control (like a panel) and writes every inner control to a pdf using their Location, Size and Font properties though, I don't recommend to use it (at least as it is) because of these:
It sets the page's size to given control's size and use only one (usually huge) pdf page. You can add a logic to split it to pages if you need to. (I didn't, but I guess you'll probably need your pdf more printer friendly).
Cheeso's method (using a FlowDocument) is a much more "legitimate" way for a task like this. I prefer using that over this but I didn't have a choice in this instance.
I used PDFsharp in this code. You can find it in it's hompage or it's CodePlex page.
PdfReport class:
private PdfDocument Document;
public Control Control { get; private set; }
public PdfReport(Control control) { Control = control; }
public PdfDocument CreatePdf(PdfDocument document = null)
{
Document = document != null ? document : new PdfDocument();
PdfPage page = Document.AddPage();
page.Height = Control.Height;
page.Width = Control.Width;
XGraphics gfx = XGraphics.FromPdfPage(page);
foreach (PdfItem item in CreatePdf(new Point(0, 0), Control.Controls))
{
XStringFormat format = item.IsContainer ? XStringFormats.TopLeft : item.TextAlign == ContentAlignment.BottomCenter ? XStringFormats.BottomCenter : item.TextAlign == ContentAlignment.TopLeft ? XStringFormats.TopLeft : item.TextAlign == ContentAlignment.TopCenter ? XStringFormats.TopCenter : XStringFormats.Center;
gfx.DrawString(item.Text, item.Font, item.Brush, new XRect(item.Location, item.Size), format);
}
return Document;
}
private IEnumerable<PdfItem> CreatePdf(Point location, Control.ControlCollection controls)
{
List<PdfItem> items = new List<PdfItem>();
foreach (Control control in controls)
{
if (control.Controls.Count > 0)
items.AddRange(CreatePdf(control.Location, control.Controls));
items.Add(new PdfItem(control, location));
}
return items;
}
public void SaveAsPdf(string path, bool open = false)
{
CreatePdf().Save(path);
if (open)
Process.Start(path);
}
PdfItem class:
public string Text { get; set; }
public Point Location { get; set; }
public Size Size { get; set; }
public Font Font { get; set; }
public bool IsContainer { get; set; }
public ContentAlignment TextAlign { get; set; }
public Color ForeColor { get; set; }
public XBrush Brush { get { return new SolidBrush(ForeColor); } }
public PdfItem() { }
public PdfItem(string text, Point location, Font font, Color foreColor, Size size, bool isContainer = false, ContentAlignment alignment = ContentAlignment.MiddleCenter)
{
Text = text;
Location = location;
Size = size;
Font = new Font(font.FontFamily, font.Size, font.Style, GraphicsUnit.World);
TextAlign = alignment;
ForeColor = foreColor;
IsContainer = isContainer;
}
public PdfItem(string text, Point location, Size size)
: this(text, location, new Font("Calibri", 12), Color.Black, size) { }
public PdfItem(Control control, Point parentLocation)
: this(control.Text, control.Location, control.Font, control.ForeColor, control.Size, control.Controls.Count > 0)
{
Location = new Point(Location.X + parentLocation.X, Location.Y + parentLocation.Y);
IEnumerable<PropertyInfo> properties = control.GetType().GetProperties();
if (properties.FirstOrDefault(p => p.Name == "TextAlign" && p.PropertyType == typeof(ContentAlignment)) != null)
TextAlign = (control as dynamic).TextAlign;
if (properties.FirstOrDefault(p => p.Name == "Checked" && p.PropertyType == typeof(bool)) != null)
{
string title = control.Text != null && control.Text.Length > 0 ? string.Format("{0}: ", control.Text) : string.Empty;
Text = string.Format("{0}{1}", title, (control as dynamic).Checked ? "Yes" : "No");
}
}
Regarding
. I think taking a screenshot and save that image as pdf would be nice but I couldn't find out how to achieve it.
There is a tool called "cropper" available on codeplex.com. It is designed to be used as a user tool that can take screenshots. It is managed code, open source.
I can imagine embedding some of the cropper magic into your app so that you could take that screenshot. I can also imagine this would be useful for collecting a diagnostic image of the screen at the time of a problem.
On the other hand... if you are interested in producing a printed form that reproduces the content on the screen, then I think you should be using WPF, in which case doing what you want is pretty easy. For example, this question describes how to do a print-preview for a FlowDocument. From that point your user can print to PDF (if he has a PDF printer installed) or print to XPS, or print to a physical output device, and so on.
I don't know if this would help you or not, but DocRaptor.com's pdf api could be built in so it would do it for you, no matter what the user inputs. It uses basic html.
As you can use the below :)
YourPanel.AutoSize = true;
int width = YourPanel.Size.Width;
int height = YourPanel.Size.Height;
Bitmap bm = new Bitmap(width, height);
YourPanel.DrawToBitmap(bm, new Rectangle(0, 0, width, height));
string outputFileName = #"C:\YourDirectory/myimage.bmp";
using (MemoryStream memory = new MemoryStream())
{
using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
{
bm.Save(memory, ImageFormat.Bmp);
Clipboard.SetImage(bm);
byte[] bytes = memory.ToArray();
fs.Write(bytes, 0, bytes.Length);
}
}
YourPanel.AutoSize = false;
The Clipboard.SetImage will send you bm to the clipboard so you can paste them to your pdf form or whatever document
This also has an example built in that saves it as a image for you if you want.
The trick here is Autosize for your panel. It needs to be set to true so the panel resizes itself as a whole area visible, then right after you do your work you can resize it to false so it uses scrollbars again for the users screen (you may see it flash for half a second, but this code does work.
Saving it in a PDF I personally just prefer to write it there as my clipboard or you can write byte. But ITextSharp is a great library for the extension to work with!
I Really hope this helps.

Categories

Resources