Picture appears only after restart the device - c#

I have an Android-App that takes pictures and saves them in an external storage ("DCIM/Cameras"). But the pictures appear only after restarting my handy.
Is there some kind of Update or a way around this?
My source-code from saving my image:
var dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim);
var pictures = dir.AbsolutePath + "/Camera";
string name = System.DateTime.Now.ToString("yyyyMMdd_HHmmssfff") + ".jpg";
string filePath = System.IO.Path.Combine(pictures, name);
FileStream output;
Bitmap bitmap = BitmapFactory.DecodeByteArray(imageData, 0, imageData.Length);
try
{
output = new FileStream(filePath, FileMode.Create);
bitmap.Compress(Bitmap.CompressFormat.Jpeg, 100, output);
output.Close();
//Static Class that contains an methode for MediaScannerConnection.ScanFile
MediaGalleryHelper.AddFileToGallery(name);
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.ToString());
}

You have to let the photo gallery know that a new photo has been added. You can use below code for that:
this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));
Where 'this' is an activity.

Related

Deleting file throws file in use exception

I have a file upload control that allows users to upload an image file. Rather then forcing them to use a specific size image, I am trying to resize it, save it the resized version to a folder and then delete the original.
When I try to delete the file, I keep getting "file in use" exception. I have searched and tried all suggestions to no avail.
This is the latest try, at which point I decided to seek help. I pass the source path (where original file is in, a destination path where resized file is to end up in, file name and width to which it should be resized, keeping aspect ratio):
public static void CreateResizedCopy(String sourcePath, String destinationPath, String filename, int width)
{
if (!File.Exists(destinationPath + filename))
{
System.Drawing.Image image = System.Drawing.Image.FromFile(sourcePath + filename);
float AspectRatio = (float)image.Size.Width / (float)image.Size.Height;
int newHeight = Convert.ToInt32(width / AspectRatio);
Bitmap thumbnailBitmap = new Bitmap(width, newHeight);
Graphics thumbnailGraph = Graphics.FromImage(thumbnailBitmap);
thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
var imageRectangle = new Rectangle(0, 0, width, newHeight);
thumbnailGraph.DrawImage(image, imageRectangle);
thumbnailBitmap.Save(destinationPath + filename, ImageFormat.Jpeg);
thumbnailGraph.Dispose();
thumbnailBitmap.Dispose();
image.Dispose();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
if (!FileInUse(sourcePath + filename))
{
File.Delete(sourcePath + filename);
}
else
{
// Error here: file is in use
using (FileStream fs = new FileStream(sourcePath + filename, FileMode.OpenOrCreate))
fs.Dispose();
}
}
}
public static bool FileInUse(string path)
{
try
{
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate))
{
return false;
}
}
catch (IOException ex)
{
return true;
}
}
UPDATE
This is the AJAX AsynFileUpload's upload completed event handler. It saves the file to a "Resize" folder. If image needs to be resized, it calls the method to resize it and then moves it to its final resting place. If not, no resizing is done, it just moves the file. It then "attempts" to delete the file in resize folder and it chokes!
protected void fuNewsImage_UploadedComplete_Resize(object sender, AsyncFileUploadEventArgs e)
{
if (fuNewsImage.HasFile)
{
HttpPostedFile file = fuNewsImage.PostedFile;
string sFileName = fuNewsImage.FileName;
string sFileSize = e.FileSize;
string sSaveFolder = ImageFilePath.TEMP_FOLDER_EA_TEST + "\\";
string sResizeFolder = ImageFilePath.TEMP_FOLDER_EA_TEST + "\\Resized\\";
fuNewsImage.SaveAs(Server.MapPath(sResizeFolder + sFileName));
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath(sResizeFolder) + sFileName);
int iImgWidth = img.Width;
int iImgHeight = img.Height;
if (iImgWidth > ImageInfo.MAX_WIDTH)
{
// sSaveFolder is the efinal resting place of the uploaded image
// If image width is more than max allowed, resize it, save it in sSaveFolder
Utils.CreateResizedCopy(Server.MapPath(sResizeFolder), Server.MapPath(sSaveFolder), sFileName, 600);
System.Threading.Thread.Sleep(1000);
File.Delete(Server.MapPath(sSaveFolder + sFileName));
}
else // just move it t sSaveFolder
{
File.Move(Server.MapPath(sResizeFolder) + sFileName, Server.MapPath(sSaveFolder) + sFileName);
}
// --- Chokes here ---
Array.ForEach(Directory.GetFiles(Server.MapPath(sResizeFolder)), File.Delete);
}
}

Bad parameter when using save() on Image

I am having a bit of trouble with saving an Image, it says "Bad paremeter" on the line where I try and save the image.
I'm not sure if it's how I am creating the image or if it's just saving that's the problem.
public static void Fullscreen()
{
string fileName = Helper.RandomStr(10) + ".png";
try
{
var image = ScreenCapture.CaptureFullscreen();
image.Save(fileName, ImageFormat.Png);
System.Diagnostics.Process.Start(fileName);
}
catch (Exception ex)
{
MessageBox.Show("Unable to capture fullscreen because: " + ex.ToString() + "\r\n\r\nFile: " + fileName);
}
}
Edit:
Here is the method that gets the Bitmap
public static Bitmap CaptureFullscreen()
{
using (Bitmap bmp = new Bitmap(ScreenDimensions.Width, ScreenDimensions.Height))
{
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(Point.Empty, Point.Empty, bmp.Size);
}
return bmp;
}
}
Bad parameter is the way GDI+ tells that there was some problem.
Its a shame that the errors are not very much descriptive.
First try to wrap image parameter to Bitmap constructor like:
image = new Bitmap(image);
This forces to process the bitmap immediately.
It was even simpler, remove using on the bitmap.
Try using a known path and see if starts working. If so then you might want a new random string generator that makes valid paths or a different way of naming the file.

Specify the location to save the pdf file asp.net

Below is my code which generates a sample PDF file. However the server.mappath method saves the file at the project folder. How do i allow the PDF file to be saved in my own desktop?
protected void btnPDF_Click(object sender, EventArgs e)
{
var document = new Document(PageSize.A4, 50, 50, 25, 25);
var filename = DDLCase.SelectedItem.Text + ".pdf";
var output = new FileStream(Server.MapPath(filename), FileMode.Create);
var writer = PdfWriter.GetInstance(document, output);
document.Open();
var welcomeParagraph = new Paragraph("Test1");
document.Add(welcomeParagraph);
document.Close();
btnPDF.Enabled= false;
}
It is very unclear what your problem is as it should be pretty straightforward to replace Server.MapPath(filename) with some other location.
One useful function is Path.Combine so you can correctly build path to a file:
var output = new FileStream(Path.Combine("c:\\myPDF\\", filename), FileMode.Create);
Note that to be done properly folder on server where you plan to store files must have enough permissions to allow ASP.Net process to save files there. If you use Windows auth with impersonation it becomes trickier as account code is running under during request will be incoming user's account.
Try this
public string CommonFileSave(HttpPostedFileBase postedFile, string filePath)
{
string resultResponse = "sccuess";
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
postedFile.SaveAs(filePath + postedFile.FileName);
}
else
{
filePath = filePath + postedFile.FileName;
if (!System.IO.File.Exists(filePath))
{
postedFile.SaveAs(filePath);
}
}
return resultResponse;
}

image file is not released after it is disposed

I am working on a project that downloads some images and put them in a arrarList to be processed later. The following portion of code is where the problem is. It works with first download, but somehow the file images were saving to is locked up after the first download. I can't seems to find a way to unlock it. File.Delete("BufferImg"); is giving error saying the file is been used by another process when "BufferImg" was not used anywhere else of the program. What am I doing wrong?
int attempcnt=0;
if (ok)
{
System.Net.WebClient myWebClient = new System.Net.WebClient();
try
{
myWebClient.DownloadFile(pth, "BufferImg");
lock (IMRequest) { IMRequest.RemoveAt(0); }
attempcnt = 0;
}
catch // will attempcnt 3 time before it remove the request from the queue
{
attempcnt++;
myWebClient.Dispose();
myWebClient = null;
if(attempcnt >2)
{
lock (IMRequest) { IMRequest.RemoveAt(0); }
attempcnt = 0;
}
goto endofWhile;
}
myWebClient.Dispose();
myWebClient = null;
using (Image img = Image.FromFile("BufferImg"))
{
lock (IMBuffer)
{
IMBuffer.Add(img.Clone());
MessageBox.Show("worker filled: " + IMBuffer.Count.ToString() + ": " + pth);
}
img.Dispose();
}
}
endofWhile:
File.Delete("BufferImg");
continue;
}
The following line is why the image is not being released:
IMBuffer.Add(img.Clone());
When you clone something loaded through a resource (file), the file is still attached to the cloned object. You will have to use a FileStream, like so:
FileStream fs = new FileStream("BufferImg", FileMode.Open, FileAccess.Read);
using (Image img = Image.FromStream(fs))
{
lock (IMBuffer)
{
IMBuffer.Add(img);
MessageBox.Show("worker filled: " + IMBuffer.Count.ToString() + ": " + pth);
}
}
fs.Close();
This should release the file after you've loaded it in the buffer.

DotNetZip - reading to memory

I've put together a quick test using the DotNetZip library which opens a zip file full of .bmp files and converts them to .jpg format.
Prior to this I was writing all of the files to a folder, converting them, saving out the jpg files & then removing the original bmp files, which got messy.
I'm no looking to unzip them in memory first, convert to jpg & then save.
The code works, but just isn't that quick. Can anyone give me any pointers as to what I can do to improve the code please? Also, Would threading help?
string zipToUnpack = "c:\\test\\1000.zip";
string unpackDirectory = "c:\\temp\\";
string f = string.Empty;
Bitmap bm;
MemoryStream ms;
using (ZipFile zip = ZipFile.Read(zipToUnpack))
{
foreach (ZipEntry e in zip)
{
if (e.FileName.ToLower().IndexOf(".bmp") > 0)
{
ms = new MemoryStream();
e.Extract(ms);
try
{
bm = new Bitmap(ms);
f = unpackDirectory + e.FileName.ToLower().Replace(".bmp", ".jpg");
bm.Save(f, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
Console.WriteLine("File: " + e.FileName + " " + ex.ToString());
}
ms.Dispose();
}
}
}
Thanks
In general, DotNetZip is single-threaded. You can open multiple archives in multiple threads, but each archive in only one thread.
If you want to enlist multiple CPUs or cores, then I can suggest calling QueueUserWorkItem for the part where you convert the data in the MemoryStream into a jpg.
The call to ZipEntry.Extract() needs to be done on the same thread, for all entries. This is because the Zipfile maintains a single FileStream for all read access, and multiple threads extracting entries will cause file pointer arithmetic errors.
So, something like this:
public class State
{
public string FileName;
public MemoryStream stream;
}
public void Run()
{
string unpackDirectory = "c:\\temp\\";
string zipToUnpack = "c:\\test\\1000.zip";
var ConvertImage = new WaitCallback( (o) => {
State s = o as State;
try
{
var bm = new Bitmap(s.stream);
var f = unpackDirectory + s.FileName.ToLower().Replace(".bmp", ".jpg");
bm.Save(f, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (Exception ex)
{
Console.WriteLine("File: " + s.FileName + " " + ex.ToString());
}
});
using (ZipFile zip = ZipFile.Read(zipToUnpack))
{
foreach (ZipEntry e in zip)
{
if (e.FileName.ToLower().IndexOf(".bmp") > 0)
{
var ms = new MemoryStream();
e.Extract(ms);
ThreadPool.QueueUserWorkItem ( ConvertImage,
new State {
FileName = e.FileName, stream = ms }
});
}
}
}
}

Categories