Deep zoom image creation throws exception in c# - c#

Iam building a website which uses a pivot viewer that uses a deep zoom collection to show images and the metadata from a database. Iam using the deezoomtools.dll from microsoft to create the deep zoom collection.
From this website i can start a thread that starts the creation of several collection. For small collections this process goes just fine, however when doing a large collection it fails regularly.
I added some debug lines to see what happens and the exception i get is:
Thread was aborted as the message and as stack trace where it came from.
I found that when the images are processed the exception occurs. I guess that the error occurs in this code sample in the function GetImageForDeepZoomComposer
private bool processImage(Item collectionItem, string backupImage,StreamWriter _logFile)
{
try
{
_logFile.WriteLine("start process");
if (string.IsNullOrEmpty(collectionItem.Image))
return false;
if (!File.Exists(collectionItem.ImagePath))
return false;
_logFile.WriteLine("File is there");
if (!AllImagesUnique) // check to see if we have processed this exact file before.
if (cacheOfImageIds.ContainsKey(collectionItem.ImagePath)) // we already have have processed this image so don't do it again
{
collectionItem.ImageId = cacheOfImageIds[collectionItem.ImagePath];
return true;
}
_logFile.WriteLine("Get Image: " + collectionItem.ImagePath);
string workingImage = GetImageForDeepZoomComposer(collectionItem.ImagePath, collectionItem.Id);
_logFile.WriteLine("Image aquired");
_logFile.WriteLine("collection name and id");
string deepZoomImage = DeepZoomImageDir + collectionItem.Id;
sendAction(string.Format("\tConverting image {0} to Deep Zoom Output file {1} ", workingImage,
deepZoomImage));
//imageCreator.Create(workingImage, deepZoomImage);
_logFile.WriteLine("set image surrogate");
SurrogateImageInfo sii = new SurrogateImageInfo(workingImage, "DeepZoomImages/" + Path.GetFileName(deepZoomImage) + ".xml");
_logFile.WriteLine("image surrogate set");
images.Add(sii);
if (!AllImagesUnique) // if we want to make sure we don't use the Deep Zoom Composer on the same file twice then add this image to the cache
cacheOfImageIds.Add(collectionItem.ImagePath, collectionItem.Id);
return true;
}
catch (Exception ex)
{
_logFile.WriteLine(ex.Message);
sendAction(
string.Format(
"\tSkipping current item cause of execption encountered while processing the image\r\n\t\t{0}",
ex.Message));
return false; // this item will not be added to the collection
}
}
internal string GetImageForDeepZoomComposer(string imageFile,int id)
{
if (imageFile.StartsWith("http://") || imageFile.StartsWith("https://"))
{
if (_client == null) // if we havent used the WebClient for this collection yet create one
_client = new WebClient();
string tempFile = ImageDownloadDir + Guid.NewGuid();
sendAction(string.Format("\tDownloading image '{0} to {1}", imageFile, tempFile));
_client.DownloadFile(imageFile, tempFile);
return tempFile;
}
else if (imageFile.StartsWith("\\") || imageFile.StartsWith("E:\\") || imageFile.StartsWith("e:\\"))
{
var dir = Path.Combine(DeepZoomImageDir, id.ToString() + "_files");
//if (!Directory.Exists(dir))
// Directory.CreateDirectory(dir);
var fixedSizeFileName = imageFile.Replace("_thumb", "_fs");
//create a fixed size image if it's not already created
if (!File.Exists(fixedSizeFileName))
FixedSize(new System.Drawing.Bitmap(imageFile), 512, 512).Save(fixedSizeFileName,codecInfo,parameters);
//copy the fixed size image to the DeepZoomImages folder so it can be used when zooming in to the deepest level
var localFixedSizeImage = Path.Combine(DeepZoomImageDir, id + ".jpg");
File.Copy(fixedSizeFileName, localFixedSizeImage);
return localFixedSizeImage;
}
return imageFile;
}
I think it has something to do with images that are locked when it tries to get the image and tries to save it with a different name such that it could be used. Iam truly at a loss here.
Thank you in advance for the information

Related

c# adobe acrobat SDK: file is still locked after SDK quit

I'm working with C# and adobe acrobat SDK.
When the program throws an error due to the pdf already being compressed I want to move the pdf.
However, C# complains that the file is being used by another process and I know it has to do with the SDK and not another program.
After some debugging I found out that compressPDFOperation.Execute is the culprit.
How can I close it so that I can move the file?
try {
// Initial setup, create credentials instance.
Console.WriteLine(".json: " + Directory.GetCurrentDirectory() + "/pdftools-api-credentials.json");
Credentials credentials = Credentials.ServiceAccountCredentialsBuilder()
.FromFile(Directory.GetCurrentDirectory() + "/pdftools-api-credentials.json")
.Build();
// Create an ExecutionContext using credentials and create a new operation instance.
ExecutionContext executionContext = ExecutionContext.Create(credentials);
CompressPDFOperation compressPDFOperation = CompressPDFOperation.CreateNew();
// Set operation input from a source file.
FileRef sourceFileRef = FileRef.CreateFromLocalFile(directory + #"\" + pdfname);
compressPDFOperation.SetInput(sourceFileRef);
// Execute the operation.
FileRef result = compressPDFOperation.Execute(executionContext);
// Save the result to the specified location.
//if pdf is part of a group, the group directory name will be stored in fileGroupDirectory
string fileGroupDirectory = directory.Replace(sourceDir, "");
result.SaveAs(finishedDir + fileGroupDirectory + pdfname);
}
catch (ServiceApiException ex)
{
Console.WriteLine("Exception encountered while executing operation", ex.Message);
if (ex.Message.Contains("The input file is already compressed"))
{
File.Move(file, finishedDir + fileGroupDirectory + fileName);
}
}
I've found a solution , it's not best practice but I don't know an other way to do it.
I've declared all the variables used to execute the compression (sourceFileRef, compressPdfOperation, ...) before the try catch statement and after result.SaveAs(...) I set those variables to null and run the garbage collection.
compressPDFOperation = null;
result = null;
sourceFileRef = null;
executionContext = null;
credentials = null;
GC.Collect();

Xamarin C# android and PARSE - Downloading a parseFile inside a parseObject

I previously made a post asking how to send a .3gpp audio file up to the parse cloud here:
Xamarin C# Android - converting .3gpp audio to bytes & sending to parseObject
I have managed to do this successfully, on parse's data manager, I can click the file's link and play the sound sent from my android device successfully.
Here's the code for uploading the data to the cloud:
async Task sendToCloud(string filename)
{
ParseClient.Initialize ("Censored Key", "Censored Key");
string LoadPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
string savetheFile = sName + ".3gpp";
string tempUserName;
LoadPath += savetheFile;
Console.WriteLine ("loadPath: " + LoadPath);
try
{
byte[] data = File.ReadAllBytes(LoadPath);
ParseFile file = new ParseFile(savetheFile, data);
await file.SaveAsync();
var auidoParseObject = new ParseObject("AudioWithData");
//Console.WriteLine(ParseUser.getUserName());
if (ParseUser.CurrentUser != null)
{
tempUserName = ParseUser.CurrentUser.Username.ToString();
}
else{
tempUserName = "Anonymous";
}
//tempUserName = ParseUser.CurrentUser.Username.ToString();
Console.WriteLine("PARSE USERNAME: " + tempUserName);
auidoParseObject["userName"] = tempUserName;
auidoParseObject["userName"] = tempUserName;
auidoParseObject["file"] = file;
await auidoParseObject.SaveAsync();
}
catch (Exception e)
{
Console.WriteLine("Failed to await audio object! {0}" + e);
}
}
So as you can see, I'm sending a ParseObject called "AudioWithData".
This object contains two children:
-The username of the user who uploaded the file (string)
-The parseFile called "file" (which has the following two children)
---SaveTheFile (A string containing the name of the audio file, input by the user, with the .3gpp extension added on the end, for example "myAudioFile.3gpp"
---data (this contains the bytes of the audio file)
I need to be able to download the file onto my android device, and play it through a mediaplayer object.
I've checked over the documentation on the parse website, but I haven't managed to do this:
(excuse my pseudo querying syntax here)
SELECT (audio files) FROM (the parseObject) WHERE (the username = current user)
I then, eventually, want to place all of these files into a listview, and when the user clicks the file, it plays the audio.
I've tried the following but I don't really know what I'm doing with it...
async Task RetrieveSound(string filename)
{
ParseClient.Initialize ("Censored key", "Censored key");
Console.WriteLine ("Hit RetrieveSound, filename = " + filename);
string username;
var auidoParseObject = new ParseObject("AudioWithData");
if (ParseUser.CurrentUser != null) {
username = ParseUser.CurrentUser.Username.ToString ();
} else {
username = "Anonymous";
}
string cloudFileName;
Console.WriteLine ("username set to: " + username);
var HoldThefile = auidoParseObject.Get<ParseFile>("audio");
//fgher
var query = from audioParseObject in ParseObject.GetQuery("userName")
where audioParseObject.Get<String>("userName") == username
select file;
IEnumerable<ParseFile> results = await query.FindAsync();
Console.WriteLine ("passed the query");
//wfojh
byte[] data = await new HttpClient().GetByteArrayAsync(results.Url);
Console.WriteLine ("putting in player...");
_player.SetDataSourceAsync (data);
_player.Prepare;
_player.Start ();
}
Any help would be GREATLY APPRECIATED! Even a point in the right direction would be great!
Thanks!
EDIT--
I'm actually getting a query error on the following lines
(I can't post images because of my reputation - I lost access to my main stackOverflow account :/ )
Links to images here:
first error: http://i.stack.imgur.com/PZBJr.png
second error: http://i.stack.imgur.com/UkHvX.png
Any ideas? The parse documentation is vague about this.
this line will return a collection of results
IEnumerable<ParseFile> results = await query.FindAsync();
you either need to iterate through them with foreach, or just pick the first one
// for testing, just pick the first one
if (results.Count > 0) {
var result = results[0];
byte[] data = await new HttpClient().GetByteArrayAsync(result.Url);
File.WriteAllBytes(some_path_to_a_temp_file, data);
// at this point, you can just initialize your player with the audio file path and play as normal
}

IO Exception - File In Use By Another Process

C# / .NET 3.5, WindowsForms.
I have this Windows form that displays an image from a file, and whenever user saves the record this code is executed:
string oldLoc = itemsBO.ImageLoc;
if (oldLoc != SystemSettings.NoImageLocation)
{
if (File.Exists(oldLoc))
{
try { File.Delete(oldLoc); }
catch (IOException ex)
{
MessageBox.Show("1 - " + ex.GetType().ToString() + " " + ex.Message);
}
}
}
string saveLoc = itemsBO.ImageSearchLoc + ".jpg";
if (File.Exists(saveLoc))
{
try { File.Delete(saveLoc); }
catch (IOException ex)
{
MessageBox.Show("2 - " + ex.GetType().ToString() + " " + ex.Message);
}
}
try
{
if (pictureBox2.Image != null)
pictureBox2.Image.Save(saveLoc, System.Drawing.Imaging.ImageFormat.Jpeg);
}
catch (IOException ex)
{
MessageBox.Show("3 - " + ex.GetType().ToString() + " " + ex.Message);
}
Disregard the poor MessageBox messages, but it errors out in each Catch statement. It can't delete the "existing" Image because it says it's in use by another process. Can't save because a file exists in that same path because it's not deleting.
This is the code that sets the Image when they try to add a new picture;
Image clipImage = Clipboard.GetImage();
if (tabControl2.SelectedTab == tabPage5)
{
pictureBox1.Image = clipImage;
itemsBO.IsDirtyImage = true;
}
else if (tabControl2.SelectedTab == tabPage6)
{
pictureBox2.Image = clipImage;
itemsBO.IsDirtyImage2 = true;
}
Then when the form loads up an existing record with an image, this is the code used to fetch/display it:
byte[] bits = File.ReadAllBytes(imgfil);
msImage = new MemoryStream(bits, 0, bits.Length);
if (tabControl2.SelectedTab == tabPage5)
pictureBox1.Image = Image.FromStream(msImage);
else if (tabControl2.SelectedTab == tabPage6)
pictureBox2.Image = Image.FromStream(msImage);
imgfil being a path to the image, of course.
Absolutely no idea where to begin...
I have this Windows form that displays an image from a file, and whenever user saves the record
If you're still displaying the image when they save the file, the application will still be accessing the file if I'm not mistaken. Try disposing of the file first, probably by setting the picture box's (or whatever you're using to display the image) image to null, or load a blank picture before you perform the operation.
If it says file in use by another process, well then it must be in use by another process :)
Have you tried monitoring the file lock using Process Explorer.
Once you have identified what's holding your file, close that file handle using Process Explorer and then try to run your code.
This might help-
How to find out what processes have folder or file locked?
So I had inherited this application from another user, turns out the pictureBoxes were having their Image set in another chunk of code independent of that third block of code in the original post. It was because of this that the IOException was happening :(

How to use LockScreen.SetImageUri to Set Windows Phone 8 Lock Screen Background

I have an image in IsolatedStorage, and I would like to programmatically set it as the device lock screen background. My problem is that I cannot get the correct path required by LockScreen.SetImageUri. From referencing http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj206968(v=vs.105).aspx it is evident that `"ms-appdata:///local/" is the required precursor for local images.
var schema = isAppResource ? "ms-appx:///" : "ms-appdata:///Local/";
var uri = new Uri(schema + filePathOfTheImage, UriKind.Absolute);
I have created a folder in my applications IsolatedStorage called Pictures in which jpg images are saved from the CameraCaptureTask. I have tried several ways to access images within this folder via the above scheme but I always receive an ArgumentException on the next line
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(uri);
When debugging, however, I see that uri = "ms-appdata:///Local/Pictures/WP_20130812_001.jpg", how is this not correct?
My implementation is as follows
private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
capturedPicture = (sender as LongListSelector).SelectedItem as CapturedPicture;
if (capturedPicture != null)
{
//filename is the name of the image in the IsolatedStorage folder named Pictures
fileName = capturedPicture.FileName;
}
}
void setAsLockScreenMenuItem_Click(object sender, EventArgs e)
{
if (!String.IsNullOrEmpty(fileName))
{
//PictureRepository.IsolatedStoragePath is a string = "Pictures"
//LockHelper("isostore:/" + PictureRepository.IsolatedStoragePath + "/" + fileName, false); //results in FileNotFoundException
LockHelper(PictureRepository.IsolatedStoragePath + "/" + fileName, false); //results in ArgumentException
}
else
{
MessageBoxResult result = MessageBox.Show("You must select an image to set it as your lock screen.", "Notice", MessageBoxButton.OK);
if (result == MessageBoxResult.OK)
{
return;
}
}
}
private async void LockHelper(string filePathOfTheImage, bool isAppResource)
{
try
{
var isProvider = Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication;
if (!isProvider)
{
// If you're not the provider, this call will prompt the user for permission.
// Calling RequestAccessAsync from a background agent is not allowed.
var op = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();
// Only do further work if the access was granted.
isProvider = op == Windows.Phone.System.UserProfile.LockScreenRequestResult.Granted;
}
if (isProvider)
{
// At this stage, the app is the active lock screen background provider.
// The following code example shows the new URI schema.
// ms-appdata points to the root of the local app data folder.
// ms-appx points to the Local app install folder, to reference resources bundled in the XAP package.
var schema = isAppResource ? "ms-appx:///" : "ms-appdata:///Local/";
var uri = new Uri(schema + filePathOfTheImage, UriKind.Absolute);
// Set the lock screen background image.
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(uri);
// Get the URI of the lock screen background image.
var currentImage = Windows.Phone.System.UserProfile.LockScreen.GetImageUri();
System.Diagnostics.Debug.WriteLine("The new lock screen background image is set to {0}", currentImage.ToString());
}
else
{
MessageBox.Show("You said no, so I can't update your background.");
}
}
catch (System.Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
How might I modify LockScreen.SetImageUri to the proper expected uri?
For setting lock screen images from the app, you might want to declare your app as lock screen provider. You can do that by modifying the WMAppManifest.xml file by adding the following tag:
<Extensions>
<Extension ExtensionName="LockScreen_Background" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default" />
</Extensions>
Check to see if you have this tag in your manifest file.
I hope this could help you to address your issue.
If your app is already installed, make sure that it is an background image provider. If not then go to settings -> lock screen -> background and select your application from the list.
On the programmatic side:
1. Declare the app’s intent in the application manifest file
Edit WMAppManifest.xml with the XML editor, make sure the following extension is present:
<Extensions> <Extension ExtensionName="LockScreen_Background" ConsumerID="{111DFF24-AA15-4A96-8006-2BFF8122084F}" TaskID="_default" /> </Extensions>
2. Write code to change the background image
The following is an example of how you can write the code for setting the background.
private async void lockHelper(Uri backgroundImageUri, string backgroundAction)
{
try
{
//If you're not the provider, this call will prompt the user for permission.
//Calling RequestAccessAsync from a background agent is not allowed.
var op = await LockScreenManager.RequestAccessAsync();
//Check the status to make sure we were given permission.
bool isProvider = LockScreenManager.IsProvidedByCurrentApplication; if (isProvider)
{
//Do the update.
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(backgroundImageUri);
System.Diagnostics.Debug.WriteLine("New current image set to {0}", backgroundImageUri.ToString());
}
else { MessageBox.Show("You said no, so I can't update your background."); }
}
catch (System.Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); }
}
Regarding Uris, there are many options, but keep on mind:
To use an image that you shipped in your app, use ms-appx:///
Uri imageUri = new Uri("ms-appx:///background1.png", UriKind.RelativeOrAbsolute); LockScreen.SetImageUri(imageUri);
To use an image stored in the Local Folder, use ms-appdata:///local/shared/shellcontent
Must be in or below the /shared/shellcontent subfolder
Uri imageUri = new Uri("ms-appdata:///local/shared/shellcontent/background2.png", UriKind.RelativeOrAbsolute); LockScreen.SetImageUri(imageUri);

Methods to process asynchronously received form data

I am having trouble wrapping my head around the async/await functionality in .NET 4.5. I am using the code below in a Web API controller to catch multiple files from a form along with some other form data. I have no control over the form or how it sends the data.
What I want to do is receive the files, get data from the form, read a database based on that form data, move the file(s), and update another database table. With the below code I have no trouble getting the files or form data. I get data from the database based on the formID passed in the form data.
It is when I uncomment the code near the bottom for writing back to the database that I run into issues. If I had three files, only one of them gets moved before the catch block catches an exception. I am assuming that my problem is related to the fact that the PostFile method is async.
What is the proper way of writing this code so that it works?
public async Task<HttpResponseMessage> PostFile()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = GetRootPath();
var provider = new MyMultipartFormDataStreamProvider(root);
string logfile = root + "/form_data_output.txt";
try
{
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
string form_id = provider.FormData.Get("FormId");
string driver_id = GetDriverID(form_id); // returns an int as a string
string location = ConfigurationManager.AppSettings["storagePath"];
location += form_id + "\\";
//// make sure the new directory exists
if (!Directory.Exists(location))
{
Directory.CreateDirectory(location);
}
var keys = provider.FormData.Keys.Cast<string>();
foreach (var k in keys.Where(k => k.StartsWith("FormViewer") == true))
{
string filename = provider.FormData.Get(k) + ".pdf";
string type_key = "FormType_" + k.Substring(k.IndexOf('_') + 1);
string type_value = provider.FormData.Get(type_key);
// setup the full path including filename
string path = root + "\\" + filename;
string newFullPath = location + filename;
// move the file
File.Move(path, newFullPath);
if (File.Exists(newFullPath))
{
if (File.Exists(newFullPath))
{
try
{
string conn_str = ConfigurationManager.ConnectionStrings["eMaintenanceConnection"].ConnectionString;
using (SqlConnection conn = new SqlConnection(conn_str))
{
SqlCommand cmd = new SqlCommand("INSERT INTO eSubmittal_Document VALUES (null,#driver_id,#location,#doctype)");
cmd.Parameters.AddWithValue("#driver_id", driver_id);
cmd.Parameters.AddWithValue("#location", location);
cmd.Parameters.AddWithValue("#doc_type", type_value);
conn.Open();
int c = await cmd.ExecuteNonQueryAsync();
conn.Close();
}
}
catch (Exception e)
{
LogEntry(logfile, e.Message);
}
}
}
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
async and await provide natural program flow for asynchronous code. So for the most part, you can just think about code the way you normally think about it:
It is when I uncomment the code near the bottom for writing back to the database that I run into issues. If I had three files, only one of them gets moved before the catch block catches an exception.
Here's what I get from this:
Your database code is throwing an exception.
When the exception is thrown, it leaves the foreach loop to go to the catch handler.
Nothing unexpected there...
It's hard to help very much without knowing the exception, but performing a synchronous database operation inside an async method seems like a bad idea to me. Try changing your code to use:
int c = await cmd.ExecuteNonQueryAsync();

Categories