I just pass the image between two pages, by passing the byte[] and I try to convert the byte[] to image in page 2 using the following code,
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Uri.OriginalString.Contains("img"))
{
expenseDetails = AuthOrgClass.expenseDetails;
imgData = NavigationService.GetImageNavigationData();
fill();
}
}
private void fill()
{
var bitmapImage = new BitmapImage();
var memoryStream = new MemoryStream(imgData);
bitmapImage.SetSource(memoryStream);
ImageBox.Source = bitmapImage;
}
While executing the line bitmapImage.SetSource(memoryStream);
I get the exception
An exception of type 'System.Exception' occurred in System.Windows.ni.dll but was not handled in user code
What could be the problem?
You should use IsolatedStorageSettings to store image as byte array. IsolatedStorageSettings accessible in all application. So you can easily pass your byte array between any pages in application. try this may this will help you.
SaveImageAsByteArray()
{
IsolatedStorageSettings MemorySettings = IsolatedStorageSettings.ApplicationSettings;
if (MemorySettings.Contains("ImageData"))
MemorySettings["ImageData"] = your byte array;
else
MemorySettings.add("ImageData", your byte array;);
IsolatedStorageSettings.ApplicationSettings.Save();
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.Uri.OriginalString.Contains("img"))
{
fill();
}
}
private void fill()
{
IsolatedStorageSettings MemorySettings = IsolatedStorageSettings.ApplicationSettings;
if (MemorySettings.Contains("ImageData"))
byte[] bytes = MemorySettings["ImageData"]
MemoryStream stream = new MemoryStream(bytes);
BitmapImage image = new BitmapImage();
image.SetSource(stream);
ImageBox.Source = image;
}
The best Practice is take a global Image varible in App.xaml.cs,assign it at first page and take value from it at second page.It would never create a problem..:)
Related
I'm trying to change an image on runtime but it's not working.
I have a user control that when you click on imagebtn it's opening a new window with a list of images.
the next step is to take the image selected from the list, close the new window, and put the image on the imagebtn.
the user control still opens in the background.
this is my code.
NewWindow:
private string myData;
public ImagesWindow()
{
InitializeComponent();
InitialImageList();
}
private async void InitialImageList()
{
//add try catch
string get = await HttpRequests.GetRequest(URLImages);
allJsonCategory = JsonConvert.DeserializeObject<List<ImageArray>>(get);
Console.WriteLine(get);
ImageBoxList.ItemsSource = images;
foreach (var item in allJsonCategory)
{
images.Add(item);
}
}
private void ImageBoxList_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
selectedImage = (ImageArray)ImageBoxList.SelectedItem;
myData = selectedImage.full_path;
Console.WriteLine("you clicked on: " + selectedImage.name);
ProductsCategory pro = new ProductsCategory();
pro.imagePath = myData;
this.Close();
}
my usercontrol(in mainWindow):
public void setImage(string imagePath)
{
if (!imageURL.Equals(""))
{
Image imageBtn = new Image();
var imgUrl = new Uri(imagePath);
var imageData = new WebClient().DownloadData(imgUrl);
// or you can download it Async won't block your UI
// var imageData = await new WebClient().DownloadDataTaskAsync(imgUrl);
var bitmapImage = new BitmapImage { CacheOption = BitmapCacheOption.OnLoad };
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(imageData);
bitmapImage.EndInit();
imageBtn.Source = bitmapImage;
//this.imageBtn.InvalidateVisual();
}
}
XAML of the image:
where is my mistake?
thank you all :)
I am taking bitmap images from camera and store them in a List< Bitmap>.
Within the same class I can set pictureBox images directly from the list like:
pictureBox1.Image = imagesToReturn[0];
where imagesToReturn is a List< Bitmap>.
The problem occurs when I call this method from a different class. ('invalid parameter' error is thrown).
First I return the list from the first object,
then copy it in the second object,
and then destruct the first object.
When I check the returned list I see they are returned correctly (Check the image below; [2] is intentionally null).
Do you guys have any idea what might be the problem or how can I solve this?
Thanks for your valuable time and help.
(edit: long story short, The list you see on the picture above cannot be loaded to pictureboxes because of the 'invalid parameter' error)
Here are some of the codes:
These are in the first class and work perfectly:
/*These are in the first class and works perfectly.*/
public static List<Bitmap> ImagesToReturn = new List<Bitmap>();
public static void updateThumbnails(Bitmap img, int* pictureBoxIndex)
{
switch (*pictureBoxIndex)
{
case 1:
ImagesToReturn[0] = img;
pictureBox2.Image = ImagesToReturn[0];//so that I know they are stored correctly.
pictureBox2.Refresh();
break;
case 2:
ImagesToReturn[1] = img;
pictureBox3.Image = ImagesToReturn[1];
pictureBox3.Refresh();
break;
case 3:
ImagesToReturn[2] = img;
pictureBox4.Image = ImagesToReturn[2];
pictureBox4.Refresh();
break;
case 4:
ImagesToReturn[3] = img;
pictureBox5.Image = ImagesToReturn[3];
pictureBox5.Refresh();
break;
default:
break;
}
*pictureBoxIndex = 0;
img.Dispose();
}
public List<Bitmap> returnCapturedImageList()
{
return ImagesToReturn;
}
//Done button. Terminates the processes.
private void button2_Click(object sender, EventArgs e)
{
keepRunning = false; // in order to stop straming
this.DialogResult = DialogResult.OK;
}
And these are at the second class:
public static List<Bitmap> returnedImages = new List<Bitmap>();
private void button1_Click(object sender, EventArgs e)
{
WindowsFormsApplication6.Form2 cameraModule = new WindowsFormsApplication6.Form2();
var result = cameraModule.ShowDialog();
if (result == DialogResult.OK)
{
returnedImages = cameraModule.returnCapturedImageList()
pictureBox1.Image = returnedImages[0]; //ERROR is thrown here!
pictureBox1.Refresh();
cameraModule.DialogResult = DialogResult.Cancel;
cameraModule.Close();
}
returnedImages.Clear();
}
The issue is solved thanks to the user6144226 and LarsTech. They actually pointed out the mistake.
ImagesToReturn[0] = img; /*not copying or cloning*/
ImagesToReturn[1] = img;
ImagesToReturn[2] = img;
ImagesToReturn[3] = img;
The statements above were not copying image to the list. It was pointing to the 'img'. In other words, when I disposed the 'img' with following command:
img.Dispose();
the "ImagesToReturn[n]" was pointing to the memory that has already been disposed.
The proper way to do it was as follows:
ImagesToReturn[0] = new Bitmap(img); /*copying*/
ImagesToReturn[1] = new Bitmap(img);
ImagesToReturn[2] = new Bitmap(img);
And that solved the issue.
I am picking image from gallery using PhotoChooserTask, here is my setup
private void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
PhotoChooserTask photo = new PhotoChooserTask();
photo.Completed += photo_Completed;
photo.Show();
}
void photo_Completed(object sender, PhotoResult e)
{
if (e.ChosenPhoto != null)
{
WriteableBitmap wbmp1 = PictureDecoder.DecodeJpeg(e.ChoosenPhoto, (int)scrnWidth, (int)scrnHeight);
ImageBrush iBru = new ImageBrush();
iBru.ImageSource = wbmp1;
iBru.Stretch = Stretch.Fill;
ContentPanel.Background = iBru;
}
}
Problem: with this way is it works only with .JPEG images
to make it work with other image formats, I tried this:
void photo_Completed(object sender, PhotoResult e)
{
if (e.ChosenPhoto != null)
{
WriteableBitmap wBmp = new WriteableBitmap(0, 0);//6930432
wBmp.SetSource(e.ChosenPhoto);//23105536
MemoryStream tmpStream = new MemoryStream();//23105536
wBmp.SaveJpeg(tmpStream, (int)scrnWidth, (int)scrnHeight, 0, 100);//22831104
tmpStream.Seek(0, SeekOrigin.Begin);//22831104
WriteableBitmap wbmp1 = PictureDecoder.DecodeJpeg(tmpStream, (int)scrnWidth, (int)scrnHeight);//24449024
ImageBrush iBru = new ImageBrush();//24449024
iBru.ImageSource = wbmp1;//24449024
iBru.Stretch = Stretch.Fill;
ContentPanel.Background = iBru;
}
}
this way works with different image formats, but it is not memory efficient.
I have mentioned number of bytes used after each line for better understanding.
Question: In latter code snippet, I do not need wbmp anymore, How can I clear memory used by wbmp object?
As #Soonts suggested I used BitmapImage and it solves my purpose,
BitmapImage bmp = new BitmapImage();
bmp.DecodePixelWidth = (int)scrnWidth;
bmp.DecodePixelHeight = (int)scrnHeight;
bmp.SetSource(e.ChosenPhoto);
It consumes less memory and we can scale down image
Get rid of the WriteableBitmap, instead do something like this:
var bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.SetSource( e.ChosenPhoto );
var ib = new ImageBrush() { ImageSource = bmp, Stretch = Stretch.Fill };
ContentPanel.Background = ib;
Using Photochooser Task the image has to be loaded and passed immediately to another page. But shows blank when implemented the following code:
private void LoadPicture_Click(object sender, RoutedEventArgs e)
{
PhotoChooserTask photoChooserTask;
photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
photoChooserTask.Show();
NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
}
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.SetSource(e.ChosenPhoto);
Page1 p1 = new Page1();
p1.encodeImg.Source = bmp;
}
else
{
MessageBox.Show("Image Loading Failed.");
}
}
Please suggest in fixing the above the issue.
Thanks!
Have you solved it? if you haven't you could use something like this. in your photoChooseTask handler save the bitmapImage
PhoneApplicationService.Current.State["yourparam"] = bmp;
and then in your Page1 you get the bitmapImage
BitmapImage bitmapGet = PhoneApplicationService.Current.State["yourparam"] as BitmapImage;
here's how you should use this.
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.SetSource(e.ChosenPhoto);
//save the bitmapImage
PhoneApplicationService.Current.State["yourparam"] = bmp;
}
else
{
MessageBox.Show("Image Loading Failed.");
}
NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
}
your Page1
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
//get the bitmapImage
BitmapImage bitmapGet = PhoneApplicationService.Current.State["yourparam"] as BitmapImage;
//set the bitmpaImage
img.Source = bitmapGet;
base.OnNavigatedTo(e);
}
More about PhoneApplicationService.Current.State :)
The navigation must be done after completed event, photochooser.show() suppresses the main application thread, hence you can only pass the image stream once you get it. So, shift navigation statement to completed event handler and using isolatedstoragesettings.applicationsettings to store the image and get it back on second page.
Another way to achieve it is to save the image in isolateStorage first and pass the file path to your page1 as a string parameter.
page1 then could load the image anytime it needs.
In my windows 8 application(C#), I want to capture images (I done) and then save it to a Sqlite database. As Sqlite is not supporting BipmapImage, Uri types etc (I tried but giving exceptions of not supported storage..) How can I do this?
I simply want to save images in local database that I have captured using camera and then retrieve these images (set to binding). Please suggest me other options to achieve this.
I also tried to convert Uri into string and then saving this string into SQLite db and then again converting string to Uri and then making Bitmap images but I couldn't achieve this (is it a right approach ?).
If you can share me any sample please do it. I spent many hours in it but don't know where I am doing wrong!
Thanks Zauk
Although I do not prefer to save images in a database.
But if you want to save images in the database then one way of doing this is to convert your images to base64 string and then save the string in SQLite database.
public string ConvertToString(Image image)
{
// First Convert image to byte array.
byte[] byteArray = new byte[0];
using (MemoryStream stream = new MemoryStream())
{
image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
}
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(byteArray);
return base64String;
}
You can save camera captured image into SQLitedatabase in this way..
public class CamActivity extends Activity {
byte[] byteArray;
private static final int CAMERA_REQUEST = 1888;
protected static final int TAKE_PHOTO_CODE = 0;
public ImageView imageView;
private DBAdapter db;
byte [] imgbyte;
EditText txtView ;
String name;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
db=new DBAdapter(CamActivity.this);
db.open();
this.imageView = (ImageView)this.findViewById(R.id.imageView1);
txtView=(EditText)findViewById(R.id.editText1);
Button B = (Button) this.findViewById(R.id.camera);
B.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
// cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,getImageUri());
startActivityForResult(cameraIntent,CAMERA_REQUEST );
}
});
Button save = (Button)findViewById(R.id.saving);
save.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
name=txtView.getText().toString();
try
{
db.insertImageDetails(byteArray,name);
}
catch (Exception e) {
e.printStackTrace();
}
//mySQLiteAdapter.close();
Toast.makeText(getApplicationContext(), "processing", Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), "image saved", Toast.LENGTH_SHORT).show();
}});
Button G = (Button) this.findViewById(R.id.get);
G.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
Intent intent= new Intent(CamActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//final byte[] byteArray;
if (requestCode == CAMERA_REQUEST) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
//imageView.setImageBitmap(photo);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
byteArray = stream.toByteArray();
System.out.println(byteArray);
Toast.makeText(getApplicationContext(), byteArray.toString(), Toast.LENGTH_SHORT).show();
}
}
}