Reloading and refreshing flash files inside a windows form - c#

Using DOTNET 3.5 . I have a app which shows load a flash movie in form, using this code
axShockwaveFlash1 = new AxShockwaveFlashObjects.AxShockwaveFlash()
axShockwaveFlash1.LoadMovie(0, Form1.currentGame);
The problem is that whenever I make a changes in the flash hosted in our application and try to refresh the to see the changes, the new changes is 'messed' up. to be more specific , it seems that the background and some controls of the previous flash still remain, 'spoiling' the new flash that is loaded. why?
Using the following methods before loading the second flash video makes no difference
axShockwaveFlash1.Refresh();
axShockwaveFlash1.Stop();

I tried other methods, it doesn't work for me. Here is what I did to achieve the desired result.
private void btnReload_Click(object sender, EventArgs e)
{
byte[] fileContent = File.ReadAllBytes(Application.StartupPath + #"\yourflashfile.swf");
if (fileContent != null && fileContent.Length > 0)
{
using (MemoryStream stm = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stm))
{
/* Write length of stream for AxHost.State */
writer.Write(8 + fileContent.Length);
/* Write Flash magic 'fUfU' */
writer.Write(0x55665566);
/* Length of swf file */
writer.Write(fileContent.Length);
writer.Write(fileContent);
stm.Seek(0, SeekOrigin.Begin);
/* 1 == IPeristStreamInit */
//Same as LoadMovie()
this.axShockwaveFlash1.OcxState = new AxHost.State(stm, 1, false, null);
}
}
fileContent = null;
GC.Collect();
}
}
I copied the core code somewhere in SO but I don't remember the source.

Have you tried loading an "empty" flash video before loading your new video?
e.g.
axShockwaveFlash1.LoadMovie(0,"");
I'm sure that I encountered a similar problem and resolved it this way.

Try this.
Make a blank swf. "Blank.swf" load it first and then re-load your game.
axShockwaveFlash1.LoadMovie(0,"Blank.swf");
axShockwaveFlash1.Play();
axShockwaveFlash1.LoadMovie(0, Form1.currentGame);
axShockwaveFlash1.Play();
Ensure you give the correct path for the Blank.swf.

Related

fo-Dicom - How do I extract image frames from the DicomFile

I need to extract all image frames from a DICOM SC using fo-DICOM. I have a test app that extracts and displays the images, which works fine. However, I need to save the individual images to a database, and am running into problems.
I have the following code so far:
public void SetImages(DicomFile dicom, ThumbResults results)
{
var images = new DicomImage(dicom.Dataset);
for(var count = 0; count < images.NumberOfFrames; count++)
{
var image = images.RenderImage(count).As<Bitmap>();
using(var stream = new MemoryStream())
{
image.Save(stream, ImageFormat.Jpeg);
results.Images.Add(Convert.ToBase64String(stream.ToArray()));
}
}
}
I get a DicomImagingException, "Cannot cast to 'Bitmap'" on images.RenderImage. It works in my test code, when I call PictureBox.Image = _image.RenderImage(count).As<Bitmap>(); so I figure RenderImage must be specifically for rendering (as the name implies).
How should I go about extracting individual frames to a string that will be saved to the database?
In case someone else runs into this problem, the issue was the original code was in .NET Framework, but the new code was in .NET Core. In Core, the ImageManager does not use the WindowsImageManager by default, so you need to set it manually.
ImageManager.SetImplementation(WinFormsImageManager.Instance);

How to close a file opened by another thread?

I've a background thread which loads an image file using Image.FromFile, I want to close the opened image file from another thread
Is there a possibility to close a file opened by a background thread in c#?
Edit:
I used this code at first - on the same thread- but I don't know why I can't free the file or delete it, or even the new file which I saved using img.Save(...). So I tried to force closing on another thread. that's why I'm asking this question.
var img = Image.FromFile(filepath);
img.Save(filepath + ".jpg", ImageFormat.Jpeg);
img.Dispose();
if (File.Exists(filepath+ ".jpg"))
File.Delete(+ ".jpg");
if (File.Exists(filepath))
File.Delete(filepath);
The file isn't "Closed" until the image has been disposed. Open and close the file immediately in a single step by loading the image with the following snippet:
System.Drawing.Bitmap image;
using (var fileLoadImage = System.Drawing.Bitmap.FromFile(#"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg"))
{
image = new System.Drawing.Bitmap(fileLoadImage);
}
You need to be very careful with this pattern though because you are still going to have to explicitly call image.Dispose() when you are finished with your image. At least this will get you around file locking though.
Best of luck!
EDIT - A Runnable Snippet
Copy and paste the following into a new Console application to see that it works. Make sure you have a file called "test.jpg" in your sample pictures before you start and you will see this deletes both the original file and the new file just fine:
public class Program
{
public static void Main(string[] args)
{
System.Drawing.Bitmap image;
var originalFile = #"C:\Users\Public\Pictures\Sample Pictures\test.jpg";
var newFile = #"C:\Users\Public\Pictures\Sample Pictures\test2.jpg";
using (var fileLoadImage = System.Drawing.Bitmap.FromFile(originalFile))
{
image = new System.Drawing.Bitmap(fileLoadImage);
}
image.Save(newFile);
System.IO.File.Delete(originalFile);
image.Dispose();
System.IO.File.Delete(newFile);
}
}

Error Loading and Deleting Images using HTML Input File Control

I desperately need help with an issue I am having while trying load an image or unload an image using ASP/C#. The problem I am having is the first time I run the code and Load the image into the thumbnail, I have no problem but the minute I try to remove the picture or load a second or third image, it takes very very long to hit the event and I get an Out of Memory error. I think something is getting locked and takes a while to get unlocked but I am not sure.
Here is the code I am using:
protected void btnUploadImgPicture1_ServerClick(object sender, EventArgs e)
{
using (filePicture1)
{
if (filePicture1.PostedFile.FileName != "")
{
imageUtil = new ImageUtility();
string realPhysicalPath = Path.Combine(Server.MapPath("~/upload/"), filePicture1.PostedFile.FileName);
filePicture1.PostedFile.SaveAs(realPhysicalPath);
//imgVehiclePicture1.Src = realPhysicalPath;
using (imgVehiclePicture1)
{
imgVehiclePicture1.Attributes["src"] = imageUtil.getBase64String(realPhysicalPath);
Session.Add("Image1", realPhysicalPath);
imageUtil = null;
}
}
}
}
public string getBase64String(string path)
{
Image img = Image.FromFile(path);
byte[] imageBytes = imageToByteArray(img);
string base64String = Convert.ToBase64String(imageBytes, 0, imageBytes.Length);
return "data:image/png;base64," + base64String;
}
I am using this code on 3 times for 3 different events and then I am using similar code to remove the selected image from the upload.
What is ImageUtility? If it implements IDisposable then you might want to try explicitly disposing it instead of setting the variable to null. Even better if you can wrap it inside of a using block.

Deleting a bitmap from local directory

Alright it has come to this. I searched this website among many others and no one can seem to give me a straight answer so I'm going to try just asking outright. Been on this issue for about a solid 3 days and I can't afford to waste any more time on it.
Goal: The app I am building is in WPF and is going to be used as a bug tracker for a project my design team and I will be undertaking soon. Since we are going to be building a game in C++ most of the errors that occur will have a visual element to them so I inlcuded functionality to provide an image of the error in question when the user adds a bug to the list. I then take that image and save it to a local directory (for testing). Now the image path in the Error object points to a path that leads to the local directory. This functionality has been tested and works fine. My problem showes up when I want to delete a bug from the list. I am getting that very infamous "IO Exception" saying that the image I want to delete is being used by another process.
So Far: At first I tried very elegant solutions, but as with all things you get to a point where you just want to see if you can get the thing to even work at all. So I am at the point where most of the code I am using is experimental and radical. So please when looking at it note that the code being used is out of desperation, so any "simple" solutions have probably already been tried (I did research this a lot becuase I hate having to do this). Things i can think of off the top of my head are the obsurd amount of disposes and forced garbage collections being called so please to not comment on the negative nature of this practice, I am well aware :).
The Code
Saving image to local directory
public void OnBrowseClick()
{
Microsoft.Win32.OpenFileDialog openBox = new Microsoft.Win32.OpenFileDialog();
// Show dialog box to user and grab output
Nullable<bool> result = openBox.ShowDialog();
if (result == true)
{
// Create temp variable to hold local path string
string localPath = Directory.GetCurrentDirectory();
// Grab the extension of the specified file path
string extension = openBox.FileName.Substring(openBox.FileName.LastIndexOf("\\"));
// Add extension to local path
localPath += extension;
// Create local copy of image at given file path (being ridiculous at this point)
using (Stream stream = new FileStream(openBox.FileName, FileMode.Open, FileAccess.ReadWrite))
{
using (Bitmap bmp = LoadImage(stream))
{
using (Bitmap temp = (Bitmap)bmp.Clone())
{
temp.Save(localPath);
temp.Dispose();
}
bmp.Dispose();
}
stream.Dispose();
}
// Set the URL in the image text box (UI stuff)
LocalError.ImagePath = localPath;
}
}
The following is the LoadImage function that is used in the function above
private Bitmap LoadImage(Stream stream)
{
Bitmap retval = null;
using (Bitmap bitmap = new Bitmap(stream))
{
retval = new Bitmap(bitmap.Width, bitmap.Height, bitmap.PixelFormat);
using (Graphics gdi = Graphics.FromImage(retval))
{
gdi.DrawImageUnscaled(bitmap, 0, 0);
gdi.Flush();
gdi.Dispose();
bitmap.Dispose();
}
}
// Garbage collection here to be safe
GC.WaitForPendingFinalizers();
GC.Collect();
return retval;
}
And finally we come to where I try to delete the image
public void OnDeleteClick()
{
// Ask user to make sure they want to delete selected item(s)
MessageBoxResult result = MessageBox.Show("Are you sure you want to delete selected item(s) from the list?",
"Delete", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
for( int i = 0; i < Parent.ErrorListControl.ErrorDataGrid.SelectedItems.Count; ++i)
{
// Get path to image
string path = (Parent.ErrorListControl.ErrorDataGrid.SelectedItems[i] as Error).ImagePath;
// Even tried calling garbage collection here!!!!!
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
File.Delete(path);
// Remove the error from the error list
Parent.ErrorListVM.ErrorList.Remove((Error)Parent.ErrorListControl.ErrorDataGrid.SelectedItems[i]);
// Decrement counter because we altered the list while in a loop
i--;
}
}
}
Notes: If anyone would like me to explain anything further or if you need to know something I left out please just ask I will get back to you ASAP! Any suggestions are helpful at this point I have absolutley no idea what I am doing wrong. I generally only program in a C++ environment so I tend to manage my own memory this whole "garbage collection" thing is really throwing a wrench in our project! (Off topic note: I do not know why I am not getting any color highlighting so I apologize to anyone who takes the time to read this).
Here's a simple way to do what you want. In this example, I'm using Path.GetTempFileName() to generate a random file name in the local user's temp directory. If you don't need to persist the files then it's a good place to store them temporarily. Also, the user could theoretically import two files with the same name. So you want to use some kind of random filename generation or other mechanism to avoid conflicts.
private void browseButton_Click(object sender, RoutedEventArgs e)
{
var openFileDialog = new Microsoft.Win32.OpenFileDialog();
if (openFileDialog.ShowDialog(this) == true)
{
using (Bitmap originalImage = new Bitmap(openFileDialog.FileName))
{
string tempFileName = System.IO.Path.GetTempFileName();
originalImage.Save(tempFileName);
// LocalError.LocalPath
LocalPath = tempFileName;
}
}
}
private void deleteButton_Click(object sender, RoutedEventArgs e)
{
if (File.Exists(LocalPath))
{
File.Delete(LocalPath);
}
}
Although a simple File.Copy should suffice as long as you have the right paths, I was just providing a solution that matched your question.
EDIT:
Actually the current directory does not seem to be changed by the OpenFileDialog. I could swear that it did at some point. So I don't think this is your problem. Regardless, this code still works for me and you shouldn't require anything more complicated than this.
EDIT #2:
It seems the lock is actually caused by the image being databound to the view and presumably locked by the BitmapSource. You should be able to create it without locking the file. Generally, this is slower so don't do it this way unless you need to be able to modify or delete the file.
bitmapSource = new BitmapImage();
bitmapSource.BeginInit();
bitmapSource.CacheOption = BitmapCacheOption.OnLoad;
bitmapSource.CreateOption = BitmapCreateOptions.IgnoreImageCache;
bitmapSource.UriSource = new Uri(ImagePath, UriKind.Absolute);
bitmapSource.EndInit();
Since your LoadImage method does simple copy of the image, why not use File.Copy(source, dest) and avoid all the bitmaps, drawings, etc? Your goal might be to modify local bitmap after it's created, but it can still be done after copy.
Also, when using the using block, explicit .Dispose() is not required, as using block does it for you:
using (var obj = new SomeDisposableObject())
{
// code here
// obj.Dispose(); <-- not needed, since...
} // ...at this point obj.Dispose is called automatically.

Loading a Flash movie from a memory stream or a byte array

I want to load an SWF object from a Memory Stream or a byte array instead of a file on disk.
AxShockwaveFlash class provides methods and properties to load an SWF providing its path to disk as a string but I haven't seen another way of doing it. There is an InlineData property but generally the class is undocumented and I don't know what this property does. Can it be done at all?
Thanks
F
I assume what you are wanting to do is initialize this in C# rather than in Flash itself. It can be done but there are limitations to doing it (for example you may get weird security issues). Another caveat is this has only been tested on VS 2010/Flash 10 but it should work in any version in theory.
Okay, let us assume you have used the standard mechanism to put your flash control on the form. Also add the flash file you want to the resources (or an inline byte array, up to you).
Then use the following code to load the flash file.
private void InitFlashMovie(AxShockwaveFlash flashObj, byte[] swfFile)
{
using (MemoryStream stm = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stm))
{
/* Write length of stream for AxHost.State */
writer.Write(8 + swfFile.Length);
/* Write Flash magic 'fUfU' */
writer.Write(0x55665566);
/* Length of swf file */
writer.Write(swfFile.Length);
writer.Write(swfFile);
stm.Seek(0, SeekOrigin.Begin);
/* 1 == IPeristStreamInit */
flashObj.OcxState = new AxHost.State(stm, 1, false, null);
}
}
}
Pass the form's flash object and the byte array containing the flash file to load and it should work.
you are the manthank you very much i was searching for it but didn't find except for native c++, i tried it and it worked well
private:void initflash(AxShockwaveFlashObjects::AxShockwaveFlash^ax,array<System::Byte>^data)
{
MemoryStream^ ms=gcnew MemoryStream();
BinaryWriter^ bwr=gcnew BinaryWriter(ms);
bwr->Write(8+data->Length);
bwr->Write(0x55665566);
bwr->Write(data->Length);
bwr->Write(data);
ms->Seek(0,SeekOrigin::Begin);
ax->OcxState=gcnew AxHost::State(ms,1,false,nullptr);
bwr->Close();
delete bwr;
ms->Close();
delete ms;
}
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
axShockwaveFlash1->FlashVars="indextext=courses/en0600000000/launch.text.xml&cid=0600000000&l1=en&l2=none";
array<System::Byte>^data= File::ReadAllBytes("F:\\Learning\\unformated\\New Folder (3)\\CCNA\\theme\\index.swf");
initflash(axShockwaveFlash1,data);
SubclassHWND^ s=gcnew SubclassHWND();
s->AssignHandle(axShockwaveFlash1->Handle);
}
the last two lines i'm using the following class to prevent right click menu
ref class SubclassHWND :public NativeWindow
{
public:
SubclassHWND(){}
protected:
virtual void WndProc(Message %m) override
{
if(m.Msg==0x204)
{
return;
}
NativeWindow::WndProc(m);
}
};
VB.net Version:
first add reference to AxShockwaveFlash
Then add this code.
Dim swfFile As Byte() = IO.File.ReadAllBytes("C:\Users\root\source\file.swf")
Using stm As MemoryStream = New MemoryStream()
Using writer As BinaryWriter = New BinaryWriter(stm)
writer.Write(8 + swfFile.Length)
writer.Write(&H55665566)
writer.Write(swfFile.Length)
writer.Write(swfFile)
stm.Seek(0, SeekOrigin.Begin)
AxShockwaveFlash1.OcxState = New AxHost.State(stm, 1, False, Nothing)
End Using
End Using

Categories