Ghostscript is increasing file size after compressing - c#

I use the following method to compress the pdf:
private bool CompressPDF(string Input, string Output, string CompressValue)
{
try
{
Process proc = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.CreateNoWindow = true;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.FileName = string.Concat(Path.GetDirectoryName(Application.ExecutablePath), "\\ghost.exe");
string args = "-sDEVICE=pdfwrite -dCompatibilityLevel=1.4" + " -dPDFSETTINGS=/" + CompressValue + " -dNOPAUSE -dQUIET -dBATCH" + " -sOutputFile=\"" + Output + "\" " + "\"" + Input + "\"";
psi.Arguments = args;
//start the execution
proc.StartInfo = psi;
proc.Start();
proc.WaitForExit();
return true;
}
catch
{
return false;
}
}
I put the pdf settings on "Printer" by default. I cant figure out why the file size of my pdf files increase sometimes.

Ghostscript (more accurately its pdfwrite device) doesn't 'compress' files.
It is possible, by judicious use of settings which will do things like downsample images to trade quality for file size, to get a smaller file produced but there is absolutely no guarantee that this is the case.
Without seeing the input file, there is no possible way to comment on why your file increases in size, but (for example) a PDF 1.5 file can use compressed streams and xref, and the pdfwrite device never uses those, so that could be one reason.
The canned 'PDFSETTINGS' cover a multitude of different controls, you should read those and understand what is actually going on. If your original file happens to already have traded quality for size, then it's entirely likely that the printer settings (which are reasonably conservative) will not actually do anything at all.

Related

How can I get Bitdefender (antivirus) to scan a file and delete it if the file contains a virus?

This is the code I use to write my file to the app_data folder:
var filename = Server.MapPath("~/App_Data") + "/" thefilename;
var ms = new MemoryStream();
file.InputStream.CopyTo(ms);
file.InputStream.Position = 0;
byte[] contents = ms.ToArray();
var fileStream = new System.IO.FileStream(filename, System.IO.FileMode.Create,
System.IO.FileAccess.ReadWrite);
fileStream.Write(contents, 0, contents.Length);
fileStream.Close();
This writes the file fine. However, if there is a virus on it, Bitdefender does not delete this file, unless I go on the IIS and manually try to open/move the file. If I do that, then it is instantly deleted.
If I copy and paste the test virus file into the app_data folder directly then Bitdefender removes it instantly.
I have tried to use various ways to read/move the file with System.IO.File.Move/Open/ReadAllLines. Yet, nothing triggers bit defender to remove the file.
The only thing I got to work was creating a new process to open the file. However, I don't want to be doing that on the server. I am looking for a different solution. This is the code that I've used to open the file, which does cause Bitdefender to scan and remove the infected file:
Process cmd = new Process();
cmd.StartInfo.FileName = filename;
cmd.Start();
A solution with System.IO.File.Open would be best for me in this situation, but I cannot figure out why it isn't working. Alternately, a way to trigger Bitdefender to instantly scan the file would also be a viable solution.
I have solved the issue with the help of #sheavens and following code:
Process cmd = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.FileName = #"C:\Program Files\Bitdefender\Endpoint Security\product.console.exe";
var args = String.Format("/c FileScan.OnDemand.RunScanTask custom path=\"{0}\" infectedAction1=delete", filename);
startInfo.Arguments = args;
cmd.StartInfo = startInfo;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.RedirectStandardError = true;
var result = cmd.Start();
This creates a new process and looks up the bitdefender exe, and then runs a command to scan the file at the provided path.

Load standart output and parse it to Image

I have graphviz dot.exe file that I call with parameter -Tpng (output type is png, but I don't care if it is in png, bmp, or any other). I start it in C# code:
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = path;
psi.UseShellExecute = false;
psi.Arguments = "-Tpng";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
Process p = Process.Start(psi);
Then, I write input
p.StandardInput.WriteLine(input);
input is defined before, it's a string. Input is valid, tested manually.
Then, I need to read output that graphviz prints into standart output and parse it to Image.
I've tried to read memory stream, but I was either unable to read it, or, after reading, the memory stream was locked (threw exception when tried Image.FromStream(myMemoryStream);).
I was able to load output to string
string output = "";
while (true)
{
string newOutput = p.StandardOutput.ReadLine();
output += newOutput;
if (newOutput == String.Empty)
break;
}
I've tried to parse this string as described in this answer, but it threw exception (string is not valid).
How can I get Image from the dot.exe output?
From the comments it seems the program is expecting the StandardInput to be finished before returning the content. Close the StandardInput to achieve it:
p.StandardInput.WriteLine(input);
p.StandardInput.BaseStream.Close();

File.Exists false when created by tesseract

I use tesseract to get text from captcha image.
I use this code
Process p = new Process();
p.StartInfo.FileName = Server.MapPath("~/app/tesseract.exe");
p.StartInfo.Arguments = imgSavePath + " " + txtSavePath;
p.Start();
p.WaitForExit();
bool exist = File.Exists(txtSavePath);
The txtSavePath is created in windows explorer, i can open it and can read the text in it. But the exist variable is false. It is so strange.
Can anybody tell me why? How can i use StreamReader to read text in created file?
Tesseract appends a ".txt" extension to the output text file; so in your case, it should be:
bool exist = File.Exists(txtSavePath + ".txt");

How to improve the quality of JPEG images that are generated from PDFs using Ghostscript?

I use this code to generate JPEG images from a PDF file:
String cmd = #"./lib/gswin32c";
String args = "-dNOPAUSE -sDEVICE=jpeg -dJPEGQ=100 -dBATCH -dSAFER -sOutputFile=" + fileName + "-%03d.jpg " + fileName + ".pdf";
Process proc = new Process();
proc.StartInfo.FileName = cmd;
proc.StartInfo.Arguments = args;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
I works really fine, but the quality is really bad. It seems to be blurred. Any hints how to improve the quality?
EDIT
Now I'm using the following arguments and it is working as expected:
String args = "-dNOPAUSE -sDEVICE=pngalpha -r300 -dBATCH -dSAFER -sOutputFile=" + fileName + "-%03d" + FILEEXTENSION + " " + fileName + ".pdf";
JPEG? For documents? Generate gifs or pngs, if you can. JPEGs are unsuitable for anything else than photos, even at a "maximum" quality setting.
http://lbrandy.com/blog/2008/10/my-first-and-last-webcomic/
I've quickly look through the document and it seems there are some options to affect image quality like -dCOLORSCREEN and -dDOINTERPOLATE. Try them! :)
I have just been struggling with the quality of a pdf to jpeg and have changed on the advice of dk-logic to gif.
This may help someone because I now have near perfect quality with the following command
gs -sDEVICE=png16m -r600 -dDownScaleFactor=3 -o outfile.png inFile.pdf
According the the docs
-dDownScaleFactor=integer
This causes the internal rendering to be scaled down by the given
(small integer) factor before being output.
For example, the above will produce a 200dpi output png from a
600dpi internal rendering:

Print existing PDF (or other files) in C#

From an application I'm building I need to print existing PDFs (created by another app).
How can I do this in C# and provide a mechanism so the user can select a different printer or other properties.
I've looked at the PrintDialog but not sure what file it is attempting to print, if any, b/c the output is always a blank page. Maybe I'm just missing something there.
Do I need to use "iTextSharp" (as suggested else where)? That seems odd to me since I can "send the the file to the printer" I just don't have any nice dialog before hand to set the printer etc. and I don't really want to write a printing dialog from the ground up but it seems like a lot of examples I found by searching did just that.
Any advice, examples or sample code would be great!
Also if PDF is the issue the files could be created by the other app in a diff format such as bitmap or png if that makes things easier.
Display a little dialog with a combobox that has its Items set to the string collection returned by PrinterSettings.InstalledPrinters.
If you can make it a requirement that GSView be installed on the machine, you can then silently print the PDF. It's a little slow and roundabout but at least you don't have to pop up Acrobat.
Here's some code I use to print out some PDFs that I get back from a UPS Web service:
private void PrintFormPdfData(byte[] formPdfData)
{
string tempFile;
tempFile = Path.GetTempFileName();
using (FileStream fs = new FileStream(tempFile, FileMode.Create))
{
fs.Write(formPdfData, 0, formPdfData.Length);
fs.Flush();
}
try
{
string gsArguments;
string gsLocation;
ProcessStartInfo gsProcessInfo;
Process gsProcess;
gsArguments = string.Format("-grey -noquery -printer \"HP LaserJet 5M\" \"{0}\"", tempFile);
gsLocation = #"C:\Program Files\Ghostgum\gsview\gsprint.exe";
gsProcessInfo = new ProcessStartInfo();
gsProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;
gsProcessInfo.FileName = gsLocation;
gsProcessInfo.Arguments = gsArguments;
gsProcess = Process.Start(gsProcessInfo);
gsProcess.WaitForExit();
}
finally
{
File.Delete(tempFile);
}
}
As you can see, it takes the PDF data as a byte array, writes it to a temp file, and launches gsprint.exe to print the file silently to the named printer ("HP Laserjet 5M"). You could replace the printer name with whatever the user chose in your dialog box.
Printing a PNG or GIF would be much easier -- just extend the PrintDocument class and use the normal print dialog provided by Windows Forms.
Good luck!
Although this is VB you can easily translate it. By the way Adobe does not pop up, it only prints the pdf and then goes away.
''' <summary>
''' Start Adobe Process to print document
''' </summary>
''' <param name="p"></param>
''' <remarks></remarks>
Private Function printDoc(ByVal p As PrintObj) As PrintObj
Dim myProcess As New Process()
Dim myProcessStartInfo As New ProcessStartInfo(adobePath)
Dim errMsg As String = String.Empty
Dim outFile As String = String.Empty
myProcessStartInfo.UseShellExecute = False
myProcessStartInfo.RedirectStandardOutput = True
myProcessStartInfo.RedirectStandardError = True
Try
If canIprintFile(p.sourceFolder & p.sourceFileName) Then
isAdobeRunning(p)'Make sure Adobe is not running; wait till it's done
Try
myProcessStartInfo.Arguments = " /t " & """" & p.sourceFolder & p.sourceFileName & """" & " " & """" & p.destination & """"
myProcess.StartInfo = myProcessStartInfo
myProcess.Start()
myProcess.CloseMainWindow()
isAdobeRunning(p)
myProcess.Dispose()
Catch ex As Exception
End Try
p.result = "OK"
Else
p.result = "The file that the Document Printer is tryng to print is missing."
sendMailNotification("The file that the Document Printer is tryng to print" & vbCrLf & _
"is missing. The file in question is: " & vbCrLf & _
p.sourceFolder & p.sourceFileName, p)
End If
Catch ex As Exception
p.result = ex.Message
sendMailNotification(ex.Message, p)
Finally
myProcess.Dispose()
End Try
Return p
End Function
You will need Acrobat or some other application that can print the PDF. From there you P/Invoke to ShellExecute to print the document.
You could also use PDFsharp - it's an open source library for creating and manipulating PDFs.
http://www.pdfsharp.net/
I'm doing the same thing for my project and it worked for me
See if it can help you...
Process p = new Process();
p.EnableRaisingEvents = true; //Important line of code
p.StartInfo = new ProcessStartInfo()
{
CreateNoWindow = true,
Verb = "print",
FileName = file,
Arguments = "/d:"+printDialog1.PrinterSettings.PrinterName
};
try
{
p.Start();
}
catch
{
/* your fallback code */
}
You can also play with different options of windows
PRINT command to get desired output...Reference link
After much research and googling about this task Microsoft has released a great KB to print a pdf without any other applications necessary. No need to call adobe or ghostprint. It can print without saving a file to the disk makes life very easy.
http://support2.microsoft.com/?kbid=322091

Categories