How to reference Ghostscript DLL in C# - c#

I'm using a C# wrapper to convert PDFs to images using Ghostscript, however i cant seem to reference the dll correctly.
I have the DLL stored in the bin folder (also don't know if that's the best place to keep it there or not)
Here's my code:
byte[] fileData = null;
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
Ghostscript.NET.Rasterizer.GhostscriptRasterizer rasterizer = null;
Ghostscript.NET.GhostscriptVersionInfo vesion = new Ghostscript.NET.GhostscriptVersionInfo(new Version(0, 0, 0), path + #"\gsdll64.dll", string.Empty, Ghostscript.NET.GhostscriptLicense.GPL);
Stream inStream = new MemoryStream(fileData);
MemoryStream outStream = new MemoryStream();
List<Image> imageList = new List<Image>();
using (rasterizer = new Ghostscript.NET.Rasterizer.GhostscriptRasterizer())
{
rasterizer.Open(inStream, vesion, false);
for (int i = 1; i <= rasterizer.PageCount; i++)
{
//string pageFilePath = Path.Combine(outputPath, Path.GetFileNameWithoutExtension(file) + "-p" + i.ToString() + ".jpg");
int dpi = 200;
Image img = rasterizer.GetPage(dpi, dpi, i);
img.Save(outStream, ImageFormat.Jpeg);
Image img = new Image
{
imgByteArray = outStream.ToArray()
};
imageList.Add(image);
}
rasterizer.Close();
}
I'm getting the Ghostscript native library could not be found error.
Here's the path I get
I think it has to do with the double / and 'file://' in the DLLPath string. And should I also specify the LipPath as well?
Any help??

In your case you should make ghostscript dll path this way:
string binPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string gsDllPath = Path.Combine(binPath, Environment.Is64BitProcess ? "gsdll64.dll" : "gsdll32.dll");

Even though this does not answer the question directly, I think it's worth mentioning, because I've ran into a problem using the OP's code with Ghostscript.NET version 1.2.1 published in 2016. Here's the fix I found:
In the source code,
Ghostscript.NET\Helpers\StreamHelper.cs:171
n = output.Read(buffer, 0, buffer.Length);
really should've been
n = input.Read(buffer, 0, buffer.Length);
If you're opening a stream instead of a path, without modifying the above mentioned code, you'll get empty result because the input stream did not get copied.
Reading into the code in more depth finds that the input stream is written into a temp file then read again into memory. You'll be better off just using rasterizer.Open by the path instead of stream, if it were a PDF file on disk to begin with.

Related

File can't not be found? C# - Get Resources

Hello i want to access my files at resources in Visual Studio but when i Build my .exe file and move it from my Folder i get a message that the files could not be found?
That is my code:
string RunningPath = AppDomain.CurrentDomain.BaseDirectory;
string pdf = string.Format("{0}Resources\\me.pdf", Path.GetFullPath(Path.Combine(RunningPath, #"..\..\")));
Process.Start(pdf);
I tried other methods but it still don't work? :/
Anyone has an idea?
something you could do like this read a file from resource stream
var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("me.pdf");
using (FileStream fs = File.Create(#"c:\temp\me.pdf"))
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = stream.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, len);
}
};
Process.Start(#"c:\temp\me.pdf");
If you have added the pdf file to Properties.Resources, you can access it as followed.
Call AppDomain.CurrentDomain.BaseDirectory to get bin\Debug folder first.
Then use .. to return to the parent directory
string path = AppDomain.CurrentDomain.BaseDirectory + #"..\..\Resources\test.pdf";
System.Diagnostics.Process.Start(path);

How to convert PDF Base64 into pdf then PDF into an image in C#

following is the code added:
The image object is in the library.imaging.
"using System.Drawing;"
"using System.Drawing.Imaging;"
{
byte[] b = Convert.FromBase64String("R0lGODlhAQABAIAAA");
Image image;
using (MemoryStream memstr = new MemoryStream(b))
{
image = Image.FromStream(memstr);
}
}
Here is the new code I'm working on:
{
string base64BinaryStr = " ";
byte[] PDFDecoded = Convert.FromBase64String(base64BinaryStr);
string FileName = (#"C:\Users\Downloads\PDF " + DateTime.Now.ToString("dd-MM-yyyy-hh-mm"));
BinaryWriter writer = new BinaryWriter(File.Create(FileName + ".pdf"));
writer.Write(PDFDecoded);
string s = Encoding.UTF8.GetString(PDFDecoded);
}
So this is your current code:
byte[] PDFDecoded = Convert.FromBase64String(base64BinaryStr);
string FileName = (#"C:\Users\Downloads\PDF " + DateTime.Now.ToString("dd-MM-yyyy-hh-mm"));
BinaryWriter writer = new BinaryWriter(File.Create(FileName + ".pdf"));
writer.Write(PDFDecoded);
You don't actually need BinaryWriter for this. File.Create already gives you a FileStream:
FileStream writer = File.Create(FileName + ".pdf");
writer.Write(PDFDecoded, 0, PDFDecoded.Length);
But this will still have the problem you're experiencing because you're not flushing the data to it. We also need to close the file. Thankfully, we can wrap it in using and it will do both for us:
using (FileStream writer = File.Create(FileName + ".pdf"))
{
writer.Write(PDFDecoded, 0, PDFDecoded.Length);
}
But a simpler way to do this is:
File.WriteAllBytes(FileName + ".pdf", PDFDecoded);
As for PDF -> Image, you'll probably have to see if there is a library available for this (search "PDF to Image NuGet") that can help you with this as I don't think there is anything built-in.
Just a thought, you don't need to create a physical PDF file, you can have it in memory and convert it to image from there.
Now the problem is that you cannot use Image from System.Drawing.Imaging for this, it doesn't support reading PDF file.
Instead you'll need to search for some library that can do that.
For example, try GemBox.Pdf, you can use it like this:
string base64String = "...";
byte[] pdfBytes = Convert.FromBase64String(base64String);
using (PdfDocument pdfDocument = PdfDocument.Load(new MemoryStream(pdfBytes)))
{
ImageSaveOptions imageOptions = new ImageSaveOptions(ImageSaveFormat.Png);
string imageName = DateTime.Now.ToString("dd-MM-yyyy-hh-mm") + ".png";
pdfDocument.Save(#"C:\Users\Downloads\" + imageName, imageOptions);
}
I've used the code provided on this Convert example.

ICSharpZipLib - unziping file issue

I have an application in ASP.NET where user can upload ZIP file. I'm trying to extract file using ICSharpZipLib (I also tried DotNetZip, but had same issue).
This zip file contains single xml document (9KB before compress).
When I open this file with other applications on my desktop (7zip, windows explorer) it seems to be ok.
My unzip method throws System.OutOfMemoryException and I have no idea why is that. When I debugged my unziping method I noticed that zipInputStreams' Length property throws Exception and is not available:
Stream UnZipSingleFile(Stream memoryStream)
{
var zipInputStream = new ZipInputStream(memoryStream);
memoryStream.Position = 0;
zipInputStream.GetNextEntry();
MemoryStream unzippedStream = new MemoryStream();
int len;
byte[] buf = new byte[4096];
while ((len = zipInputStream.Read(buf, 0, buf.Length)) > 0)
{
unzippedStream.Write(buf, 0, len);
}
unzippedStream.Position = 0;
memoryStream.Position = 0;
return unzippedStream;
}
and here's how I get string of unzippedStream:
string GetString()
{
var reader = new StreamReader(unzippedStream);
var result = reader.ReadToEnd();
unzippedStream.Position = 0;
return result;
}
From their wiki:
"Sharpzip supports Zip files using both stored and deflate compression methods and also supports old (PKZIP 2.0) style and AES encryption"
Are you sure the format of the uploaded zip file is acceptable for SharpZipLib?
While this post is quite old, I think it could be beneficial to illustrate how I did this for compression and decompression using ICSharpZipLib (C# package version 1.1.0). I put this together by looking into the examples shown here (see ie. these compression and decompression examples).
Assumption: The input to the compression and decompression below should be in bytes. If you have ie. an xml file you could load it to an XDocument, and convert it into an XmlDocument with .ToXmlDocument(). From there, you could access the string contents by calling .OuterXml, and converting the string to a byte array.
// Compression (inputBytes = ie. string-to-compress, as bytes)
using var dataStream = new MemoryStream(inputBytes);
var outputStream = new MemoryStream();
using (var zipStream = new ZipOutputStream(outputStream))
{
zipStream.SetLevel(3);
var newEntry = new ZipEntry("someFilename.someExtension");
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(dataStream, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false;
}
outputStream.Position = 0;
var outputBytes = outputStream.ToArray();
// Decompression (inputBytes = ie. string-to-decompress, as bytes)
using var dataStream = new MemoryStream(inputBytes);
var outputStream = new MemoryStream();
using (var zipStream = new ZipInputStream(dataStream))
{
while (zipStream.GetNextEntry() is ZipEntry zipEntry)
{
var buffer = new byte[4096];
StreamUtils.Copy(zipStream, outputStream, buffer);
}
}
var outputBytes = outputStream.ToArray();

File handling in c#

In my c# application, when i upload a file , it needs to be converted to temp file and store in a temporary folder then read the temp file as image find its height width every thing and later stores in databse.I am getting error when I read the temp file as image, as Out of Memory, below is my entire code.
string img = System.Windows.Forms.Application.StartupPath +#"\"+ path;
//in path .png file is accessed.
string filename = Path.GetFileName(img);
string internetCache = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache);
string IEPath=internetCache+#"\tmp";
if (!Directory.Exists(IEPath))
Directory.CreateDirectory(IEPath);
FileInfo fi = new FileInfo(img);
FileStream fs = fi.OpenRead();
//lResult = URLDownloadToFile(0, img.src, TempFolder & strFileName, 0, 0)
Stream stream = fs;
byte[] buffer = new byte[fs.Length];
stream.Seek(273, SeekOrigin.Begin);
stream.Read(buffer, 0, (int)buffer.Length);
string tempfile = Path.Combine(IEPath, Math.Abs(filename.GetHashCode()) + ".tmp");
File.WriteAllBytes(tempfile, buffer);
fs.Close();
stream.Close();
string _contentType = "application/octet-stream";
FileType Type = FileType.png;
string MimeType = "image/png";
FileStream fst = new FileStream(tempfile, FileMode.Open);
Image _image = System.Drawing.Image.FromStream(fst, true, true);
The last line where I am getting the exception as out of memory.
Please help me to find a solution.
I'd venture that the stream you are reading is corrupted (perhaps because you remove the leading 273 bytes).
I just followed the instructions of the question:
read some file
Copy the file to a temp file
Read as image
Get width & height
var bytes = File.ReadAllBytes(#"C:\temp\duck.jpg");
var temp = Path.GetTempFileName();
File.WriteAllBytes(temp, bytes);
var img = Image.FromFile(temp);
Console.WriteLine ("width: {0}, height: {0}", img.Width, img.Height);

Use libtiff in C# to convert from one TIFF format to another

I have a TIFF using JPEG format the WPF / C# can not handle via TiffBitmapDecoder. Our clients use the file format and our current C++ and Java code handles it.
I need to convert this to a format I can display using TiffBitmapDecoder or standard BitmapImage. It looks like the C# version of libtiff is the way to go but I am not having any luck converting in code.
Here is my attempt - I always end up with corrupt files.
Boolean doSystemLoad = false;
Tiff tiff = null;
try
{
tiff = Tiff.Open(file, "r");
}
catch (Exception e) // TIFF could not handle, let OS do it
{
doSystemLoad = true;
}
if (tiff != null)
{
width = Double.Parse(tiff.GetField(TiffTag.IMAGEWIDTH)[0].Value.ToString());
height = Double.Parse(tiff.GetField(TiffTag.IMAGELENGTH)[0].Value.ToString());
int bits = Int32.Parse(tiff.GetField(TiffTag.BITSPERSAMPLE)[0].Value.ToString());
int samples = Int32.Parse(tiff.GetField(TiffTag.SAMPLESPERPIXEL)[0].Value.ToString());
string compression = tiff.GetField(TiffTag.COMPRESSION)[0].Value.ToString();
Console.WriteLine("Image is " + width + " x " + height + " bits " + bits + " sample " + samples);
Console.WriteLine("Compression " + compression);
// We allow OS to load anything that is not JPEG compression
doSystemLoad = compression.ToLower().IndexOf("jpeg") == -1;
string tempFile = Path.GetTempFileName() + ".tiff";
// Convert here then load converted via OS
if (!doSystemLoad)
{
Console.WriteLine(">> Attempting to convert... " + tempFile);
Console.WriteLine(" Scan line " + tiff.ScanlineSize());
Tiff tiffOut = Tiff.Open(tempFile, "w");
tiffOut.SetField(TiffTag.IMAGEWIDTH, width);
tiffOut.SetField(TiffTag.IMAGELENGTH, height);
tiffOut.SetField(TiffTag.BITSPERSAMPLE, bits);
tiffOut.SetField(TiffTag.SAMPLESPERPIXEL, samples);
tiffOut.SetField(TiffTag.ROWSPERSTRIP, 1L);
tiffOut.SetField(TiffTag.COMPRESSION, Compression.NONE);
tiffOut.SetField(TiffTag.ORIENTATION, BitMiracle.LibTiff.Classic.Orientation.TOPLEFT);
tiffOut.SetField(TiffTag.FAXMODE, FaxMode.CLASSF);
tiffOut.SetField(TiffTag.GROUP3OPTIONS, 5);
tiffOut.SetField(TiffTag.PHOTOMETRIC, Photometric.RGB);
tiffOut.SetField(TiffTag.FILLORDER, FillOrder.MSB2LSB);
tiffOut.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
tiffOut.SetField(TiffTag.RESOLUTIONUNIT, ResUnit.INCH);
tiffOut.SetField(TiffTag.XRESOLUTION, 100.0);
tiffOut.SetField(TiffTag.YRESOLUTION, 100.0);
tiffOut.SetField(TiffTag.SUBFILETYPE, FileType.PAGE);
tiffOut.SetField(TiffTag.PAGENUMBER, new object[] { 1, 1 });
tiffOut.SetField(TiffTag.PAGENAME, "Page 1");
Byte[] scanLine = new Byte[tiff.ScanlineSize() + 5000];
for (int row = 0; row < height; row++)
{
tiff.ReadScanline(scanLine, row);
tiffOut.WriteScanline(scanLine, row);
}
tiffOut.Dispose();
}
tiff.Dispose();
Stream imageStreamSource = new FileStream(tempFile, FileMode.Open, FileAccess.Read, FileShare.Read);
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
width = bitmapSource.Width;
height = bitmapSource.Height;
imageMain.Width = width;
imageMain.Height = height;
imageMain.Source = bitmapSource;
}
if (doSystemLoad)
{
Stream imageStreamSource = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
TiffBitmapDecoder decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
width = bitmapSource.Width;
height = bitmapSource.Height;
imageMain.Width = width;
imageMain.Height = height;
imageMain.Source = bitmapSource;
}
Kevin, one of the previous versions of LibTiff.Net had a bug: Flush was not automatically called. It's fixed some time ago.
Also, we have just released LibTiff.Net 2.2 with support for OJPEG (or Old Jpeg, or Original Jpeg) files. You may want to retry your attempts with the new version if it's still relevant.
After direct contact with BitMiracle it turns out that neither LibTIff for C or LibTiff for .NET support the underlying file format so I am out of luck in this area. I will need to look into commercial package support which we hoped to avoid for our .NET product. We already use Acordex for Java and ImageGear for C++ so I believe we will use ImageGear for .NET. TIFF is just a bear to support and we have too many clients using this obscure file format to drop support for it.

Categories