I am working with the Windows Forms app. It connects to the Flikr website via free API key, searches images that I provide through the textBox and displays the names of the files that correspond to the keyword in the imagesListBox. When I click on the image name in the imagesListBox the image is displayed inside of the pictureBox. Now I am trying to save an image from the pictureBox and I get this error: "non-invocable member PictureBox.ImageLocation cannot be used like a method". Is there another method similar to ImageLocation which I can use to retrieve the image url address? Here is my code for the button which is supposed to save the image:
private void btnSave_Click(object sender, EventArgs e)
{
//method of saving image
try
{
if (pictureBox.Image != null)
{
//5
string filePath = PictureBox.ImageLocation();
string fileName = Path.GetFileName(filePath);
File.Copy(pictureBox.Text, Path.Combine(#"C:\", Path.GetFileName(pictureBox.Text)), true);
MessageBox.Show("The image has been saved to C drive.");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Searching and uploading images from Flikr:
private async void searchButton_Click(object sender, EventArgs e)
{
// if flickrTask already running, prompt user
if (flickrTask?.Status != TaskStatus.RanToCompletion)
{
var result = MessageBox.Show(
"Cancel the current Flickr search?",
"Are you sure?", MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
// determine whether user wants to cancel prior search
if (result == DialogResult.No)
{
return;
}
else
{
flickrClient.CancelPendingRequests(); // cancel search
}
}
// Flickr's web service URL for searches
var flickrURL = "https://api.flickr.com/services/rest/?method=" +
$"flickr.photos.search&api_key={KEY}&" +
$"tags={inputTextBox.Text.Replace(" ", ",")}" +
"&tag_mode=all&per_page=500&privacy_filter=1";
imagesListBox.DataSource = null; // remove prior data source
imagesListBox.Items.Clear(); // clear imagesListBox
pictureBox.Image = null; // clear pictureBox
imagesListBox.Items.Add("Loading..."); // display Loading...
// invoke Flickr web service to search Flick with user's tags
flickrTask = flickrClient.GetStringAsync(flickrURL);
// await flickrTask then parse results with XDocument and LINQ
XDocument flickrXML = XDocument.Parse(await flickrTask);
// gather information on all photos
var flickrPhotos =
from photo in flickrXML.Descendants("photo")
let id = photo.Attribute("id").Value
let title = photo.Attribute("title").Value
let secret = photo.Attribute("secret").Value
let server = photo.Attribute("server").Value
let farm = photo.Attribute("farm").Value
select new FlickrResult
{
Title = title,
URL = $"https://farm{farm}.staticflickr.com/" +
$"{server}/{id}_{secret}.jpg"
};
// clear imagesListBox
imagesListBox.Items.Clear();
// set ListBox properties only if results were found
if (flickrPhotos.Any())
{
imagesListBox.DataSource = flickrPhotos.ToList();
imagesListBox.DisplayMember = "Title";
}
else // no matches were found
{
imagesListBox.Items.Add("No matches");
}
}
Since it has been asked how I get images inside the pictureBox:
// display selected image
private async void imagesListBox_SelectedIndexChanged(
object sender, EventArgs e)
{
if (imagesListBox.SelectedItem != null)
{
string selectedURL = ((FlickrResult)imagesListBox.SelectedItem).URL;
// use HttpClient to get selected image's bytes asynchronously
byte[] imageBytes = await flickrClient.GetByteArrayAsync(selectedURL);
// display downloaded image in pictureBox
using (var memoryStream = new MemoryStream(imageBytes))
{
pictureBox.Image = Image.FromStream(memoryStream);
}
}
}
Change the line to the following. ImageLocation is a property, not a method.
string filePath = pictureBox.ImageLocation;
Related
I am trying to load a picture from my PC as a raw image in order to use it with the Microsoft cognitive services emotion (UWP).
below is a piece of my code:
//Chose Image from PC
private async void chosefile_Click(object sender, RoutedEventArgs e)
{
//Open Dialog
FileOpenPicker open = new FileOpenPicker();
open.ViewMode = PickerViewMode.Thumbnail;
open.SuggestedStartLocation = PickerLocationId.Desktop;
open.FileTypeFilter.Add(".jpg");
open.FileTypeFilter.Add(".jpeg");
open.FileTypeFilter.Add(".gif");
open.FileTypeFilter.Add(".png");
file = await open.PickSingleFileAsync();
if (file != null)
{//imagestream is declared as IRandomAccessStream.
imagestream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
var image = new BitmapImage();
image.SetSource(imagestream);
imageView.Source = image;
}
else
{
//
}
}
The part above works fine, it selects a photo from the pc (dialog box) and displays it in Image box.
private async void analyse_Click(object sender, RoutedEventArgs e)
{
try
{
emotionResult = await emotionServiceClient.RecognizeAsync(imagestream.AsStream());
}
catch
{
output.Text = "something is wrong in stream";
}
try {
if(emotionResult!= null)
{
Scores score = emotionResult[0].Scores;
output.Text = "Your emotions are: \n" +
"Happiness: " + score.Happiness + "\n" +
"Sadness: " + score.Sadness;
}
}
catch
{
output.Text = "Something went wrong";
}
}
I think the error is due to imagestream.AsStream()
imagestream is declared as IRandomAccessStream.
Can someone please tell me how to fix that part and if the error is in fact due to not loading the image correctly?
EDIT:
Also is there a better way to do this, instead of using stream to pass the emotionServiceClient a saved file instead of a stream?
Your problem is that you've advanced the stream position by virtue of creating the BitmapImage, so your read position is at the end by the time you call emotionServiceClient.RecognizeAsync. So you'll need to 'rewind':
var stream = imagestream.AsStreamForRead();
stream.Position = 0;
emotionResult = await emotionServiceClient.RecognizeAsync(stream);
Why not use their example, instead of trying to hold the file in memory, why don't you hold a path, and then use the path to read the stream at the time.
https://www.microsoft.com/cognitive-services/en-us/Emotion-api/documentation/GetStarted
In there example;
using (Stream imageFileStream = File.OpenRead(imageFilePath))
{
//
// Detect the emotions in the URL
//
emotionResult = await emotionServiceClient.RecognizeAsync(imageFileStream);
return emotionResult;
}
So you would be capturing imageFilePath as the result of the open file dialog.
Getting closer to solve my problem, one step at a time. I now have a raw image data and the last step is to send it to my database and in this case I use Parse. This is the code so far:
The viewmodel with the Selectpicture function and how I get the image raw (works):
public async Task SelectPicture()
{
Setup ();
ImageSource = null;
try
{
var mediaFile = await _Mediapicker.SelectPhotoAsync(new CameraMediaStorageOptions
{
DefaultCamera = CameraDevice.Front,
MaxPixelDimension = 400
});
VideoInfo = mediaFile.Path;
ImageSource = ImageSource.FromStream(() => mediaFile.Source);
imageData = ReadStream(mediaFile.Source);
}
catch (System.Exception ex)
{
Status = ex.Message;
}
}
The page where I try to send the picture to my database and where the user can see the picture they selected, this is where I am stuck:
private async void btnPickPicture_Clicked (object sender, EventArgs e)
{
await MyViewModel.SelectPicture ();
imgPicked.Source = MyViewModel.ImageSource; //my image x:name in xaml
System.Diagnostics.Debug.WriteLine (imgPicked.Source);
}
//Below I send it to my parse and in parse they save it as a "File". This is the part where I am not sure how to get it right. I have to pass it as a byte but Iam not sure how to execute it.
async void SendDataClick (object sender, EventArgs args)
{
var createResult = await parseAPI.createInfo
( MyViewModel.ImageData );
}
Code to parse:
static public async Task<bool> createInfo (byte [] thePicture)
use ParseFile for saving images and binary data
// pass the ImageData from your VM into the constructor
ParseFile file = new ParseFile("image.jpg", MyViewModel.ImageData);
// save the file
file.SaveAsync();
I have a function in my program that exports data. The exporting works great, but I'm having trouble with something: When the user clicks Export, they are presented with a folder browser to choose where on their hard drive they would like to export to. The browser launches initially with all the hard drives/folders collapsed like they should be, but I can't figure out how to make it so the program remembers which location the user chose, so that the next time they want to export, it automatically opens to that location instead of once again opening with everything collapsed. I'm just having trouble with the logic, I suppose. Anyone have any tips?
Also, just for clarification, I'm trying to get it to remember the location only for the duration of the session, not like permanently on the register.
Here's my export function so far, if you think that would be helpful:
private void Export(int formatVersion, bool pureXmlDriver)
{
if (Device != null)
{
Utilities.StripShortNameFromLongNames(Device);
using (var folderBrowser = new FolderBrowserDialog())
{
folderBrowser.Description = Resources.SelectExportFolder;
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
string selectedFolder = folderBrowser.SelectedPath;
try
{
Cursor = Cursors.WaitCursor;
HandleExport(formatVersion, pureXmlDriver, selectedFolder);
}
finally
{
Cursor = Cursors.Default;
}
}
}
}
}
This should do it. You just need a class field to keep the last value in.
public class MyClass
{
private string selectedPath = "";
public void Export(int formatVersion, bool pureXmlDriver)
{
if (Device != null)
{
Utilities.StripShortNameFromLongNames(Device);
using (var folderBrowser = new FolderBrowserDialog())
{
folderBrowser.Description = Resources.SelectExportFolder;
folderBrowser.SelectedPath = selectedPath;
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
selectedFolder = folderBrowser.SelectedPath;
try
{
Cursor = Cursors.WaitCursor;
HandleExport(formatVersion, pureXmlDriver, selectedFolder);
}
finally
{
Cursor = Cursors.Default;
}
}
}
}
}
}
I am working on a C# project and i need the file to deleted after 30 seconds. So once the file sent to the machine i need the software to count till 30 seconds and at same time show a splash form and once 30 seconds crossed close the splash screen and then delete the file.
I have added a splash screen called "image". So now what happens is, the data is only sent to the printer after the splash screen is closed. I need to multi thread the job. I mean the data should print in one side while the splash screen should show at the same time. Is there a way i can come out!!.. Please help me out.
So in my case i am copying the file to the bin/debug folder. then sending data to the machine simultaneously show the splash screen for 30 seconds and close the splash screen and then i need to delete the file..
codes:
private void button4_Click(object sender, EventArgs e)
{
//string filePath = image_print();
// MessageBox.Show(filePath, "path");
string s = image_print() + Print_image();
if (String.IsNullOrEmpty(s) || img_path.Text == "")
{
return;
}
else
{
//here its coming to the splash screen code, But data is transferred to the machine only after the splash screen is close :-(
this.Hide();
omg = new image();
omg.ShowDialog();
this.Show();
//splash screen closed and then data is transferred.. which i don't need.. i need simultaneous job to be done at the same time..
PrintFactory.sendTextToLPT1(s);
}
}
private string image_print()
{
OpenFileDialog ofd = new OpenFileDialog();
string path = "";
string full_path = "";
string filename_noext = "";
ofd.InitialDirectory = #"C:\ZTOOLS\FONTS";
ofd.Filter = "GRF files (*.grf)|*.grf";
ofd.FilterIndex = 2;
ofd.RestoreDirectory = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
filename_noext = System.IO.Path.GetFileName(ofd.FileName);
path = Path.GetFullPath(ofd.FileName);
img_path.Text = filename_noext;
//MessageBox.Show(filename_noext, "Filename"); - - -> switching.grf
// MessageBox.Show(full_path, "path");
//move file from location to debug
string replacepath = #"\\bin\Debug";
string fileName = System.IO.Path.GetFileName(path);
string newpath = System.IO.Path.Combine(replacepath, fileName);
// string newpath = string.Empty;
if (!System.IO.File.Exists(filename_noext))
System.IO.File.Copy(path, newpath);
filename_noext = img_path.Text;
MessageBox.Show(filename_noext, "path");
}
if (string.IsNullOrEmpty(img_path.Text))
return "";//
StreamReader test2 = new StreamReader(img_path.Text);
string s = test2.ReadToEnd();
return s;
}
private string Print_image()
{
//some codes
return s;
}
In image form: I have the following codes
public partial class image : Form
{
string filePath;
public image()
{
InitializeComponent();
// this.filePath = FileToDeletePath;
System.Timers.Timer timer1 = new System.Timers.Timer();
timer1.Interval = 30000;
timer1.Elapsed += timer1_Elapsed;
timer1.Start();
}
private void image_Load(object sender, EventArgs e)
{
}
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
//delete the file using "filePath"
string Filename = img_path.Text; // here i cannot pass the old string file name with extension to this form.. Any ways please help me out
if (string.IsNullOrEmpty(Filename))
return;
if (Filename.ToCharArray().Intersect(Path.GetInvalidFileNameChars()).Any())
return;
File.Delete(Path.Combine(#"\\bin\Debug", Filename));
}
}
something like this????
Task waitfordelete = Task.Run(() =>
{
image im = new image();
});
Assumptions: window image should be shown as a dialog (modal), and only while the call to PrintFactory.sendTextToLPT1 is in progress.
If that's correct, then something like this could work for you:
// Don't forget, you need to dispose modal dialogs
image omg = new image();
// Ensure the dialog has been shown before starting task. That
// way the task knows for sure the dialog's been opened and can
// be closed.
omg.Loaded += (sender, e) =>
{
// Run the print task in a separate task
Task.Run(() =>
{
PrintFactory.sendTextToLPT1(s);
// But get back onto the main GUI thread to close the dialog
Dispatcher.Invoke(() => omg.Close());
});
};
this.Hide();
omg.ShowDialog();
this.Show();
Apologies in advance for any typos/syntax errors/etc. Hopefully the above is sufficient to express the general idea.
The answer given by Narzul and Peter both are correct. You can implement any one. But, I know your next question will be how to implement that method in your code.
you can use Thread or Task class object to separate the process. So when one process is running then other process can perform their taks at that time. There are two process in your login. The first one is send the file to the printer and the second one is the show dialog for 30 seconds and then delete the file. You should create the another thread to invoke the any one of the process so other process can perform asynchronously.
1st: make the seperate process for Print file.
Task waitfordelete = Task.Run(() =>
{
PrintFactory.sendTextToLPT1(s);
});
this.Hide();
omg = new image();
omg.ShowDialog();
this.Show();
2nd: make the seperate process for show dialog and delete the file. But, I think you may get the error in this method. You cannot change the UI from other thread
Task waitfordelete = Task.Run(() =>
{
Dispatcher.Invoke(() => this.ShowSplashScreen());
});
PrintFactory.sendTextToLPT1(s);
private void ShowSplashScreen()
{
this.Hide();
omg = new image();
omg.ShowDialog();
this.Show();
}
if you don't want to use the thread or task then just simply handle the close event of Image form
this.Hide();
omg = new image();
omg.Show();
PrintFactory.sendTextToLPT1(s);
omg.FormClosed += (object sender, EventArgs e) => {
File.Delete(Path.Combine(Application.StartupPath, Path.GetFileName(img_path.Text));
this.Show();
};
and modify the code in timer_tick event in Image form and add the this.Close() after delete file statement.
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
....
//File.Delete(Path.Combine(#"\\bin\Debug", Filename)); comment this line
this.Close();
}
Another hidden question I have found here. here i cannot pass the old string file name with extension to this form.. Any ways please help me out
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
//delete the file using "filePath"
string Filename = img_path.Text; // here i cannot pass the old string file name with extension to this form.. Any ways please help me out
for that, you can create the property in Image class and assign the file name from the parent form.
Image omg = new Image()
omg.FileName = Path.Combine(Application.StartupPath, Path.GetFileName(img_path.Text));
omg.Show();
and the property in Image form will be created like this
public class Image : Form
{
public string FileName { get; set; }
public Image()
{
}
void timer1_Elapsed(object sender, ElapsedEventArgs e)
{
....
File.Delete(Path.Combine(Application.StartupPath, this.Filename));
this.Close();
}
}
NOTE: Use the Application.StartupPath istead of \\bin\debug
I try to create a web browser. Currently I try to realize a function that if the user wants to download some file an additional window is shown with a list of already downloaded files. If the file has already been loaded, a message is shown (just an idea).
So far, I get a link to the file location in the main form and send it to the other form:
DownLoadFile dlf = new DownLoadFile();
...
WebBrowser wb = new WebBrowser();
wb.Navigating += new WebBrowserNavigatingEventHandler(wb_Navigating);
...
private void wb_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
...
if (e.Url.ToString().EndsWith(".mp3"))
{
dlf.DownloadPath = e.Url;
dlf.Show();
}
}
In the new form I try to use this link for file downloading:
public Uri DownloadPath { get; set; }
...
private void DownLoadFile_Load(object sender, EventArgs e)
{
string filePath = null;
//get FileName from URL
string[] ArrayForName;
ArrayForName = DownloadPath.ToString().Split('/');
saveFileDialogFile.FileName =
ArrayForName[ArrayForName.Length-1].Replace("%"," ").Trim();
if (saveFileDialogFile.ShowDialog() == DialogResult.OK)
{
WebClient client = new WebClient();
//get Url
Uri url = new Uri(DownloadPath.ToString());
//get place where want to save with default name
filePath = saveFileDialogFile.FileName;
//event for result
client.DownloadFileCompleted +=
new System.ComponentModel.AsyncCompletedEventHandler (client_DownloadFileCompleted);
//download
client.DownloadFileAsync(url, filePath);
}
}
void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MessageBox.Show("Compleated");
}
My questions are:
Regarding if (e.Url.ToString().EndsWith(".mp3")) - How can i
change this for knowing not only when the user tries to download mp3 file,
but all types of files - maybe there is a better way
If i want to download a file using some link directly, I get the message "Currently you have not required permission for that" - How can I
change permission level for my web browser
If i finally get a link to the file and start to download it, as result just name of file (size of file 0 kb) - where i'm wrong.
my solution (maybe not the best one)
create event for webBrowser
wb.Navigating += new WebBrowserNavigatingEventHandler(wb_Navigating);
and in this event use next
if (GetWorkingWebBrowser().StatusText != null)
{
try
{
WebRequest request = WebRequest.Create(GetWorkingWebBrowser().StatusText);
request.Method = "HEAD";
using (WebResponse response = request.GetResponse())
{
if (response.ContentLength > 0 &&
!response.ContentType.ToString().ToLower().Contains("text/html"))
{
dlf.DownloadPath = e.Url; //move url to my form for dwnload
dlf.Show(); //show form
}
}
}
catch (UriFormatException)
{
}
catch (WebException)
{
}
}
GetWorkingWebBrowser() - method that return current active webBrowser on tab, meas webBrowser