c# foreach image in folder - c#

Below is some code that
creates a directory
uses MagickNet to covert a PDF into separate BMP images and stores it in a folder (ImagePath)
Then it uses TessNet2 to scan each image in that folder to parse out information
I can't seem to get the foreach loop that scans the ImagePath folder. Any help?
The error right now is on the 'foreach' statement and it says "Cannot convert type 'char' to 'System.Drawing.Image'"
static void Main(string[] args)
{
string ImagePath = exePath + "\\Images";
if (!Directory.Exists(ImagePath))
{
Directory.CreateDirectory(ImagePath);
}
MagickReadSettings settings = new MagickReadSettings();
settings.Density = new MagickGeometry(300, 300);
using (MagickImageCollection images = new MagickImageCollection())
{
images.Read(#"D:\Test\ABStest.pdf",settings);
int page = 1;
foreach (MagickImage image in images)
{
image.Write(ImagePath + "\\ABS" + page + ".bmp");
page++;
}
}
foreach (Image item in ImagePath)
{
using (Bitmap bmp = new Bitmap(item))
{
tessnet2.Tesseract tessocr = new tessnet2.Tesseract();
tessocr.Init(#"C:\Users\Matt Taylor\Documents\Visual Studio 2012\Projects\TessNet2\TessNet2\bin\Debug\tessdata", "eng", false);
tessocr.GetThresholdedImage(bmp, Rectangle.Empty).Save("c:\\temp\\" + Guid.NewGuid().ToString() + ".bmp");
// Tessdata directory must be in the directory than this exe
Console.WriteLine("Multithread version");
ocr.DoOCRMultiThred(bmp, "eng");
//Console.WriteLine("Normal version");
//ocr.DoOCRNormal(bmp, "eng");
}
}
}

You can use Directory.GetFiles to return all the filenames in the directory and create your Bitmaps from there
foreach (string imageFileName in Directory.GetFiles(ImagePath))
{
using (Bitmap bmp = new Bitmap(imageFileName))
{
}
}
But if there are other files in that folder you should add a filter
foreach (string imageFileName in Directory.GetFiles(ImagePath, "*.jpg"))
{
using (Bitmap bmp = new Bitmap(imageFileName))
{
}
}

You don't need to save the file to disk. You could use the .ToBitmap() method of MagickImage.
foreach (MagickImage image in images)
{
using (Bitmap bmp = image.ToBitmap())
{
tessnet2.Tesseract tessocr = new tessnet2.Tesseract();
// etc...
}
}

You are looping through String ImagePath, which gives you a collection of characters. You need to search through the directory with Directory.GetFiles(), and load the images with Image.FromFile():
foreach (String itemPath in Directory.GetFiles(ImagePath))
{
using (Image item = Image.FromFile(itemPath))
{
...
}
}

Related

Access Images and videos from android internal Storage using Unity C#

i am trying to access the Whatsapp folder from android internal storage but for some reason this code is not working the file path is correct but this if statement never gets true
here is the code for checking if file exixts
public static Texture2D LoadPNG()
{
Texture2D tex = null;
byte[] fileData;
if (File.Exists(filePath))
{
Debug.Log("file exists");
fileData = File.ReadAllBytes(filePath);
tex = new Texture2D(2, 2);
tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
}
return tex;
}
now filepath = "/storage/emulated/0/Whatsapp/Media/.statuses
code which makes this path
public static string GetDownloadFolder()
{
string[] temp = (Application.persistentDataPath.Replace("Android", "")).Split(new string[] { "//" }, System.StringSplitOptions.None);
filePath = temp[0]+"/WhatsApp/Media/.Statuses";
return (temp[0] + "/WhatsApp/Media/.Statuses");
}
now problem is that in android device this .statuses folder have images and video files but this if statement never gets called why i dont understand even path is correct
if (File.Exists(filePath))
{
Debug.Log("file exists");
fileData = File.ReadAllBytes(filePath);
tex = new Texture2D(2, 2);
tex.LoadImage(fileData); //..this will auto-resize the texture dimensions.
}
Your problem is that you check if file exists at folder path.
The solution is check if path is directory and get all files from it:
if (Directory.Exists(path))
{
string filenames[] = Directory.GetFiles(path);
foreach (var filename in filenames)
{
LoadPNG(filename);
}
}

ERROR: The process cannot access the file 'Companion.jpg' because it is being used by another process

I have a problem when trying to delete the files from a directory because it says a file is being used by another process. I cant figure out how to delete all the files in the folder after I run the cmdCombine Method. Here is the code, a little help please:
private void cmdCombine_Click(object sender, EventArgs e)
{
DirectoryInfo directory = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Images");
if (directory != null)
{
FileInfo[] files = directory.GetFiles();
ResizeImages(files);
}
DirectoryInfo directory2 = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Upload");
if (directory2 != null)
{
FileInfo[] files = directory2.GetFiles();
CombineImages(files);
System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Images");
foreach (FileInfo file2 in downloadedMessageInfo.GetFiles())
{
file2.Delete();
}
foreach (DirectoryInfo dir in downloadedMessageInfo.GetDirectories())
{
dir.Delete(true);
}
}
}
//Method for resizing the images
private void ResizeImages(FileInfo[] files)
{
//Set Count integers and strings to save files
int fileCount = Directory.GetFiles(#"C:\Users\Elder Zollinger\Desktop\Images").Length;
int count = 1;
string fileNameOnly = Path.GetFileNameWithoutExtension(#"C:\Users\Elder Zollinger\Desktop\Upload\NewImage.jpg");
string extension = Path.GetExtension(#"C:\Users\Elder Zollinger\Desktop\Upload\NewImage.jpg");
string uploadPath = Path.GetDirectoryName(#"C:\Users\Elder Zollinger\Desktop\Upload\NewImage.jpg");
string newFullUploadPath = #"C:\Users\Elder Zollinger\Desktop\Upload\NewImage.jpg";
//Read Files in the folder
foreach (FileInfo file in files)
{
//Create a new file name that doesnt exist
while (File.Exists(newFullUploadPath))
{
string tempFileName = string.Format("{0}({1})", fileNameOnly, count++);
newFullUploadPath = Path.Combine(uploadPath, tempFileName + extension);
}
//Resize and save images when there is more than 2
if (fileCount > 2)
{
Image img = Image.FromFile(file.FullName);
var newImage = resizeImage(img, new Size(66, 200));
newImage.Save(newFullUploadPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
//Resize and save images for 1 or 2 images
else
{
Image img = Image.FromFile(file.FullName);
var newImage = resizeImage(img, new Size(100, 200));
newImage.Save(newFullUploadPath, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
//Stitch Images
private void CombineImages(FileInfo[] files)
{
//Create strings for saved images
int count = 1;
string fileNameOnly = Path.GetFileNameWithoutExtension(#"C:\Users\Elder Zollinger\Desktop\Dump\Final.jpg");
string extension = Path.GetExtension(#"C:\Users\Elder Zollinger\Desktop\Dump\Final.jpg");
string uploadPath = Path.GetDirectoryName(#"C:\Users\Elder Zollinger\Desktop\Dump\Final.jpg");
string newFullUploadPath = #"C:\Users\Elder Zollinger\Desktop\Dump\Final.jpg";
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();
while (File.Exists(newFullUploadPath))
{
string tempFileName = string.Format("{0}({1})", fileNameOnly, count++);
newFullUploadPath = Path.Combine(uploadPath, tempFileName + extension);
}
img3.Save(newFullUploadPath, System.Drawing.Imaging.ImageFormat.Jpeg);
img3.Dispose();
imageLocation.Image = Image.FromFile(newFullUploadPath);
foreach (FileInfo file in files)
{
file.Delete();
}
}
//Method to resize the images
private static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
private void SelectImages_Click(object sender, EventArgs e)
{
Stream myStream = null;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = "c:\\";
openFileDialog1.Filter = "png files (*.png)|*.png|All files (*.*)|*.*";
openFileDialog1.FilterIndex = 2;
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if ((myStream = openFileDialog1.OpenFile()) != null)
{
int count = 1;
string fileNameOnly = Path.GetFileNameWithoutExtension(#"C:\Users\Elder Zollinger\Desktop\Images\Companion.jpg");
string extension = Path.GetExtension(#"C:\Users\Elder Zollinger\Desktop\Images\Companion.jpg");
string uploadPath = Path.GetDirectoryName(#"C:\Users\Elder Zollinger\Desktop\Images\Companion.jpg");
string newFullUploadPath = #"C:\Users\Elder Zollinger\Desktop\Images\Companion.jpg";
while (File.Exists(newFullUploadPath))
{
string tempFileName = string.Format("{0}({1})", fileNameOnly, count++);
newFullUploadPath = Path.Combine(uploadPath, tempFileName + extension);
}
System.IO.File.Copy(openFileDialog1.FileName, newFullUploadPath);
}
}
}
private void Clear_Click(object sender, EventArgs e)
{
imageLocation.Image = null;
System.IO.DirectoryInfo downloadedMessageInfo = new DirectoryInfo(#"C:\Users\Elder Zollinger\Desktop\Images");
foreach (FileInfo file in downloadedMessageInfo.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo dir in downloadedMessageInfo.GetDirectories())
{
dir.Delete(true);
}
}
}
}
I suspect this is the problem:
Image img = Image.FromFile(file.FullName);
That opens the file - but you never dispose the same object, so the file will be open until the object is finalized. Image implements IDisposable, so you should use a using statement:
using (Image image = ...)
{
...
}
You should also dispose of the resized image, although at least that isn't holding on to a file handle.
Note that you've got the almost exactly the same block of code for whether there are more than two files or not. It would be cleaner to choose just the size conditionally:
Size size = fileCount > 2 ? new Size(66, 200) : new Size(100, 200);
using (Image original = Image.FromFile(file.FullName))
using (Image resized = ResizeImage(original, size))
{
resized.Save(newFullUploadPath, ImageFormat.Jpeg);
}
Much cleaner, IMO.

Add image from local system to listbox

I have a listbox and i want to update my listbox with all the logical drives. I want to show all the images in a parent and child format. I am using this code
string[] path = System.IO.Directory.GetLogicalDrives();
foreach (string directories in path)
{
Bitmap bitimg = null;
DirectoryInfo dinfo = new DirectoryInfo(directories);
FileInfo[] Files = dinfo.GetFiles("*.jpg");
for (int i = 0; i < Files.Count(); i++)
{
string fileName = Files[i].FullName;
Uri uri = new Uri(fileName, UriKind.Relative);
BitmapImage bitmap=new BitmapImage(uri);
Image img = new Image();
img.Source(bitmap);
listBox1.Items.Add(img);
}
}
But i am getting error as
Cannot create an instance of the abstract class or interface 'System.Drawing.Image'

OutOfMemoryException error in Loop

I am trying to create a Windows app which uploads files to FTP. Essentially, it looks for .jpeg files in a given folder, it reads through the barcodes found in the .jpg files before uploading it into the FTP server, and entering the URL into the database for our records.
As there will be multiple files at any given time in the folder, I am essentially trying to read them in a loop, and process them accordingly. However, I get an OutOfMemoryException whenever the loop starts again. I am trying to figure out what I'm doing wrong here. I have appended my code below:
private void btnProcess_Click(object sender, RoutedEventArgs e)
{
podPath = Directory.GetFiles(DestPath, "*.jpg");
List<string> scans = new List<string>(podPath.Length);
List<string> badscans = new List<string>();
byte[] imageBytes;
string filename, result;
POD conpod = new POD();
OTPOD otpod = new OTPOD();
ConsignmentObj scanJob;
//Pickup OTScan;
//Consolidate ccv;
for (int i = 0; i < podPath.Count(); i++ )
{
filename = podPath[i].ToString();
using (Bitmap bm = (Bitmap)Bitmap.FromFile(filename))
{
var results = barcodeReader.Decode(bm);
result = results.ToString();
bm.Dispose();
}
if (result != null)
{
//if barcode can be read, we throw the value into the database to pull out relevant information
if (result.Contains(ConNotePrefix))
{
#region Consignments
scanJob = getCon(result.ToString());
final = ImageFolder + "\\" + result.ToString() + ".jpg";
using (System.Drawing.Image img = System.Drawing.Image.FromFile(filename))
{
MemoryStream ms = new MemoryStream();
try
{
img.Save(ms, ImageFormat.Jpeg);
imageBytes = ms.ToArray();
img.Dispose();
}
finally
{
ms.Flush();
ms.Close();
ms.Dispose();
}
}
lock (filename)
{
if (System.IO.File.Exists(filename))
{
File.Delete(filename);
}
}
using (var stream = File.Create(final)) { }
File.WriteAllBytes(final, imageBytes);
File.Delete(filename);
conpod.ConsignmentID = scanJob.ConsignmentID;
conpod.UserID = 1;
conpod.Location = ftpUrl + "//" + result.ToString() + ".jpg";
conpod.rowguid = Guid.NewGuid();
UploadFilesToFtp(ftpUrl, ftpUser, ftpPass, final, result.ToString() + ".jpg");
insertPOD(conpod);
scans.Add(result.ToString());
#endregion
}
}
else
{
badscans.Add(filename);
}
}
this.lbScans.ItemsSource = scans;
this.lbBadScans.ItemsSource = badscans;
}
The FTP method, UploadFilesToFtp(x, x, x, x, x, x) is not a problem here. All feedback will be much appreciated.
An OutOfMemoryException can also be thrown by the method FromFile of the Image class when
The file does not have a valid image format.
or
GDI+ does not support the pixel format of the file.
So i think there is a problem with one of your image files you are reading. One solution is to catch the OutOfMemoryException and adding the file to the badscans.
try{
using (Bitmap bm = (Bitmap)Bitmap.FromFile(filename)) {
var results = barcodeReader.Decode(bm);
result = results.ToString();
bm.Dispose();
}
}
catch(OutOfMemoryException) {
badscans.add(filename);
}

Why can I only write ONE item in my Resource.resx file?

I thought I am writing 10 file extensions and their related Icons as Bitmap into a resource file within a for loop. The odd thing is that only the last file extension with its Icon is written into the Resource.resx file. Somehow the next file extension in the loop is overwriting the previous one, but WHY ? I thought a resource is sort of a dictionary with key/value pair where I can add as much as I want just as I do in the Resource designer...
What do I wrong?
My code:
private void AddDocument()
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Multiselect = true;
DialogResult result = fileDialog.ShowDialog();
if (result == DialogResult.OK)
{
for (int i = 0; i < fileDialog.FileNames.Length; i++)
{
string absoluteFilePath = fileDialog.FileNames.GetValue(i).ToString();
byte[] file = File.ReadAllBytes(absoluteFilePath);
String fileExtension = Path.GetExtension(absoluteFilePath);
Bitmap gdiImage;
Document doc = new Document();
doc.DocumentData = file;
doc.DocumentName = fileDialog.SafeFileNames.GetValue(i).ToString();
if (TryIsFileExtensionExisting(fileExtension, out gdiImage))
{
// Filetype was saved before => Convert GDI Bitmap to wpf BitmapImage
doc.DocumentTypeImage = gdiImage.ConvertGDIImageToWPFBitmapImage();
}
else
{
BitmapImage wpfImage;
// Filetype is new => get Bitmap out of the Icon
Icon icon = IconFromFilePath(absoluteFilePath);
Bitmap bitmap = icon.ToBitmap();
wpfImage = bitmap.ConvertGDIImageToWPFBitmapImage();
doc.DocumentTypeImage = wpfImage;
// Save bitmap to resource
using (ResXResourceWriter writer = new ResXResourceWriter("TBM.Resource"))
{
writer.AddResource(fileExtension, bitmap);
writer.Generate();
}
}
DocumentList.Add(doc);
}
_documentService.AddDocumentsToPeriod(DocumentList, _parentId);
}
}
private bool TryIsFileExtensionExisting(String fileExtension, out Bitmap wpfImage)
{
DictionaryEntry entry;
using (ResXResourceReader reader = new ResXResourceReader ("TBM.Resource"))
{
entry = reader.Cast<DictionaryEntry>()
.Where(x => x.Key.ToString()
.Equals(fileExtension, StringComparison.CurrentCultureIgnoreCase))
.FirstOrDefault();
};
wpfImage = entry.Value as Bitmap;
return entry.Key != null;
}
private Icon IconFromFilePath(string filePath)
{
Icon result = null;
try
{
result = Icon.ExtractAssociatedIcon(filePath);
//'# swallow and return nothing. You could supply a default Icon here as well
}
catch
{
}
return result;
}
The problem is here:
using (ResXResourceWriter writer = new ResXResourceWriter("TBM.Resource"))
{
writer.AddResource(fileExtension, bitmap);
writer.Generate();
}
Each time you create a new writer object and write to it. But you don't have the creation of the writer object read from the old file. So you overwrite every time. You should be able to use a different constructor and solve your problem.
http://msdn.microsoft.com/en-us/library/system.resources.resxresourcewriter.aspx

Categories

Resources