Capture, save and retrieve images/pictures using Sqlite database - c#

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();
}
}
}

Related

Image not uploading and getting "Cannot access a closed file."

I have been trying to upload images via a file upload control. The file is not being uploaded and I keep getting the following error:"Cannot access a closed file."
I am unsure as to why I am getting this error, any assistance would be appreciated.
My code: First is the code that grabs the image and creates the 'preview'
protected void btnupload_Click(Object sender, EventArgs e)
{
Session["Image"] = flupGalImg.PostedFile;
Stream fs = flupGalImg.PostedFile.InputStream;
BinaryReader br = new BinaryReader(fs);
byte[] bytes = br.ReadBytes((Int32)fs.Length);
string base64String = Convert.ToBase64String(bytes, 0, bytes.Length);
imgGalImg.ImageUrl = "data:image/png;base64," + base64String;
imgGalImg.Visible = true;
}
My code that calls my business logic code:
else if(btnaddedit.Text == "Add item")
{
if(txtItemTitle.Text != "")
{
if(txtItemDescription.Text != "")
{
if(Session["Image"] != null)
{
HttpPostedFile postedFile = (HttpPostedFile)Session["Image"];
int alb;
int.TryParse(hdnAlbId.Value, out alb);
if(newsLogic.CreateNewGalleryItem(txtItemTitle.Text, txtItemDescription.Text, alb, postedFile) == true)
{
// Do something.
}
}
}
}
}
And finally my business logic code:
// create gallery item
[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Insert, true)]
public bool CreateNewGalleryItem(string itemTitle, string itemDescription, int itemAlbum, HttpPostedFile itemFile)
{
string folderpath = #"~/Images/GalleryImages/";
string filename = Path.GetFileName(itemFile.FileName.ToString());
bool itemCreated = false;
string itemImgPath;
try
{
itemImgPath = Path.Combine(folderpath + filename);
string itemImgUploadPath = Path.Combine(HttpContext.Current.Server.MapPath(folderpath) + filename);
itemFile.SaveAs(itemImgUploadPath);
galAdp.CreateGalleryItem(itemTitle, itemDescription, itemImgPath, itemAlbum);
itemCreated = true;
}
catch (Exception er)
{
itemCreated = false;
string consmsg = er.Message;
}
return itemCreated;
}
My 'image preview' works just fine. The error is thrown on this line of the business logic: itemFile.SaveAs(itemImgUploadPath);
When I did a google search (well lots of google searches) I read that it may be the file size so I increased the max allowed content in the web.config but nothing changed.
Any ideas as to what I am doing wrong?

Screen shot in android with c#

I am working on an android project in which I want to take the screen shot of current activity and save that as .jpeg file in my android device.
When I use instance of FileOutputStream to write the stream of bitmap image into a file, it gives me following error
Argument 3 cannot converted from 'Java.IO.FileOutputStream' to 'System.IO.Stream'
My code
private void ShareButton_Click(object sender, EventArgs e)
{
//create a bitmap screen capture
View screen = FindViewById(Resource.Layout.AboutImage);
Bitmap bitmap = Bitmap.CreateBitmap(screen.GetDrawingCache(false));
screen.SetWillNotCacheDrawing(true);
image = new File(directory, "Eco_Friendly " + mc.identifier);
FileOutputStream outputstream = new FileOutputStream(image);
int quality = 100;
bitmap.Compress(Bitmap.CompressFormat.Jpeg, quality, outputstream);//Here is error
}
Q:How to solve this problem?
Try this code:
package com.screen.shots;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class CaptureScreenShots extends Activity {
LinearLayout L1;
ImageView image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.screen_shots);
L1 = (LinearLayout) findViewById(R.id.LinearLayout01);
Button but = (Button) findViewById(R.id.munchscreen);
but.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
View v1 = L1.getRootView();
v1.setDrawingCacheEnabled(true);
Bitmap bm = v1.getDrawingCache();
BitmapDrawable bitmapDrawable = new BitmapDrawable(bm);
image = (ImageView) findViewById(R.id.screenshots);
image.setBackgroundDrawable(bitmapDrawable);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.screen_shots, menu);
return true;
}
}
Result:
like this
View root = getWindow().getDecorView().getRootView();
root.setDrawingCacheEnabled(true);
root.buildDrawingCache();
Bitmap snapshot = root.getDrawingCache();
at last, you should call this
root.destroyDrawingCache();

Why my image update is not "binded"?

I have a gird view of my objects "Sessions". On user selection, every Session's Image gets display in an Image on my GUI. I have this routine where, on user SelectedSession, it Deletes any existing image, Takes a new Image frameSource, Saves it locally and then sets the private member variable ImagePath as its path:
public Session SelectedSession { get { return selectedSession; } set { SetValue(ref selectedSession, value); } }
public BitmapSource SessionImage { get { return sessionImage; } private set { SetValue(ref sessionImage, value); } }
//..
public void TakeSessionImage(BitmapSource frameSource)
{
if (SelectedSession != null)
{
if (File.Exists(SelectedSession.ImagePath))
File.Delete(SelectedSession.ImagePath); // delete old - works
SelectedSession.ImagePath = FileStructure.CurrentSessionPath + "\\" + SelectedSession.Name + ".png"; // set ImagePath - works - Technically it does not change. I kept it if I needed later to add anything to the file name like GUID or whatever
ImageIO.RotateAndSaveImage(SelectedSession.ImagePath, (WriteableBitmap)frameSource, -270); // save new image - works
SessionImage = SelectedSession.LoadImageFromFile(); // binded the image to display
}
}
Binding in Xaml:
<Image x:Name="currentSessionImage" Source="{Binding SessionImage}"/>
In "Session.cs" class:
public BitmapImage LoadImageFromFile()
{
if (File.Exists(ImagePath)) // image path is correct
{
try
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(ImagePath);
image.EndInit();
return image;
}
catch
{
return null;
}
}
return null;
}
This has been debugged and all statements are valid. SessionImageis my property that is "binded" to an Image on my GUI. However, a very weird behavior is happening:
It is deleting the old image file and I can see that in windows explorer that the file is gone.
It is saving the new one correctly
It is loading the new image from the correct path
But then, it only displays the very First Image I ever took.
Whatever new image I send. It always displays the same image I took the first time. Could anyone please check it for me? I validated the whole code and all values are logical. No syntax errors anywhere.
Edit:
protected virtual bool SetValue<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(storage, value))
{
storage = value;
OnPropertyChanged(propertyName);
return true;
}
return false;
}
//..
protected void OnPropertyChanged(string propertyName)
{
try
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
catch (Exception ex)
{
}
}
WPF caches bitmaps that are loaded from URIs. To avoid that, load the BitmapImage directly from file instead:
using (var fileStream = new FileStream(ImagePath, FileMode.Open, FileAccess.Read))
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = fileStream;
image.EndInit();
return image;
}

Reduce size of image after Scan?

I have code that scan file and save it on my path:
public ImageFile Scan()
{
var device = this._deviceInfo.Connect();
var item = device.Items[1];
var imageFile = (ImageFile)item.Transfer(FormatID.wiaFormatJPEG);
return imageFile;
}
protected void btnscan_Click(object sender, EventArgs e)
{
foreach (Object scanner in scanners)
{
if (ddlSelectDevice.SelectedItem.ToString().Equals(scanner.ToString()))
{
//var d = ddlSelectDevice.SelectedIndex as Scanner;
var device = scanner as Scanner;
if (device == null)
{
return;
}
var image = device.Scan();
var path = "~/Scanner/scan.jpeg";
if (File.Exists(Server.MapPath(path)))
{
File.Delete(Server.MapPath(path));
}
image.SaveFile(Server.MapPath(path));
break;
}
}
}
I save this image in database by convert to byte:
private byte[] image2Byte()
{
string filePath = null;
Byte[] bytes = null;
if (File.Exists(Server.MapPath("~/Scanner/scan.jpeg")))
{
filePath = Server.MapPath("~/Scanner/scan.jpeg");
return bytes = File.ReadAllBytes(filePath);
}
else
{
filePath = Server.MapPath("~/Scanner/None.jpg");
return bytes = File.ReadAllBytes(filePath);
}
}
But my images usually have large size (up 400kB) and makes problem on load. How I can reduce image size?
You can use ImageProcessor to reduce the quality of the JPEG file. A quality of 80% is accaptable for most use cases.
using (ImageFactory imageFactory = new ImageFactory(preserveExifData:true))
{
imageFactory.Load(inStream)
.Quality(80)
.Save(outStream);
}

Passing image between two pages

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..:)

Categories