MemoryStream (pdf) to Ghostscript to MemoryStream (jpg) - c#

I did see "PDF to Image using GhostScript. No image file has to be created", but that only (sort of) answered half my question. Is it possible to use GhostScriptSharp (or the regular GhostScript dll) to convert a pdf in a MemoryStream to a jpg in a MemoryStream? I speak of a dynamically filled in pdf form with iTextSharp which I am already directing to a MemoryStream to save to a database or stream to a http response, and I'd really love to avoid saving to a file (and subsequent cleanup) if I can.
The sole answer in the answer I referenced claimed that one has to go down to the GhostScript dll to do the latter part, but it was obvious I would need to do a good bit of leg-work to figure out what that meant. Does anyone have a good resource that could help me on this journey?

The thing is that the PDF language, unlike the PostScript language, inherently requires random access to the file. If you provide PDF directly to Standard Input or via PIPE, Ghostscript will copy it to a temporary file before interpreting the PDF. So, there is no point of passing PDF as MemoryStream (or byte array) as it will anyway end up on the disk before it is interpreted.
Take a look at the Ghostscript.NET and it's GhostscriptRasterizer sample for the 'in-memory' output.

Ghostscript.Net is a wrapper to the Ghostscript dll. It now can take a stream object and can return an image that can be saved to an stream. Here is an example that I used on as ASP page to generate PDF's from a memory stream. I haven't completely figured out the best way to handle the ghostscript dll and where to locate it on the server.
void PDFToImage(MemoryStream inputMS, int dpi)
{
GhostscriptRasterizer rasterizer = null;
GhostscriptVersionInfo version = new GhostscriptVersionInfo(
new Version(0, 0, 0), #"C:\PathToDll\gsdll32.dll",
string.Empty, GhostscriptLicense.GPL);
using (rasterizer = new GhostscriptRasterizer())
{
rasterizer.Open(inputMS, version, false);
for (int i = 1; i <= rasterizer.PageCount; i++)
{
using (MemoryStream ms = new MemoryStream())
{
Image img = rasterizer.GetPage(dpi, dpi, i);
img.Save(ms, ImageFormat.Jpeg);
ms.Close();
AspImage newPage = new AspImage();
newPage.ImageUrl = "data:image/png;base64," + Convert.ToBase64String((byte[])ms.ToArray());
Document1Image.Controls.Add(newPage);
}
}
rasterizer.Close();
}
}

Related

What the best way or lib for creating thumbnail from memory stream (video) in C#?

I have to create multiple thumbnails and save on amazon s3 in c#. I don't find library which can create thumbnail from memory stream only from source file. But can't have file source, I have only the stream from the upload and I don't want save localy the file.
Thx for ur help!
Simple c# code can do this for you. You can create a thumbnail from byte array.
First convert your memory stream object to byte array by following code
byte[] bytes = memoryStream.ToArray();
and then you can use below method
public byte[] MakeThumbnail(byte[] myImage, int thumbWidth, int thumbHeight)
{
using (MemoryStream ms = new MemoryStream())
using (Image thumbnail = Image.FromStream(new MemoryStream(myImage)).GetThumbnailImage(thumbWidth, thumbHeight, null, new IntPtr()))
{
thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms.ToArray();
}
}
I don't find library which can create thumbnail from memory stream only from
source file
Really? Because I do not need a library for that - I can do that with standard C#.
System.Drawing.Bitmap has a constructor accepting a stream.
But can't have file source,
Actually you can - it is called a temporary file and there is a whole mechanism for that in .NET (and windows). Really.
But it is not needed. Read the manual, create a bitmap (by packing your byte array into a MemoryStream) and it should work.

Issue while saving clipboard data as image

I have copied some data in Clipboard using MS-Word Com API
Range.CopyAsPicture();
and when I am pasting(Ctrl + v) it on window's paint software its getting displayed.
Issue is while converting Clipboard data to image Using c#
I looked into various link on internet and tried following code which is not working
MemoryStream ms = Clipboard.GetData("DeviceIndependentBitmap") as MemoryStream;
above line returning null
clipboardData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap)
Above line returning false
Can anyone please suggest how can convert the clipboard data to image.
If all you are looking for is getting the bitmap of the image in the clipboard (or the underlying binary data), look into using GetImage.
Here is a code snippet you can try:
BitmapSource bmpSource = Clipboard.GetImage();
MemoryStream ms = new MemoryStream();
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmpSource));
encoder.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
In case that also doesn't seem to work, you can try looking into this workaround, it doesn't seem directly related, but it might be just what you need.
Apparently MS Office puts images on the clipboard as a stream of PNG bytes, which is actually a really sensible innovation. This image data simply uses the identifier "PNG".
So try this instead:
if (retrievedData.GetDataPresent("PNG"))
{
MemoryStream png_stream = retrievedData.GetData("PNG") as MemoryStream;
if (png_stream != null)
return new Bitmap(png_stream);
}

How could I make WebBrowser.Navigate analog for bytes array, instead of URL?

I planning to load PDF files into it, but I can't save those to disk. PDFs exist only as byte arrays in my program.
For text data I can use something like this:
webBrowser1.DocumentText = "<html>page content</html>";
But PDF is not text, so I need some other way, but can't find any.
I tried this:
byte[] file_content = File.ReadAllBytes("C:\\Users\\Metafalica\\Documents\\DatabaseSQLLanguageRzheutskaya.pdf");
MemoryStream ms = new MemoryStream(file_content);
ms.Flush();
ms.Position = 0;
webBrowser1.DocumentStream = ms;
But getting this:
It's not possible to load and render a PDF via webBrowser.DocumentStream. What happens behind the scene is that an instance of MSHTML Document Object gets created and initialized with the supplied stream. You could possibly load an image (which MIME type is recognized by MSHTML), but not a PDF. On the other hand, when webBrowser.Navigate is used, an instance of Adobe Acrobat Reader PDF Document gets created, rather than MSHTML.

how to convert a jpeg in an array into a bitmap

I have a functioning application in c#/.net that currently accepts raw image data in a bayer format from a set of embedded cameras and converts them to jpeg images. To save transmission time, I have modified the embedded devices to encode the images as jpegs prior to transmission. I'm an experienced embedded programmer but a total c#/.net noob. I have managed to modify the application to save the arrays to file with a jpeg name using this snippet: ( the offset of 5 is to skip header data in the transmission frame)
FileStream stream = File.Create(fileName);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(multiBuff.msgData, 5, multiBuff.dataSize - 5);
writer.Close();
The files open up fine, but now I want to treat the data as a bitmap without having to save & load from file. I tried the following on the data array:
MemoryStream stream = new MemoryStream(data);
BinaryReader reader = new BinaryReader(stream);
byte[] headerData = reader.ReadBytes(5);
Bitmap bmpImage = new Bitmap(stream);
But this throws a parameter not valid exception. As a newbie, I'm a little overwhelmed with all the classes and methods for images and it seems like what I'm doing should be commonplace, but I can't find any examples in the usual places. Any ideas?
I think you are looking for Bitmap.FromStream() :
Bitmap bmpImage = (Bitmap)Bitmap.FromStream(stream);
Actually using new Bitmap(stream) should have worked as well - this means that the data in the stream does not constitute a valid image - are you sure the jpg is valid? Can you save it to disk and open it i.e. in Paint to test?
You use the Image class.
Image image;
using (MemoryStream stream = new MemoryStream(data))
{
image = Image.FromStream(stream);
}
FYI it didn't work because reader.ReadBytes(5) returns the 5 first bytes of stream not the bytes after position 5

Replace an Image in an existing Multiple Page Tiff using .Net

Using .Net how do I replace the first page of a multiple page tiff file with a new image. Preferable without create a new file.
I think you could not do it without creating another file.
You could read all the images first, replace the image you want to replace, close the original source, and then replace the file with the new multi-page TIFF, but I believe it will use a lot of memory. I would read an image at a time, and write it to a new file and, as the last step, change the file names.
Something like:
// open a multi page tiff using a Stream
using(Stream stream = // your favorite stream depending if you have in memory or from file.)
{
Bitmap bmp = new Bitmap(imagePath);
int frameCount = bmp.GetFrameCount(FrameDimension.Page);
// for a reference for creating a new multi page tiff see:
// http://www.bobpowell.net/generating_multipage_tiffs.htm
// Here all the stuff of the Encoders, and all that stuff.
EncoderParameters ep = new EncoderParameters(1);
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.MultiFrame);
Image newTiff = theNewFirstImage;
for(int i=0; i<frameCount; i++)
{
if(i==0)
{
// Just save the new image instead of the first one.
newTiff.Save(newFileName, imageCodecInfo, Encoder);
}
else
{
Bitmap newPage = bmp.SelectActiveFrame(FrameDimension.Page);
newTiff.SaveAdd(newPage, ep);
}
}
ep.Param[0] = new EncoderParameter(enc, (long)EncoderValue.Flush);
newTiff.SaveAdd(ep);
}
// close all files and Streams and the do original file delete, and newFile change name...
Hope it helps. For questions in .NET imaging, the Bob Powell page has a lot of good stuff.
This is fairly easy to do. There's source code on this CodeProject tutorial page that will help you do what you want.
Essentially, you'll need to make a call to Image.GetFrameCount() which will give you the number of images in your multi-page TIFF (just to confirm that you actually have a multi-page TIFF).
You might need to experiment with how you save your resulting TIFF - you may need to reassemble the TIFF manually, or you might be able to edit/replace the image directly before writing the TIFF back to disk.

Categories