I would like to browse an image from form window. Also I created a class and created some filters. I can read this image from form.
My goal is declare it in my class. And use this image in everywhere. But I don't know how can I do this.
private void btn_BROWSE_Click(object sender, EventArgs e)
{
OpenFileDialog imge = new OpenFileDialog();
imge.Filter = "Extensions |*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff|"
+ "BMP|*.bmp|GIF|*.gif|JPG|*.jpg;*.jpeg|PNG|*.png|TIFF|*.tif;*.tiff|"
+ "Zip Files|*.zip;*.rar";
imge.ShowDialog();
string imgepath = imge.FileName;
pBox_SOURCE.ImageLocation = imgepath;//i'm browsing an image
}
private void sliderKernel_MouseUp(object sender, MouseEventArgs e)
{
Bitmap OriginalImage = new Bitmap(pBox_SOURCE.Image);
}
class Filters
{
// (i would like to initialize my image in here not in form :) )
}
I would define an abstract class Filter and implement every filter as an heir of that class.
public abstract class Filter
{
public Bitmap Image { get; set; }
public abstract void Apply();
}
An implementation would be:
public class SliderKernel : Filter
{
public overrides void Apply()
{
//manipulates the Image property
}
}
If you want to use that image everywhere you should declare it as a static member of a class:
public static class ImageContainer
{
public static Bitmap Image { get; set; }
}
You can use all this in your form code like this:
private void btn_BROWSE_Click(object sender, EventArgs e)
{
OpenFileDialog imge = new OpenFileDialog();
imge.Filter = "Extensions |*.bmp;*.jpg;*.jpeg;*.png;*.tif;*.tiff|"
+ "BMP|*.bmp|GIF|*.gif|JPG|*.jpg;*.jpeg|PNG|*.png|TIFF|*.tif;*.tiff|"
+ "Zip Files|*.zip;*.rar";
imge.ShowDialog();
string imgepath = imge.FileName;
pBox_SOURCE.ImageLocation = imgepath;//i'm browsing an image
//save the image to the container
ImageContainer.Image = new Bitmap(pBox_SOURCE.Image);
}
private void sliderKernel_MouseUp(object sender, MouseEventArgs e)
{
Filter filter = new SliderKernel () { Image = ImageContainer.Image };
filter.Apply();
}
I think you should turn the image into a byte array
using the following code and store it in a static class
public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
using (var ms = new MemoryStream())
{
imageIn.Save(ms,imageIn.RawFormat);
return ms.ToArray();
}
}
https://www.codeproject.com/Articles/15460/C-Image-to-Byte-Array-and-Byte-Array-to-Image-Conv
And use this code to turn into a graphic to display in pictureBox
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
Related
I am creating a BlackJack game and I'm currently having a problem displaying the card image needed on my list.
I have added all 52 card to my resource file and I can't seem to have them displayed in a PictureBox.
Am I going about the right way?
My Card class:
internal class Card
{
public int Value { get; set; }
public string Name { get; set; }
public string Image { get; set; }
public Card(int value, string name, string image)
{
Value = value;
Name = name;
Image = image;
}
}
Main Form:
public partial class Form1 : Form
{
static List<Card> myListOfCards = new List<Card>();
static List<Card> dealersHand = new List<Card>();
static List<Card> playersHand = new List<Card>();
private void startButton_Click(object sender, EventArgs e)
{
//Clubs
myListOfCards.Add(new Card(2, "Two of Clubs", "Resources._2C.png"));
}
}
I've spotted a potential issue. Your code uses "Resources._2C.png" as a literal, and the Card class deals with it as a string. One way or another an Image must be retrieved from the resources of the Assembly and I don't see any code that does that.
Try this change:
class Card
{
// METHOD 1
// CTor with Image
public Card(int value, string name, Image image)
{
Value = value;
Name = name;
Image = image;
}
// METHOD 2
// CTor with string
// The `BuildAction` property for the image files must
// be set to `EmbeddedResource` for this version to work.
public Card(int value, string name, string resource)
{
Value = value;
Name = name;
Image = Image.FromStream(
typeof(Card)
.Assembly
.GetManifestResourceStream(resource));
}
public int Value { get; }
public string Name { get; }
// Try making this an Image
public Image Image { get; }
}
In the MainForm:
The image can either be read from the Resource file by removing the quotes and the extension:
// METHOD 1
private void buttonCard1_Click(object sender, EventArgs e)
{
var card = new Card(1, "AceOfDiamonds", Resources.AceOfDiamonds);
pictureBox1.Image = card.Image;
}
OR if the string is used, it must be fully qualified:
// METHOD 2
private void buttonCard2_Click(object sender, EventArgs e)
{
// Get full names of available resources
Debug.WriteLine(
string.Join(
Environment.NewLine,
typeof(MainForm).Assembly.GetManifestResourceNames()));
var card = new Card(2, "EightOfSpades", "resources.Images.EightOfSpades.png");
pictureBox1.Image = card.Image;
}
Gets this in the PictureBox:
FYI: Here are the available embedded resources listed by the Debug.WriteLine:
I just wrote thsi code to have an access to images
private Bitmap[] hi = { HangmanUrdu.Properties.Resources._4, HangmanUrdu.Properties.Resources._5, HangmanUrdu.Properties.Resources._6, HangmanUrdu.Properties.Resources._7, HangmanUrdu.Properties.Resources._8, HangmanUrdu.Properties.Resources._9, HangmanUrdu.Properties.Resources._10 };
but when i want to increment the index and get these images in my picture box
// wg is just a counter;
pictureBox1.Image = hi { wg}; i
t throws me an error saying
cannot implicitly convert Bitmap to images
I also tried to change my array from bitmap to image but then it shows me error that cannot convert Images to Images.
Create a List<Bitmap> - as a Field, here - or any other type that fits the design (a class property, for example).
Fill the List<Bitmap> in a Form's constructor with the Bitmap objects needed in that context, creating a new Bitmap from the resource object:
private List<Bitmap> hi = null;
public Form1()
{
InitializeComponent();
this.hi = new List<Bitmap>()
{
new Bitmap(Properties.Resources._4),
new Bitmap(Properties.Resources._5)
};
}
The assign a Bitmap to a control's Image property when you need to:
pictureBox1.Image = hi[1];
You could also build a specialized class that hold these references, so you can access them with different naming conventions.
For example:
private List<BitmapResource> BitmapResources = null;
public Form1()
{
InitializeComponent();
this.BitmapResources = new List<BitmapResource>()
{
new BitmapResource(new Bitmap(Properties.Resources._4), "Logo"),
new BitmapResource(new Bitmap(Properties.Resources._5), "Watermark")
};
}
internal class BitmapResource
{
public BitmapResource(Bitmap bitmap, string imageName)
{
this.Image = bitmap;
this.Name = imageName;
}
public Bitmap Image { get; private set; }
public string Name { get; private set; }
}
Then, when needed:
By index:
pictureBox1.Image = BitmapResources[0].Image;
By name (simplified):
pictureBox1.Image = BitmapResources.FirstOrDefault(res => res.Name == "Logo").Image;
My main goal is to load an image from a server and while the loading process is running I would like to show a placeholder instead of the real image.
For reaching this goal I am using C# and Windows Forms. I have to use the proxy pattern and C# background worker which means the loading and the view are using different threads.
I know there are already examples of using proxy pattern for image loading but I have not found any solution which uses a background worker for loading images from a server.
I have already implemented the core functionality but I am now stucking at the question: When the image is fully loaded and therefore the background worker has done his job, how can I force my picture box to load the real image.
My design looks like this:
public class MyPictureBox : PictureBox
{
AbstractImage myImage;
public MyPictureBox(AbstractImage image) : base()
{
this.myImage = image;
}
}
public abstract class AbstractImage
{
protected readonly String url;
public AbstractImage(String url)
{
this.url = url;
}
public abstract Image getImage();
}
public class RealImage : AbstractImage
{
private Image img;
public RealImage(String url) : base(url)
{
}
public override Image getImage()
{
if (img == null)
{
WebRequest requestPic = WebRequest.Create(url);
WebResponse responsePic = requestPic.GetResponse();
img = Image.FromStream(responsePic.GetResponseStream());
}
return img;
}
}
public class ProxyImage : AbstractImage
{
private readonly Image Dummy = Image.FromFile("Waiting.jpg");
private readonly RealImage realImage;
public readonly BackgroundWorker bgw;
private bool done = false;
public ProxyImage(String url) : base(url)
{
realImage = new RealImage(url);
bgw = new BackgroundWorker();
bgw.WorkerReportsProgress = true;
bgw.DoWork += new DoWorkEventHandler(loadImage);
bgw.RunWorkerAsync();
}
public void loadImage(object sender, DoWorkEventArgs e)
{
Console.WriteLine("Loading file" + url);
realImage.getImage();
Console.WriteLine("Finished loading file " + url);
done = true;
bgw.ReportProgress(100);
}
public override Image getImage()
{
return done ? realImage.getImage() : Dummy;
}
}
public partial class Form1 : Form
{
private String urlPrefix = "http://...";
String[] filenames = { "Penguins.jpg", "Koala.jpg", "Desert.jpg"};
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_Shown(object sender, EventArgs e)
{
ProxyImage image = new ProxyImage(urlPrefix + filenames[0]);
MyPictureBox pb = new MyPictureBox(image);
pb.Image = image.getImage();
pb.SizeMode = PictureBoxSizeMode.Zoom;
pb.Size = new Size(200, 200);
pb.Location = new Point(0, 0);
Controls.Add(pb);
}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
At the moment the picture box only shows the dummy image because the background worker has loaded the image but doesn't inform the picture box to use this instead of the dummy image.
I would be glad if anyone could tell my how to set the real image as image of the picture box.
Here is the code as it now stands, I will include all of the code of the program as I left some bits out before. The bits I have changed due to your help I have emphasized with asterisks and ///
The first class is the standard one created from Windows Forms when directly editing your form.
namespace DistanceEstimatorFinal
{
public partial class Form1 : Form
{
private bool saved;
public Form1()
{
dataPoints mydataPoints = new dataPoints();
InitializeComponent();
dataPoint a = mydataPoints.getItem(0);
latTextBox.Text = a.CurLatitude;
longTextbox.Text = a.CurLongtitude;
eleTextBox.Text = a.CurElevation;
saved = true;
}
private void latTextBox_TextChanged(object sender, EventArgs e)
{
}
private void openDataListToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "CSV files (*.csv)|*.csv|Text files ( *.txt)|*.txt |All files (*.*)|*.*";
if (ofd.ShowDialog(this).Equals(DialogResult.OK))
{
*var dp = new dataPoints (ofd.FileName);* /////
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (saved)
{
if (MessageBox.Show("Save?", "Data Not Saved", MessageBoxButtons.YesNo).Equals(DialogResult.Yes))
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.ShowDialog();
}
}
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog sfd1 = new SaveFileDialog();
sfd1.Filter = "CSV files (*.csv)|*.csv|Text files ( *.txt)|*.txt |All files (*.*)|*.*";
sfd1.ShowDialog();
}
}
}
This class was designed to read in the data from a file, I am currently adapting it to read in a file from the open function.
namespace DistanceEstimatorFinal
{
public class dataPoints
{
List<dataPoint> Points;
string p;
public dataPoints(string path)
{
p = path;
Points = new List<dataPoint>();
StreamReader tr = new StreamReader(p);
string input;
while ((input = tr.ReadLine()) != null)
{
string[] bits = input.Split(',');
dataPoint a = new dataPoint(bits[0],bits[1],bits[2]);
Points.Add(a);
}
tr.Close();
}
internal dataPoint getItem(int p)
{
if (p < Points.Count)
{
return Points[p];
}
else
return null;
}
}
}
This file held the three variables Distance, latitude and Longtitude.
namespace DistanceEstimatorFinal
{
class dataPoint
{
private string latitude;
private string longtitude;
private string elevation;
public dataPoint() //Overloaded incase no value available
{
latitude = "No Latitude Specified";
longtitude = "No Longtitude Specified";
elevation = "No Elevation Specified";
}
public dataPoint(string Latitude, string Longtitude, string Elevation)
{
// TODO: Complete member initialization
this.latitude = Latitude;
this.longtitude = Longtitude;
this.elevation = Elevation;
}
public string CurLongtitude { get { return this.longtitude; } }
public string CurLatitude { get { return this.latitude; } }
public string CurElevation { get { return this.elevation; } }
}
Your pathFile is a method local variable, so it's inacccesible anywhere except the body of that method (here openDataListToolStripMenuItem_Click).
You could add a parameter to your dataPoints constructor to pass that value to the class:
public class dataPoints
{
List<dataPoint> Points;
public dataPoints(string path)
{
Points = new List<dataPoint>();
//here `path` from constructor arguments
TextReader tr = new StreamReader(path);
//...rest part of your code
}
Besides you'll have to pass the value to this constructor. You didn't show the code, you have to create dataPoints instanses.
var dp = new dataPoints(pathFile);
But remember, pathFile is accessible only in openDataListToolStripMenuItem_Click. So you should either create the dataPoints right there, or make your pathFile a field of a form for it to be accessible in any method of that form. Then you'd get an opportunity to access pathFile in any method of this form.
According to your previous post, this should look like:
private void openDataListToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "CSV files (*.csv)|*.csv|Text files ( *.txt)|*.txt |All files (*.*)|*.*";
if (ofd.ShowDialog(this).Equals(DialogResult.OK))
{
//actually you don't even need to have a separate `pathFile` variable
//just pass the value from the dialog straight to your `dataPoints` object
var dp = new dataPoints(ofd.FileName);
//...rest of your code
}
}
P.S.: off-topic, but, please, consider reading MSDN Guidelines for Names
I have a ListBox bind with images from SampleData source. On selection of the ListBox Item, I want to display the image in next page so I have passed the SelectedIndex on navigation but I am unable to get the image or display it. My code is below:`
//AlbumImages.cs
public class AlbumImages: ObservableCollection
{
}
//AlbumImage.cs
public class AlbumImage
{
public string title { get; set; }
public string content { get; set; }
}
//App.xaml.cs
private static MainViewModel viewModel = null;
public AlbumImages albumImages = new AlbumImages();
public int selectedImageIndex;
//MainPage.xaml.cs
private void listBoxPhoto_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (listBoxPhoto.SelectedIndex == -1) return;
this.NavigationService.Navigate(new Uri("/Photogallery.xaml?SelectedIndex=" + listBoxPhoto.SelectedIndex, UriKind.Relative));
}
//Photogallery.xaml.cs
// Reference to App
private App app = App.Current as App;
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
IDictionary<string, string> parameters = this.NavigationContext.QueryString;
if (parameters.ContainsKey("SelectedIndex"))
{
app.selectedImageIndex = Int32.Parse(parameters["SelectedIndex"]);
}
else
{
app.selectedImageIndex = 0;
}
LoadImage();
}
private void LoadImage()
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.UriSource=new Uri(app.albumImages[app.selectedImageIndex].content, UriKind.RelativeOrAbsolute);
image.Source = bitmapImage;
}`
To achieve your requirement, you have to make the photoCollection globally available to Photogallery page as well.
You can do this by assigning a copy of photoCollection (which you are using to bind to Listbox) to albumImages of App.xaml.cs from your MainPage.xaml.cs page
Note: There were some changes made your code in the question (I am not sure who did those), but the code is very near to working.