I'm implementing "copy map to clip" as an image.
what I do is I create an image an save it to certain directory and copy it to clipboard.
but before I do that I delete every file that exist in the directory, but now I cant since, the image is being used by clipboard.
here's my code.
public override void OnClick()
{
//base.OnClick();
DeleteOldCopiedJPG();
System.Windows.Forms.Clipboard.Clear();
string fileName = System.Windows.Forms.Application.ExecutablePath.Substring(0, System.Windows.Forms.Application.ExecutablePath.LastIndexOf("\\") + 1) + Guid.NewGuid() + ".jpg";
//System.Windows.Forms.Cursor.Current = Cursors.Wait;
//if (System.IO.File.Exists(fileName))
// System.IO.File.Delete(fileName);
IExport objExport = (IExport)new ExportJPEG();
objExport.ExportFileName = fileName;
#if Debug || Release
ESRI.ArcGIS.Display.tagRECT objExportRECT = default( ESRI.ArcGIS.Display.tagRECT);
#else
tagRECT objExportRECT = default(tagRECT);
#endif
var _with1 = objExportRECT;
_with1.left = mapControl.ActiveView.ExportFrame.left;
_with1.top = mapControl.ActiveView.ExportFrame.top;
_with1.right = mapControl.ActiveView.ExportFrame.right;
_with1.bottom = mapControl.ActiveView.ExportFrame.bottom;
IEnvelope envelope = new EnvelopeClass();
envelope.PutCoords(mapControl.ActiveView.ExportFrame.left, mapControl.ActiveView.ExportFrame.top,
mapControl.ActiveView.ExportFrame.right, mapControl.ActiveView.ExportFrame.bottom);
objExport.PixelBounds = envelope;
System.Int32 intHDC = objExport.StartExporting();
mapControl.ActiveView.Output(intHDC, Convert.ToInt16(objExport.Resolution), objExportRECT, null, null);
objExport.FinishExporting();
objExport.Cleanup();
System.Drawing.Image objImage = System.Drawing.Bitmap.FromFile(fileName);
System.Windows.Forms.Clipboard.SetImage(objImage);
//RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
//renderTargetBitmap.Render((Visual)mapControl.ActiveView.ScreenDisplay);
//Clipboard.SetImage(renderTargetBitmap);
}
private void DeleteOldCopiedJPG(string Path)
{
string[] filePaths = Directory.GetFiles(System.Windows.Forms.Application.ExecutablePath.Substring(0, System.Windows.Forms.Application.ExecutablePath.LastIndexOf("\\") + 1));
foreach (string filepath in filePaths)
if (filepath.Substring(filepath.Length - 4) == ".jpg")
try{ File.Delete(filepath); } catch {}
}
You need to dispose the image after inserting it into the clipboard:
using (System.Drawing.Image objImage = System.Drawing.Bitmap.FromFile(fileName))
{
System.Windows.Forms.Clipboard.SetImage(objImage);
}
Otherwise it will remain open until the garbage collector calls the finalizer for objImage.
Related
When I am saving an image, it is getting saved by the Barcode name.
But If I modify the barcode name, then the image is gone, not saving.
I have noticed while debugging that the if(System.IO.File.Exists(imageFilePath)) is not executing when I am updating the barcode. But at the time of saving a new one, its executing.
How to correct this?
Updating code
public object Update(ItemEntity item)
{
var val = _itemRepository.Save(item);
if (item.ImageFileName != string.Empty || item.ImageOriginalFileName != string.Empty)
{
string result = JsonConvert.SerializeObject(val);
var definition = new { Success = false, EntryMode = string.Empty, BarCode = string.Empty, ItemCode = string.Empty };
var info = JsonConvert.DeserializeAnonymousType(result, definition);
if (info.Success)
{
if (!string.IsNullOrEmpty(item.ImageOriginalFileName))
this.SaveImage(item.ImageFileName, (item.ImageOriginalFileName == "BARCODE" ? info.ItemCode : item.ImageOriginalFileName == "BARCODEYes" ? item.Barcode : item.ImageOriginalFileName));
}
}
if (item.DeleteImageFileName != string.Empty && item.ImageFileName == string.Empty) // Image file removed but no new image file is uploaded[Bug Id :34754 -No image is uploaded, when a user re-uploads an image after deleting a previous one.]
{
this.DeleteImage(item.DeleteImageFileName);
}
return val;
}
Saving Code
public void SaveImage(string fileName, string originalFileName)
{
string tempFileName = fileName;
if (!string.IsNullOrEmpty(tempFileName))
{
// move file from temp location to actual loation
var webAppPath = System.Web.Hosting.HostingEnvironment.MapPath("~");
var splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
var upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
var UIFolder = "WebUI";
splitPath.AddRange(new string[] { UIFolder, "Temp", "ImageUpload", CurrentSession.UserId.Value.ToString(), "ItemImage" });
var webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
var imageFilePath = Path.Combine(webUIPath.EnsureEndsWith('\\'), tempFileName);
if (System.IO.File.Exists(imageFilePath))
{
splitPath = webAppPath.Split("\\".ToCharArray()).ToList();
upLevel = splitPath.Count - 1; // one level up
splitPath = splitPath.Take(upLevel).ToList();
splitPath.AddRange(new string[] { "Shared", "ItemImage" });
webUIPath = splitPath.Aggregate((i, j) => i + "\\" + j);
// Check existence of folder, create if not found and Delete-Create if found
if (!Directory.Exists(webUIPath))
{
Logger.Debug("Create directory :" + webUIPath);
Directory.CreateDirectory(webUIPath);
}
originalFileName = originalFileName + ".jpg";
var imagDestPath = Path.Combine(webUIPath.EnsureEndsWith('\\'), originalFileName);
if (File.Exists(imagDestPath))
{
GC.Collect();
GC.WaitForPendingFinalizers();
Logger.Debug("Delete File :" + imagDestPath);
File.Delete(imagDestPath);
}
byte[] bytes = System.IO.File.ReadAllBytes(imageFilePath);
FileStream fs = new FileStream(imagDestPath, FileMode.Create, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(bytes);
bw.Close();
}
}
}
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);
}
}
I want to watermark files in a folder with another image. However, am getting the error
'Parameter Not Valid'
when invoking the code
img.Save(filepath, System.Drawing.Imaging.ImageFormat.Jpeg);
I have the following code;
public static string WatermarkImagesInFolder(string url)
{
if (url == null)
throw new Exception("URL must be provided");
string path = HttpContext.Current.Server.MapPath(url);
if (!Directory.Exists(path))
throw new DirectoryNotFoundException();
Directory.CreateDirectory(String.Format(#"{0}\watermarked", path));
List<string> urls = GetJpgFilesFromFolder(path);
foreach (string imageUrl in urls)
{
Image img = WatermarkImage(imageUrl);
string filename = Path.GetFileName(imageUrl);
string filepath = String.Format(#"{0}\watermarked\{1}", path, filename);
img.Save(filepath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
return "complete";
}
and
public static Image WatermarkImage(string filename)
{
using (Image image = Image.FromFile(filename))
using (Image watermarkImage = Image.FromFile(HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["WatermarkImageUrl"])))
using (Graphics imageGraphics = Graphics.FromImage(image))
using (TextureBrush watermarkBrush = new TextureBrush(watermarkImage))
{
int x = (image.Width / 2 - watermarkImage.Width / 2);
int y = (image.Height / 2 - watermarkImage.Height / 2);
watermarkBrush.TranslateTransform(x, y);
imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(x, y), new Size(watermarkImage.Width + 1, watermarkImage.Height)));
return image;
}
}
as an example of input for img.save;
img.save("C:\\IMAGES\\wateremarked\\IMAGE (1).jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
any ideas on what could be causing the error here please?
In your WatermarkImage you have the image object in a using statement. As soon as that goes out of scope, Dispose is invoked on the image. You would need to return a copy of the image - or not use the using statement & ensure you dispose properly later.
See : Exception: Parameter is not valid (on passing new image to pictureBox)
public static string WatermarkImagesInFolder(string url)
{
if (url == null)
throw new Exception("URL must be provided");
string path = HttpContext.Current.Server.MapPath(url);
if (!Directory.Exists(path))
throw new DirectoryNotFoundException();
Directory.CreateDirectory(String.Format(#"{0}\watermarked", path));
List<string> urls = GetJpgFilesFromFolder(path);
foreach (string imageUrl in urls)
{
using(Image img = WatermarkImage(imageUrl))
{
string filename = Path.GetFileName(imageUrl);
string filepath = String.Format(#"{0}\watermarked\{1}", path, filename);
img.Save(filepath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
return "complete";
}
public static Image WatermarkImage(string filename)
{
Image image = Image.FromFile(filename);
using (Image watermarkImage = Image.FromFile(HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings["WatermarkImageUrl"])))
using (Graphics imageGraphics = Graphics.FromImage(image))
using (TextureBrush watermarkBrush = new TextureBrush(watermarkImage))
{
int x = (image.Width / 2 - watermarkImage.Width / 2);
int y = (image.Height / 2 - watermarkImage.Height / 2);
watermarkBrush.TranslateTransform(x, y);
imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(x, y), new Size(watermarkImage.Width + 1, watermarkImage.Height)));
return image;
}
}
Here is my alternative solution, which gives the ability to use picture stream, but not it's location as it's currently browsed from Kendo Control as in my example and it still have not physical location yet.
public static Image ApplyWatermark(HttpPostedFileBase img, string appDataPath)
{
Image resultImage = null;
using (Image image = Image.FromStream(img.InputStream))
{
using (Image watermarkImage = Image.FromFile(appDataPath + "\\Watermark\\sample-watermark.png"))
{
using (Graphics imageGraphics = Graphics.FromImage(image))
{
using (Brush watermarkBrush = new TextureBrush(watermarkImage))
{
imageGraphics.FillRectangle(watermarkBrush, new Rectangle(new Point(0, 0), image.Size));
resultImage = (Image)image.Clone();
}
}
}
}
return resultImage;
}
private void SaveImagesOnDisk(IEnumerable<HttpPostedFileBase> images, int rentalPropertyId)
{
if (images != null)
{
foreach (var file in images)
{
// Some browsers send file names with full path. This needs to be stripped.
var fileName = Path.GetFileName(file.FileName);
var appDataPath = this.Server.MapPath("~/App_Data/");
var newPath = Path.Combine(appDataPath, rentalPropertyId.ToString());
if (!Directory.Exists(newPath))
{
DirectoryInfo di = Directory.CreateDirectory(newPath);
}
var physicalPath = Path.Combine(newPath, fileName);
System.Drawing.Image markedImage = Helper.ApplyWatermark(file, appDataPath);
markedImage.Save(physicalPath, System.Drawing.Imaging.ImageFormat.Png);
}
}
//return this.Json(new { status = "OK" }, "text/plain");
}
I am first creating Bitmap image file and saving it to some temp location. Later using that file to read in BitmapImage object to compare it with other file. Once comparison is done, I want to delete file but then it throws exception that file is being used by another process. How can I delete this file?
Here is my code:
private void btnLogin_Click(object sender, EventArgs e)
{
string strPath = AppDomain.CurrentDomain.BaseDirectory;
GC.Collect();
if (txtLoginImage.Text != "")
{
string strFileName = txtLoginImage.Text.Substring(txtLoginImage.Text.LastIndexOf('\\') + 1);
Bitmap MainImg = new System.Drawing.Bitmap(txtLoginImage.Text);
Bitmap NewImage = ConvertToGrayScale(MainImg);
NewImage.Save(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" + strFileName, System.Drawing.Imaging.ImageFormat.Bmp);
NewImage.Dispose();
Uri SourceUri = new Uri(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" + strFileName);
BitmapImage source = new BitmapImage();
source.UriSource = SourceUri;
IrisSystem.Class.BLL.User_BLL ubll = new IrisSystem.Class.BLL.User_BLL();
DataSet dsUserData= ubll.getlist();
bool isMatchFound = false;
if (dsUserData != null && dsUserData.Tables.Count > 0)
{
foreach (DataRow item in dsUserData.Tables[0].Rows)
{
Uri TargetUri = new Uri(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Grayscale\\" + item["GrayScaleImgName"]);
BitmapImage Target = new BitmapImage(TargetUri);
if (source.IsEqual(Target))
{
IrisSystem.frmHome frm= new IrisSystem.frmHome();
frm.strFullName = item["FullName"].ToString();
frm.ShowDialog();
Form.ActiveForm.Close();
isMatchFound = true;
break;
}
Target = null;
}
if (!isMatchFound)
MessageBox.Show("Invalid Credential..","Invalid Operation");
}
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" + strFileName);
}
else
MessageBox.Show("Please select image", "Login Error");
}
You need to make sure that your Bitmap objects are disposed properly.
You are not disposing the MainImg object. you need to use using {} block to make sure that objects are disposed properly.
Replace This:
Bitmap MainImg = new System.Drawing.Bitmap(txtLoginImage.Text);
Bitmap NewImage = ConvertToGrayScale(MainImg);
NewImage.Save(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\"
+ strFileName, System.Drawing.Imaging.ImageFormat.Bmp);
NewImage.Dispose();
With This:
using(Bitmap MainImg = new System.Drawing.Bitmap(txtLoginImage.Text))
using(Bitmap NewImage = ConvertToGrayScale(MainImg))
{
NewImage.Save(AppDomain.CurrentDomain.BaseDirectory + "\\Images\\Temp\\" +
strFileName, System.Drawing.Imaging.ImageFormat.Bmp);
}
EDIT:
Replace This:
BitmapImage source = new BitmapImage();
source.UriSource = SourceUri;
With This:
BitmapImage source = new BitmapImage();
source.BeginInit();
source.UriSource = SourceUri;
source.EndInit();
Imagename = objUser.UserID + filename;
Imagepath = "D:\\Shop\\ShopMonkey\\Images" + Imagename;
FileUpload.SaveAs(Path.Combine(#"D:\ShopMonkey_Web_21-6-12\ShopMonkey\Images", Imagename));
objUser.UploadImagePath = Imagepath;
objUser.UploadImagename = Imagename;
System.Drawing.Image img1 = System.Drawing.Image.FromFile(Imagepath);
System.Drawing.Image bmp1 = img1.GetThumbnailImage(50, 50, null, IntPtr.Zero);
ThumbNailPath = "D:\\ShopMonkey_Web_21-6-12\\ShopMonkey\\ThumbNails" + Imagename;
bmp1.Save(Path.Combine(#"D:\ShopMonkey_Web_21-6-12\ShopMonkey\ThumbNails", Imagename));
objUser.UploadThumbnailPath = ThumbNailPath;
How to delete the image and thumbnail in other function? (Is it necessary to close that first or not?)
I'm guessing that you're trying to delete a file on disk if it already exists for this user upon asp.net upload of an image by that same user again.
This method will delete both image and thumbnail if they exist.
Keep your image creation activities separate from your image clean up activities to keep your intent clear and your code maintainable.
// replace with an entry loaded from a config file
const string ImageRoot = #"D:\ShopMonkey_Web_21-6-12\ShopMonkey";
// replace this is your user instance
object user = new object();
string Imagename = objUser.UserID + filename;
string uploadImagePath = Path.Combine(ImageRoot, "Images", Imagename);
string thumbnailPath = Path.Combine(ImageRoot, "ThumbNails", Imagename);
objUser.UploadImagePath = uploadImagePath;
objUser.UploadImagename = Imagename;
objUser.UploadThumbnailPath = thumbnailPath;
// delete both if they exist
if (File.Exists(uploadImagePath))
File.Delete(uploadImagePath);
if (File.Exists(thumbnailPath))
File.Delete(thumbnailPath);
// replace this with your uploaded file details
object fileInfo = new object();
using (System.Drawing.Image img1 = System.Drawing.Image.FromFile(uploadImagePath)) {
img1.Save(uploadImagePath);
using (System.Drawing.Image bmp1 = img1.GetThumbnailImage(50, 50, null, IntPtr.Zero)) {
bmp1.Save(thumbnailPath);
}
FileUpload.SaveAs(uploadImagePath);
}