I'm writing a C # method that scans a lot of documents, but I need to scan these documents two-sided, ie for each sheet, scan the front and back of the document using the scanner's ADF. But I've tried all the ways I found on the internet and I could not. My code is below:
//user select the scanner
int indexScanner = Convert.ToInt32(Console.ReadLine());
// Connect to the first available scanner
var device = deviceManager.DeviceInfos[indexScanner - 1].Connect();
// Select the scanner
var scannerItem = device.Items[1];
int resolution = 150;
int width_pixel = 1250;
int height_pixel = 1700;
int color_mode = 1;
int adf_mode = 1;
int pages_mode = 1;
device.Properties["3096"].set_Value(pages_mode);
//device.Properties["3088"].set_Value(adf_mode);
scannerItem.Properties["3088"].set_Value(adf_mode);
AdjustScannerSettings(scannerItem, resolution, 0, 0, width_pixel, height_pixel, 0, 0, color_mode);
CommonDialogClass dlg = new CommonDialogClass();
object scanResult = dlg.ShowTransfer(scannerItem, FormatID.wiaFormatJPEG, true);
if (scanResult != null)
{
ImageFile image = (ImageFile)scanResult;
string filename = "scan.jpeg";
if (File.Exists(filename))
File.Delete(filename);
image.SaveFile(filename);
}
scanResult = dlg.ShowTransfer(scannerItem, FormatID.wiaFormatJPEG, true);
if (scanResult != null)
{
ImageFile image = (ImageFile)scanResult;
string filename = "scan1.jpeg";
if (File.Exists(filename))
File.Delete(filename);
image.SaveFile(filename);
}
Related
I want to load in a JPEG file and print it with Aspose.Pdf in C# (.net Framework 4.8). The code I currently have is:
public void PrintImage(string fileToPrint, string printerName, string jobName)
{
System.Drawing.Image srcImage = System.Drawing.Image.FromFile(fileToPrint);
int h = srcImage.Height;
int w = srcImage.Width;
var doc = new Document();
var page = doc.Pages.Add();
var image = new Image();
image.File = (fileToPrint);
page.PageInfo.Height = (h);
page.PageInfo.Width = (w);
page.PageInfo.Margin.Bottom = (0);
page.PageInfo.Margin.Top = (0);
page.PageInfo.Margin.Right = (0);
page.PageInfo.Margin.Left = (0);
page.Paragraphs.Add(image);
var viewer = new PdfViewer(doc);
PrintUsingViewer(viewer, printerName, jobName);
}
private static void PrintUsingViewer(PdfViewer viewer, string printerName, string jobName)
{
viewer.AutoResize = true; // Print the file with adjusted size
viewer.AutoRotate = true; // Print the file with adjusted rotation
viewer.PrintPageDialog = false; // Do not produce the page number dialog when printing
var ps = new System.Drawing.Printing.PrinterSettings();
var pgs = new System.Drawing.Printing.PageSettings();
ps.PrinterName = printerName;
viewer.PrinterJobName = jobName;
viewer.PrintDocumentWithSettings(pgs, ps);
viewer.Close();
}
When I save the document instead of printing and look at it, it seems fine (the image is added). However, when trying to print the image it is not printed and the page is just blank..
I would like to print without first saving the document as a PDF and then trying to print that saved PDF. Does anyone see what I am doing wrong?
The solution was adding this line of code
doc.ProcessParagraphs();
right after this line:
page.Paragraphs.Add(image);
So the code now becomes
public void PrintImage(string fileToPrint, string printerName, string jobName)
{
System.Drawing.Image srcImage = System.Drawing.Image.FromFile(fileToPrint);
int h = srcImage.Height;
int w = srcImage.Width;
var doc = new Document();
var page = doc.Pages.Add();
var image = new Image();
image.File = (fileToPrint);
page.PageInfo.Height = (h);
page.PageInfo.Width = (w);
page.PageInfo.Margin.Bottom = (0);
page.PageInfo.Margin.Top = (0);
page.PageInfo.Margin.Right = (0);
page.PageInfo.Margin.Left = (0);
page.Paragraphs.Add(image);
doc.ProcessParagraphs();
var viewer = new PdfViewer(doc);
PrintUsingViewer(viewer, printerName, jobName);
}
private static void PrintUsingViewer(PdfViewer viewer, string printerName, string jobName)
{
viewer.AutoResize = true; // Print the file with adjusted size
viewer.AutoRotate = true; // Print the file with adjusted rotation
viewer.PrintPageDialog = false; // Do not produce the page number dialog when printing
var ps = new System.Drawing.Printing.PrinterSettings();
var pgs = new System.Drawing.Printing.PageSettings();
ps.PrinterName = printerName;
viewer.PrinterJobName = jobName;
viewer.PrintDocumentWithSettings(pgs, ps);
viewer.Close();
}
Now the image is printed correctly!
I have an issue with Files.
I am doing an image importer so clients put their files on an FTP server and then they can import it in the application.
During the import process I copy the file in the FTP Folder to another folder with File.copy
public List<Visuel> ImportVisuel(int galerieId, string[] images)
{
Galerie targetGalerie = MemoryCache.GetGaleriById(galerieId);
List<FormatImage> listeFormats = MemoryCache.FormatImageToList();
int i = 0;
List<Visuel> visuelAddList = new List<Visuel>();
List<Visuel> visuelUpdateList = new List<Visuel>();
List<Visuel> returnList = new List<Visuel>();
foreach (string item in images)
{
i++;
Progress.ImportProgress[Progress.Guid] = "Image " + i + " sur " + images.Count() + " importées";
string extension = Path.GetExtension(item);
string fileName = Path.GetFileName(item);
string originalPath = HttpContext.Current.Request.PhysicalApplicationPath + "Uploads\\";
string destinationPath = HttpContext.Current.Server.MapPath("~/Images/Catalogue") + "\\";
Visuel importImage = MemoryCache.GetVisuelByFilName(fileName);
bool update = true;
if (importImage == null) { importImage = new Visuel(); update = false; }
Size imageSize = importImage.GetJpegImageSize(originalPath + fileName);
FormatImage format = listeFormats.Where(f => f.width == imageSize.Width && f.height == imageSize.Height).FirstOrDefault();
string saveFileName = Guid.NewGuid() + extension;
File.Copy(originalPath + fileName, destinationPath + saveFileName);
if (format != null)
{
importImage.format = format;
switch (format.key)
{
case "Catalogue":
importImage.fileName = saveFileName;
importImage.originalFileName = fileName;
importImage.dossier = targetGalerie;
importImage.dossier_id = targetGalerie.id;
importImage.filePath = "Images/Catalogue/";
importImage.largeur = imageSize.Width;
importImage.hauteur = imageSize.Height;
importImage.isRoot = true;
if (update == false) { MemoryCache.Add(ref importImage); returnList.Add(importImage); }
if (update == true) visuelUpdateList.Add(importImage);
foreach (FormatImage f in listeFormats)
{
if (f.key.StartsWith("Catalogue_"))
{
string[] keys = f.key.Split('_');
string destinationFileName = saveFileName.Insert(saveFileName.IndexOf('.'), "-" + keys[1].ToString());
string destinationFileNameDeclinaison = destinationPath + destinationFileName;
VisuelResizer declinaison = new VisuelResizer();
declinaison.Save(originalPath + fileName, f.width, f.height, 1000, destinationFileNameDeclinaison);
Visuel visuel = MemoryCache.GetVisuelByFilName(fileName.Insert(fileName.IndexOf('.'), "-" + keys[1].ToString()));
update = true;
if (visuel == null) { visuel = new Visuel(); update = false; }
visuel.parent = importImage;
visuel.filePath = "Images/Catalogue/";
visuel.fileName = destinationFileName;
visuel.originalFileName = string.Empty;
visuel.format = f;
//visuel.dossier = targetGalerie; On s'en fout pour les déclinaisons
visuel.largeur = f.width;
visuel.hauteur = f.height;
if (update == false)
{
visuelAddList.Add(visuel);
}
else
{
visuelUpdateList.Add(visuel);
}
//importImage.declinaisons.Add(visuel);
}
}
break;
}
}
}
MemoryCache.Add(ref visuelAddList);
// FONCTION à implémenter
MemoryCache.Update(ref visuelUpdateList);
return returnList;
}
After some processes on the copy (the original file is no more used)
the client have a pop-up asking him if he wants to delete the original files in the ftp folder.
If he clicks on Ok another method is called on the same controller
and this method use
public void DeleteImageFile(string[] files)
{
for (int i = 0; i < files.Length; i++)
{
File.Delete(HttpContext.Current.Request.PhysicalApplicationPath + files[i].Replace(#"/", #"\"));
}
}
This method works fine and really delete the good files when I use it in other context.
But here I have an error message:
Process can't acces to file ... because it's used by another process.
Someone have an idea?
Thank you.
Here's the screenshot of Process Explorer
There are couple of thing you can do here.
1) If you can repro it, you can use Process Explorer at that moment and see which process is locking the file and if the process is ur process then making sure that you close the file handle after your work is done.
2) Use try/catch around the delete statement and retry after few seconds to see if the file handle was released.
3) If you can do it offline you can put in some queue and do the deletion on it later on.
You solve this by using c# locks. Just embed your code inside a lock statement and your threads will be safe and wait each other to complete processing.
I found the solution:
in my import method, there a call to that method
public void Save(string originalFile, int maxWidth, int maxHeight, int quality, string filePath)
{
Bitmap image = new Bitmap(originalFile);
Save(ref image, maxWidth, maxHeight, quality, filePath);
}
The bitmap maintains the file opened blocking delete.
just added
image.Dispose();
in the methos and it work fine.
Thank you for your help, and thank you for process explorer. Very useful tool
I'm creating a software to get the data from .dat file and write those data in database. There are so many .dat files so I need to do a batch process. I'm currently reading one dat file by using this code
UDisk udisk = new UDisk();
byte[] byDataBuf = null;
int iLength;//length of the bytes to get from the data
string sPIN2 = "";
string sVerified = "";
string sTime_second = "";
string sDeviceID = "";
string sStatus = "";
string sWorkcode = "";
openFileDialog1.Filter = "1_attlog(*.dat)|*.dat";
openFileDialog1.FileName = "1_attlog.dat";//1 stands for one possible deviceid
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
FileStream stream = new FileStream(openFileDialog1.FileName, FileMode.OpenOrCreate, FileAccess.Read);
byDataBuf = File.ReadAllBytes(openFileDialog1.FileName);
iLength = Convert.ToInt32(stream.Length);
lvSSRAttLog.Items.Clear();
int iStartIndex = 0;
int iOneLogLength;//the length of one line of attendence log
for (int i = iStartIndex; i < iLength - 2; i++)//modify by darcy on Dec.4 2009
{
if (byDataBuf[i] == 13 && byDataBuf[i + 1] == 10)
{
iOneLogLength = (i + 1) + 1 - iStartIndex;
byte[] bySSRAttLog = new byte[iOneLogLength];
Array.Copy(byDataBuf, iStartIndex, bySSRAttLog, 0, iOneLogLength);
udisk.GetAttLogFromDat(bySSRAttLog, iOneLogLength, out sPIN2, out sTime_second, out sDeviceID, out sStatus, out sVerified, out sWorkcode);
ListViewItem list = new ListViewItem();
list.Text = sPIN2;
list.SubItems.Add(sTime_second);
list.SubItems.Add(sDeviceID);
list.SubItems.Add(sStatus);
list.SubItems.Add(sVerified);
list.SubItems.Add(sWorkcode);
lvSSRAttLog.Items.Add(list);
bySSRAttLog = null;
iStartIndex += iOneLogLength;
iOneLogLength = 0;
}
}
stream.Close();
}
How can I read files one by one and transfer those data into database.
My database is - SMS
table is -
CHECKINOUT
columns -CHECKDate datetime
CHECKTime datetime
InOutMode int
Status varchar(50)
WorkCode varchar(50)
Memoinfo varchar(50)
sn int
sn2 int
Ip varchar(16)
Updated int
Given a folder path, you can use Directory.EnumerateFiles to get .dat files one by one:
string folder = #"D:\your\Folder";
foreach(var file in Directory.EnumerateFiles(
folder, // folder path
"*.dat" // file type you want
/*, SearchOption.AllDirectories*/)) // uncomment it if you want open files in subfolder
{
FileStream stream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Read);
byDataBuf = File.ReadAllBytes(openFileDialog1.FileName);
iLength = Convert.ToInt32(stream.Length);
// Do your stuff here
stream.Close();
}
I have working code that uses signature pad data to create and save a signature bmp image to a file location. My question is: how can I modify this code to insert the image into a SQL Server 2008 image field?
The following from my Controller obtains signature data from a signature tablet and creates a bmp image and saves it to a file location.
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public ActionResult SaveSignature2(IPrincipal principal) {
int userId = ((ScoutIdentity)principal.Identity).UserId.Value;
//Put user code to initialize the page here
SIGPLUSLib.SigPlus sigObj = new SIGPLUSLib.SigPlus();
sigObj.InitSigPlus();
sigObj.AutoKeyStart();
string visitorname = Request.Form["visitorname"];
visitorname = visitorname.Replace(" ", ""); //combines the first name with last name with no spaces
visitorname = visitorname.Trim();
string thevrvIDstr = Request.Form["vrvID"];
int thevrvID = Convert.ToInt32(thevrvIDstr);
//use the same data to decrypt signature
sigObj.AutoKeyData = Request.Form["SigText"];
sigObj.AutoKeyFinish();
sigObj.SigCompressionMode = 1;
sigObj.EncryptionMode = 2;
//Now, get sigstring from client
//Sigstring can be stored in a database if
//a biometric signature is desired rather than an image
sigObj.SigString = Request.Form["hidden"];
if (sigObj.NumberOfTabletPoints() > 0) {
sigObj.ImageFileFormat = 0;
sigObj.ImageXSize = 500;
sigObj.ImageYSize = 150;
sigObj.ImagePenWidth = 8;
sigObj.SetAntiAliasParameters(1, 600, 700);
sigObj.JustifyX = 5;
sigObj.JustifyY = 5;
sigObj.JustifyMode = 5;
long size;
byte[] byteValue;
sigObj.BitMapBufferWrite();
size = sigObj.BitMapBufferSize();
byteValue = new byte[size];
byteValue = (byte[])sigObj.GetBitmapBufferBytes();
sigObj.BitMapBufferClose();
System.IO.MemoryStream ms = new System.IO.MemoryStream(byteValue);
System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
String path;
path = System.AppDomain.CurrentDomain.BaseDirectory;
path = path + "/uploadFiles/Signatures/"+thevrvIDstr+".bmp";
img.Save(path, System.Drawing.Imaging.ImageFormat.Bmp);
ViewData["Result"] = ("Image saved successfully to " + path);
}
else {
ViewData["Result"] = "signature has not been returned successfully!";
}
ViewData["Result"] = sigObj.SigString;
//return RedirectToAction("vrSignIn");
return View();
}
I also have code elsewhere in my controller that gets an uploaded file and inserts it into the database. This code works OK.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UploadTempFiles(string id, string u)
{
//this method temporarily stores files
string userIdString = Cryptographer.DecryptSymmetric("RijndaelManaged", SecurityImpl.UrlToBase64(u));
int userId = Convert.ToInt32(userIdString);
if (Request.Files.Count > 0)
{
for (int i = 0; i < Request.Files.Count; i++)
{
HttpPostedFileBase file = Request.Files[i];
int contentlength = file.ContentLength;
byte[] b = new byte[contentlength];
Stream s;
s = file.InputStream;
s.Read(b, 0, contentlength);
VisitRequest.AddVisitorSignature(userId, b);
}
}
return View("UploadFiles");
}
I'm thinking that I can use some part of the second code to interrupt the image creation process in the first code and insert the image into the database INSTEAD of saving the image to a file location. I don't know how to do that.
I had same problem, and I solved it:
Comment these three lines:
//path = System.AppDomain.CurrentDomain.BaseDirectory;
//path = path + "/uploadFiles/Signatures/"+thevrvIDstr+".bmp";
//img.Save(path, System.Drawing.Imaging.ImageFormat.Bmp);
Convert image to String data (assumed that your variable 'strSignature' was declared before):
strSignature = img.ToString();
Save it with your Stored Procedure.
Hope this help you!
Working in C# with the EWS Managed API, we're having trouble efficiently retrieving the images stored as inline attachments.
The endpoint is to show an email with inline images as a fully formed html page in a panel. The code we currently us:
string sHTMLCOntent = item.Body;
FileAttachment[] attachments = null;
if (item.Attachments.Count != 0)
{
attachments = new FileAttachment[item.Attachments.Count];
for (int i = 0; i < item.Attachments.Count; i++)
{
string sType = item.Attachments[i].ContentType.ToLower();
if (sType.Contains("image"))
{
attachments[i] = (FileAttachment)item.Attachments[i];
string sID = attachments[i].ContentId;
sType = sType.Replace("image/", "");
string sFilename = sID + "." + sType;
string sPathPlusFilename = Directory.GetCurrentDirectory() + "\\" + sFilename;
attachments[i].Load(sFilename);
string oldString = "cid:" + sID;
sHTMLCOntent = sHTMLCOntent.Replace(oldString, sPathPlusFilename);
}
}
}
(sourced: http://social.technet.microsoft.com/Forums/en-US/exchangesvrdevelopment/thread/ad10283a-ea04-4b15-b20a-40cbd9c95b57)
.. this is not very efficient though and is slowing down the responsiveness of our web app. Does anyone have a better solution for this problem? We are using Exchange 2007 SP1, so the IsInline property wont work as its Exchange 2010 only.
I build an index of your "cid:"s first:
private const string CidPattern = "cid:";
private static HashSet<int> BuildCidIndex(string html)
{
var index = new HashSet<int>();
var pos = html.IndexOf(CidPattern, 0);
while (pos > 0)
{
var start = pos + CidPattern.Length;
index.Add(start);
pos = html.IndexOf(CidPattern, start);
}
return index;
}
Then you need a replace function that replaces the cids based on your index
private static void AdjustIndex(HashSet<int> index, int oldPos, int byHowMuch)
{
var oldIndex = new List<int>(index);
index.Clear();
foreach (var pos in oldIndex)
{
if (pos < oldPos)
index.Add(pos);
else
index.Add(pos + byHowMuch);
}
}
private static bool ReplaceCid(HashSet<int> index, ref string html, string cid, string path)
{
var posToRemove = -1;
foreach (var pos in index)
{
if (pos + cid.Length < html.Length && html.Substring(pos, cid.Length) == cid)
{
var sb = new StringBuilder();
sb.Append(html.Substring(0, pos-CidPattern.Length));
sb.Append(path);
sb.Append(html.Substring(pos + cid.Length));
html = sb.ToString();
posToRemove = pos;
break;
}
}
if (posToRemove < 0)
return false;
index.Remove(posToRemove);
AdjustIndex(index, posToRemove, path.Length - (CidPattern.Length + cid.Length));
return true;
}
so now, you can check your attachments
FileAttachment[] attachments = null;
var index = BuildCidIndex(sHTMLCOntent);
if (index.Count > 0 && item.Attachments.Count > 0)
{
var basePath = Directory.GetCurrentDirectory();
attachments = new FileAttachment[item.Attachments.Count];
for (var i = 0; i < item.Attachments.Count; ++i)
{
var type = item.Attachments[i].ContentType.ToLower();
if (!type.StartsWith("image/")) continue;
type = type.Replace("image/", "");
var attachment = (FileAttachment)item.Attachments[i];
var cid = attachment.ContentId;
var filename = cid + "." + type;
var path = Path.Combine(basePath, filename);
if(ReplaceCid(index, ref sHTMLCOntent, cid, path))
{
// only load images when they have been found
attachment.Load(path);
attachments[i] = attachment;
}
}
}
Additional to that: instead of calling attachment.Load right away, and pass the path to the image directly, you could link to another script, where you pass the cid as a parameter and then check back with the exchange for that image; then the process of loading the image from exchange does not block the html cid replacement and could lead to loading the page faster, since the html can send to the browser sooner.
PS: Code is not tested, just so you get the idea!
EDIT
Added the missing AdjustIndex function.
EDIT 2
Fixed small bug in AdjustIndex