I am making a simple app which will show the images from a specific folder on a winform load.
I've done the "showing part" with using openfileDialog and it's working fine, where the user has to select images each time.I want to make it more automatic that user doesn't have to select the files, It should select the files automatically.
Target Folder is static(It'll remain same) while it contains multiple images.
How can I obtain all of the image files from the directory?
I am using this code.
string[] path = Directory.GetFiles("Cards");
foreach (string filepath in path)
{
string[] files = filepath;
int x = 20;
int y = 20;
int maxheight = -1;
foreach (string img in files)
{
PictureBox pic = new PictureBox();
pic.Image = Image.FromFile(img);
pic.Location = new Point(x, y);
pic.Size = new Size(200, 200);
pic.SizeMode = PictureBoxSizeMode.Zoom;
x += pic.Width + 10;
maxheight = Math.Max(pic.Height, maxheight);
if (x > this.ClientSize.Width - 100)
{
x = 20;
y += maxheight + 10;
}
this.panelImages.Controls.Add(pic);
}
}
but stuck at string[] files = filepath; here.
Please guide me where I am making any mistake.
Please let me know if anybody needs more info.
Thanks in advance.
Consider changing:
string[] path = Directory.GetFiles("Cards");
foreach (string filepath in path)
{
string[] files = filepath;
to:
string[] files = Directory.GetFiles("Cards");
Then your later:
foreach (string img in files)
will iterate over all file in the Cards folder.
There are some dangers in passing in just "Cards" as a parameter, as per the docs:
Relative path information is interpreted as relative to the current
working directory.
It would be better, if possible, to pass an absolute path.
Related
I want to show images with gps tags on form. User click on image than I show gps location from the image on statusbar. I loaded some image files(for example, 40) and get exception - OutOfMemory.
File jpeg have size - 5Mb, after Image.FromFile disappear 50 Mb memory.
Example,
1) run application - memory - 50Mb
2) select 5 image files(25Mb) - memory - 316Mb(!?)
3) click on image in ListView,rise event listView1_SelectedIndexChanged, show gps location - memory - 43Mb(GC did his good job)
How do I load images without big memory?
If I call
image.Dispose();
after
imageList1.Images.Add(image);
there is no images on Form
Code load images:
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
ofd.Filter = "Images (*.jpg, )|*.jpg";
ofd.Title = "Select files";
if (ofd.ShowDialog() != DialogResult.OK)
return;
ListPathFoto.Clear();
foreach (string f in ofd.FileNames)
{
ListPathFoto.Add(f);
}
imageList1.Images.Clear();
foreach (var oneFilePath in ListPathFoto)
{
var image = Image.FromFile(oneFilePath);
imageList1.Images.Add(image);
}
listView1.Clear();
listView1.View = View.LargeIcon;
imageList1.ImageSize = new Size(32, 32);
listView1.LargeImageList = imageList1;
for (int j = 0; j < imageList1.Images.Count; j++)
{
ListViewItem item = new ListViewItem
{
ImageIndex = j
};
listView1.Items.Add(item);
}
Thank you for comments. Thanks to them i found a solution.
Solution is - add Thumbnail instead Image
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Multiselect = true;
ofd.Filter = "Файлы изображений (*.jpg, )|*.jpg";
ofd.Title = "Выберите файлы изображений";
if (ofd.ShowDialog() != DialogResult.OK)
return;
ListPathFoto.Clear();
foreach (string f in ofd.FileNames)
{
ListPathFoto.Add(f);
}
}
imageList1.ImageSize = new Size(32, 32);
imageList1.Images.Clear();
foreach (var oneFilePath in ListPathFoto)
{
var image = Image.FromFile(oneFilePath);
Image thumb = image.GetThumbnailImage(32, 32, () => false, IntPtr.Zero);
imageList1.Images.Add(thumb);
image.Dispose(); // important for clear memory
}
listView1.Clear();
listView1.View = View.LargeIcon;
listView1.LargeImageList = imageList1;
for (int j = 0; j < imageList1.Images.Count; j++)
{
ListViewItem item = new ListViewItem
{
ImageIndex = j
};
listView1.Items.Add(item);
}
Apart from answer what you have found, ideally you should not be loading all images at once . Say you have 100 images to load, if you load all images at once you are at high risk of getting OOM exception .
In this case it is advisable to use lazy loading mechanism . Load only say 10 images at first and as you scroll down load remaining 10 or whatever the feasible number and dispose previously loaded 10 .
How to add watermark image while uploading image in asp.net mvc.
I am using jquery.uploadfile.min.js multiple file upload for uploading image.
Want to add automatically stored logo image (watermark) to append in my image file that i am going to upload.
IN VIEW:
var errorOccured = false;
$(function () {
var uploadObj = $("#multipleupload").uploadFile({
url: "./Handler.ashx",
multiple: true,
fileName: "myfile",
maxFileSize: 1024 * 5000,
allowedTypes: "jpg,jpeg,gif,png",
autoSubmit: false,
formData: { "FunctionName": "UploadProductImage", "ProductID": '#clsEncrypt.Encrypt(ViewBag.ProductID.ToString())' }, //"ImgResizeOption": ImgResizeOption
afterUploadAll: function () {
if (!errorOccured) {
window.location.href = 'ProductImage?Product=#(clsEncrypt.Encrypt(ViewBag.ProductID.ToString()))';
}
},
onError: function (files, status, errMsg) {
alert('file(s) could not be uploaded. Error: ' + errMsg);
errorOccured = true;
}
});
$("#startUpload").click(function () {
uploadObj.startUpload();
});
});
IN HANDLER :
public void UploadProductImage()
{
int ProductID = Convert.ToInt32(clsEncrypt.Decrypt(HttpContext.Current.Request["ProductID"]));
string PhysicalFolderPath = "~/Images/Product/";
for (int j = 0; j < HttpContext.Current.Request.Files.Count; j++)
{
HttpPostedFile uploadFile = HttpContext.Current.Request.Files[j];
string extention = System.IO.Path.GetExtension(uploadFile.FileName);
UploadPic(uploadFile, j++, PhysicalFolderPath, ProductID);
}
}
protected void UploadPic(HttpPostedFile FUPhoto, int sort, string RemotePath, int ProductID)
{
if (FUPhoto.FileName != "")
{
string ImgUploadResponse = "";
string strExt = Path.GetExtension(FUPhoto.FileName).Trim().ToLower();
string ImageName = DateTime.Now.ToFileTimeUtc() + strExt;
string OriginalImageFullPath = "~/Images/Product/" + ImageName;
if (Directory.Exists(HttpContext.Current.Server.MapPath("~/Images/Product/")).Equals(false))
Directory.CreateDirectory(HttpContext.Current.Server.MapPath("~/Images/Product/"));
FUPhoto.SaveAs(HttpContext.Current.Server.MapPath(OriginalImageFullPath));
ProductImageEntity objProdImage = new ProductImageEntity();
objProdImage.ProductID = ProductID;
if (ImgUploadResponse != "")
objProdImage.Image = "";
else
objProdImage.Image = ImageName;
if (!String.IsNullOrEmpty(objProdImage.Image))
new ProductImageBLL().InsertUpdateProductImage(objProdImage);
}
}
Please refer the below code for watermark logo to add from code side.
using (Image image = Image.FromFile(#"C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"))
using (Image watermarkImage = Image.FromFile(#"C:\Users\Public\Pictures\Sample Pictures\watermark.png"))
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)));
image.Save(#"C:\Users\Public\Pictures\Sample Pictures\Desert_watermark.jpg");
}
I have installed and tried your dll. Everything is good but one issue. The watermark text is added vertically to vertical images (images whose height is bigger than width). Better solution is to add watermark in a horizantal line to vertical images as well as horizantal images. Thanks anyway.
--Edit--
I have solved the problem within this code, which checks and changes the orientation of the image in need. (uploadedImage is the image that i read from stream)
if (uploadedImage.PropertyIdList.Contains(0x0112))
{
PropertyItem propOrientation = uploadedImage.GetPropertyItem(0x0112);
short orientation = BitConverter.ToInt16(propOrientation.Value, 0);
if (orientation == 6)
{
uploadedImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
}
else if (orientation == 8)
{
uploadedImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
}
else
{
// Do nothing
}
}
Recently I've published a nugget package that do add image water mark with control over opacity and target spot to place the watermark in. Additionally you can add text watermark and do image crop/resize as well.
install via nugget:
Install-Package LazZiya.ImageResize
then you can use the code as below:
//get image from local path
var img = Image.FromFile("wwwroot\\images\\lum3n-358833-unsplash.jpg");
//scale and crop, 600x250 center focus
var newImg = ImageResize.ScaleAndCrop(img, 600, 250, TargetSpot.Center);
//watermark image path
var imgWatermark = "wwwroot\\images\\icon.png";
//add image watermark
newImg.ImageWatermark(imgWatermark,
TargetSpot.TopRight, //define target spot
10, //margin
37); //opacity (0-100)
//save new image
newImg.SaveAs("wwwroot\\images\\600x250-image-watermark.jpg");
//dispose to free up memory
img.Dispose();
newImg.Dispose();
[UPDATE]
The package is updated and some methods has been changed, and better support for more image formats is available (including animated gif).
See the docs for more details.
see live demo page.
I'm using Movie Maker Timeline Control in C# to try and randomize the order of pictures in Windows Movie Maker. I have the form set up, but I seem to encounter a problem with the importing of photos. My code needs to be able to import multiple randomly named images (ex: IMG_xxxx.JPG). I'm able to individually import a specifically named image, but when I try to use a foreach loop, it fails.
My code:
private void btnOpen_Click(object sender, EventArgs e)
{
openFolder.Description = "Open a folder containing pictures for the slideshow!";
if (openFolder.ShowDialog() == DialogResult.OK)
{
// this code right here
string folderPath = openFolder.SelectedPath;
string[] fileArray = Directory.GetFiles(folderPath, "*.JPG");
foreach (string file in fileArray)
{
folderPath = folderPath + "\\" + file;
float duration = 4;
float startpos = 0;
timelineControl.AddImageClip(timelineControl.GetImageTrackIndex(), folderPath, startpos, (startpos + duration));
startpos = startpos + 4;
}
/* string image = "C:\\Users\\OSR\\Desktop\\jpgs\\img.JPG";
float duration = 4;
timelineControl.AddImageClip(timelineControl.GetImageTrackIndex(), image, 0, duration);
*/
}
else
{
MessageBox.Show("Next time, select a folder and click open!", "Selection Cancelled", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Full code: https://pastebin.com/MrB928Ri
Program: http://imgur.com/a/bikxU
You are destroying the folderPath in the loop:
var folderPath = openFolder.SelectedPath;
var fileArray = Directory.GetFiles(folderPath, "*.JPG");
float duration = 4;
float startpos = 0;
foreach (var file in fileArray) {
var filePath = $#"{folderPath}\{file}";
timelineControl.AddImageClip(timelineControl.GetImageTrackIndex(), filePath, startpos, (startpos + duration));
startpos += 4;
}
In in powerpoint i have placed some diagrams diagrams, where each diagram contains different guid.And i have set the GUID as their hyperlink. when the refresh button is clicked what i do is ,will find the shape and then will get the guid which i have saved as hyperlink for each image , from each image and using that GUID will replace the recent image with the old image in that shape.
foreach (var shape in presentation.Slides[slideno].Shapes)
{
var slide = (PPT.Slide)item;
if (j <= shapeCount)
{
string[] address = new string[] { };
string dskj = slide.Shapes[j].Name;
if (slide.Shapes[j].Name.Equals("DIAGRAM")//, StringComparison.InvariantCultureIgnoreCase)
&& slide.Shapes[j].ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address != null)
{
address = slide.Shapes[j].ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address.Split('*');
string Type = address[0];
string Guid = address[1];
if (Type == "D")
{
Session.path = presentation.Path;
if (Session.path != "")
Session.Repository.GetProjectInterface().PutDiagramImageToFile(address[1], Session.path + "\\" + address[1] + ".jpg", 1);
bool diagrm = false;
try
{
EA.Diagram diag = Session.Repository.GetDiagramByGuid(Guid);
diagrm = true;
}
catch
{
continue;
}
if (diagrm)
{
float Shapeleft = slide.Shapes[j].Left;
float Shapetop = slide.Shapes[j].Top;
float Shapewidth = slide.Shapes[j].Width;
float Shapeheight = slide.Shapes[j].Height;
slide.Shapes[j].Delete();
PPT.Shape pic = slide.Shapes.AddPicture(Session.path + "\\" + Guid + ".jpg", Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoTrue, Shapeleft, Shapetop, Shapewidth, Shapeheight);
pic.Name = "DIAGRAM";
pic.ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address = "D*" + Guid;
}
}
}
}
using this above code everything works great.
address = slide.Shapes[j].ActionSettings[PPT.PpMouseActivation.ppMouseClick].Hyperlink.Address
in address i will get the hyperlink address of that current image,but now my problem is if i have two images in a same single slide , then both the time when it loops inside the shapes it only gives the same hyperlink for both the images.
**NOTE:**If i have only one image in a slide then everything works properly.
Its because you're deleting the previous shape and inserting a new shape at the same place , but each shape contains a ZOrderPosition , where because of you deleted the previous and inserted a new shape the Zorderposition get changed for the new shape and it will be included in the next iteration.So if more than one image is inserted in a shape it only refrsh some images .
SOLUTION:
After deleting the existing and when inserting a new shape set its ZorderPosition also.
pic.ZOrder(MsoZOrderCmd.msoSendToBack);
Hope it works..!!
Here is my Code, I am trying to stitch two pictures together and as soon as I get to line 42 "Image img = Image.FromFile(file.FullName);" I get an out of memory error. What should I do?
namespace Practicing_Stiching
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void cmdCombine_Click(object sender, EventArgs e)
{
//Change the path to location where your images are stored.
DirectoryInfo directory = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Images");
if (directory != null)
{
FileInfo[] files = directory.GetFiles();
CombineImages(files);
}
}
private void CombineImages(FileInfo[] files)
{
//change the location to store the final image.
string finalImage = #"C:\Users\Elder Zollinger\Desktop\Images";
List<int> imageHeights = new List<int>();
int nIndex = 0;
int width = 0;
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
imageHeights.Add(img.Height);
width += img.Width;
img.Dispose();
}
imageHeights.Sort();
int height = imageHeights[imageHeights.Count - 1];
Bitmap img3 = new Bitmap(width, height);
Graphics g = Graphics.FromImage(img3);
g.Clear(SystemColors.AppWorkspace);
foreach (FileInfo file in files)
{
Image img = Image.FromFile(file.FullName);
if (nIndex == 0)
{
g.DrawImage(img, new Point(0, 0));
nIndex++;
width = img.Width;
}
else
{
g.DrawImage(img, new Point(width, 0));
width += img.Width;
}
img.Dispose();
}
g.Dispose();
img3.Save(finalImage, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
imageLocation.Image = Image.FromFile(finalImage);
}
}
}
That's likely GDI playing tricks on you.
You see, when GDI encounters an unknown file, it will quite likely cause an OutOfMemoryException. Since you're not filtering the input images at all, I'd expect that you're simply grabbing a non-image file (or an image type that GDI doesn't understand).
Oh, and a bit sideways - make sure you set JPEG quality when saving JPEGs - the default is something like 75, which is rather bad for a lot of images. And please, do use using - it's very handy to ensure proper and timely clean-up :)
Get more memory!
But seriously, you don't appear to be filtering out files that are not image files. There are some hidden files in folders that you may be trying to open as an image accidentally, such as "Thumbs.db". Make sure that the file is an image with something like if (Path.GetExtension(file.FullPath) != ".png") continue;.
Also, on objects that you are calling .Dispose() on, consider wrapping them in a using() instead. For example:
using(var img = Image.FromFile(file.FullPath))
{
// ...
}