Determine whether an image is PNG despite .BMP extension - c#

I want to check if images in a directory are of type png but with extension .bmp. The following determines whether it is a .bmp extension
string x = Path.GetExtension(file);
From this we establish that its extension is .bmp. Now the problem comes in checking if it is in a png format. I am stuck on this part.
The reason why I am doing this is because I want to have my images transparent and .bmp images don't work so well with that.
Thank you!

The above answer is incorrect, the code should be:
var header = new byte[4];
using (var fs = new FileStream(filename))
{
fs.Read(header, 0, 4);
}
var strHeader = Encoding.ASCII.GetString(header);
return strHeader.ToLower().EndsWith("png");

We can check the file extension with this
Byte[] imageBase64 = ....
var encodedFile = Encoding.ASCII.GetString(imageBase64);
return encodedFile.ToLower().StartsWith("?png", StringComparison.InvariantCultureIgnoreCase);

Here is another take that I personally like since you don't have to check against strings (using the System.Drawing Library).
using (var fs = new FileStream(filename))
{
var fsImage = System.Drawing.Image.FromStream(fs);
if (fsImage.RawFormat == System.Drawing.Imaging.ImageFormat.Jpeg)
{
// Do something with Jpegs
}
else if (fsImage.RawFormat == System.Drawing.Imaging.ImageFormat.Png)
{
// Do something with Pngs
}
}

Read the first 4 bytes of the file:
byte[] b = new byte[4];
using (var fs = new FileStream(filename))
{
fs.Read(b, 0, 4);
}
if (b.ToString().Contains("PNG"))
{
// this is a png file
}

Related

Put multiple Attachments to CouchDB

I have an .NET Core console application which does some update stuff to my CouchDB.
Now I have to add multiple attachments (in this case images) to my doc.
Here (https://docs.couchdb.org/en/stable/api/document/common.html#attachments) in point 1.4.1.1.4 they describe the way, but I get a Bad Request, I think my json is not perfect.
So I have a list of images that I convert and then send to DB, here is my code:
List<ImageFromApi> imagesFromApi = new List<ImageFromApi>();
string base64String;
foreach (var image in Images)
{
using (image)
{
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
byte[] imageBytes = m.ToArray();
// Convert byte[] to Base64 String
base64String = Convert.ToBase64String(imageBytes);
}
}
ImageFromApi Imagebuffer = new ImageFromApi() {
content_type = "image/*",
data = base64String
};
imagesFromApi.Add(Imagebuffer);
DocAttachments bufferData = new DocAttachments() {imagesFromApi = imagesFromApi };
newImages._attachments = bufferData;
}
string imagesJson = JsonConvert.SerializeObject(newImages);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(imagesJson);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
My Json from this code looks like this:
I see the difference between mine and the one from the documentation, but I dont know how to change my json correctly.
Any solutions?
So that nobody had a solution, i tried something around and find a way to achieve what i need. I made a new Attachment and added each image manually.
Here is an example of the first image:
Attachments attBuffer = new Attachments();
using (imagesFromApi[0])
{
using (MemoryStream m = new MemoryStream())
{
partImgs[0].Save(m, partImgs[0].RawFormat);
byte[] imageBytes = m.ToArray();
// Convert byte[] to Base64 String
base64String = Convert.ToBase64String(imageBytes);
}
}
attBuffer.Hood = new Hood()
{
content_type = "image/jpeg",
data = base64String,
};
As you can see, i created any of my images as a class and then mapped the list to it. I think this is not the best way, but it works for me, so better than nothing.
Hope it helps you as well.

Sharepoint ClientObject Model download files C#

I am trying to download files from a SharePoint library using the client object model. I seem to be able to access the files using OpenBinaryStream() and then executing the query, but when I try to access the stream, it is a stream of Length = 0. I've seen many examples and I've tried several, but I can't get the files to download. I've uploaded successfully, and credentials and permissions aren't the problem. Anyone have any thoughts?
public SharepointFileContainer DownloadFolder(bool includeSubfolders, params object[] path)
{
try
{
List<string> pathStrings = new List<string>();
foreach (object o in path)
pathStrings.Add(o.ToString());
var docs = _context.Web.Lists.GetByTitle(Library);
_context.Load(docs);
_context.ExecuteQuery();
var rootFolder = docs.RootFolder;
_context.Load(rootFolder);
_context.ExecuteQuery();
var folder = GetFolder(rootFolder, pathStrings);
var files = folder.Files;
_context.Load(files);
_context.ExecuteQuery();
SharepointFileContainer remoteFiles = new SharepointFileContainer();
foreach (Sharepoint.File f in files)
{
_context.Load(f);
var file = f.OpenBinaryStream();
_context.ExecuteQuery();
var memoryStream = new MemoryStream();
file.Value.CopyTo(memoryStream);
remoteFiles.Files.Add(f.Name, memoryStream);
}
...
}
SharepointFileContainer is just a custom class for my calling application to dispose of the streams when it has finished processing them. GetFolder is a recursive method to drill down the given folder path. I've had problems with providing the direct url and have had the most success with this.
My big question is why "file.Value" is a Stream with a Length == 0?
Thanks in advance!
EDIT:
Thanks for your input so far...unfortunately I'm experiencing the same problem. Both solutions pitched make use of OpenBinaryDirect. The resulting FileInformation class has this for the stream...
I'm still getting a file with 0 bytes downloaded.
You need to get the list item of the file (as a ListItem object) and then use it's property File. Something like:
//...
// Previous code
//...
var docs = _context.Web.Lists.GetByTitle(Library);
var listItem = docs.GetItemById(listItemId);
_context.Load(docs);
clientContext.Load(listItem, i => i.File);
clientContext.ExecuteQuery();
var fileRef = listItem.File.ServerRelativeUrl;
var fileInfo = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, fileRef);
var fileName = Path.Combine(filePath,(string)listItem.File.Name);
using (var fileStream = System.IO.File.Create(fileName))
{
fileInfo.Stream.CopyTo(fileStream);
}
After that you do whatever you need to do with the stream. The current one just saves it to the specified path, but you can also download it in the browser, etc..
We can use the following code to get the memory stream.
var fileInformation = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, file.ServerRelativeUrl);
if (fileInformation != null && fileInformation.Stream != null)
{
using (MemoryStream memoryStream = new MemoryStream())
{
byte[] buffer = new byte[32768];
int bytesRead;
do
{
bytesRead = fileInformation.Stream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
}
Reference: https://praveenkasireddy.wordpress.com/2012/11/11/download-document-from-document-set-using-client-object-model-om/

Verify that c# Embedded Resource matches file

I know that this is may be a question without one 'right' answer
I have a C# windows application that has an embedded resource included in the assembly. I've been trying to come up with a way to compare the contents of my resource stream to determine if the contents of that stream matches a particular file on the file system.
e.g.
using(var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(#"Manifest/Resource/Path/thing.exe"))
using(var fileStream = new FileStream(#"File/System/Path/thing.exe", FileMode.Read))
// Compare Contents (thing.exe may be an older version)
if(CompareStreamContents(resourceStream, fileStream))
{
/* Do a thing */
}
else
{
/* Do another thing*/
}
Is there a better way than simply doing a byte-by-byte comparison? Thoughts? (and thanks in advance!)
Per my comment:
private bool CompareStreamContents(Stream resourceStream, Stream fileStream)
{
var sha = new SHA256CryptoServiceProvider();
var hash1 = Convert.ToBase64String(sha.ComputeHash(ReadToEnd(resourceStream)));
var hash2 = Convert.ToBase64String(sha.ComputeHash(ReadToEnd(fileStream)));
return hash1 == hash2;
}
private byte[] ReadToEnd(Stream stream)
{
var continueRead = true;
var buffer = new byte[0x10000];
var ms = new MemoryStream();
while (continueRead)
{
var size = stream.Read((byte[])buffer, 0, buffer.Length);
if (size > 0)
{
ms.Write(buffer, 0, size);
}
else
{
continueRead = false;
}
}
return ms.ToArray();
}
If you plan on doing something else with the streams after the compare, you may want to set the stream position back to origin before returning from the compare method.

Convert Base64 from PDF to Bitmap [duplicate]

Is there any way, I can convert HTML Document (file not URL) to Image, or PDF to image?
I am able to do the above using Ghostscript DLL , Is there any other way , I can do it, without using the Ghostscript DLL?
I am developing a C# Windows Application.
the best and free nuget package that you can save every page of your Pdf to png and with custom resilution Docnet.core this can be use in the .net core project.
they have github and nice examples but here i want to add my code for reading en pdf with more that one page
string webRootPath = _hostingEnvironment.WebRootPath;
string fullPath = webRootPath + "/uploads/user-manual/file.pdf";
string fullPaths = webRootPath + "/uploads/user-manual";
using (var library = DocLib.Instance)
{
using (var docReader = library.GetDocReader(fullPath, 1080, 1920))
{
for (int i = 1; i < docReader.GetPageCount(); i++)
{
using (var pageReader = docReader.GetPageReader(i))
{
var bytes = EmailTemplates.GetModifiedImage(pageReader);
System.IO.File.WriteAllBytes(fullPaths+"/page_image_" +i+".png", bytes);
}
}
}
}
Other functions you can find in thier github repo.
Use LibPdf, for PDF to Image conversion
LibPdf library converts converts PDF file to an image. Supported image formats are PNG and BMP, but you can easily add more.
Usage example:
using (FileStream file = File.OpenRead(#"..\path\to\pdf\file.pdf")) // in file
{
var bytes = new byte[file.Length];
file.Read(bytes, 0, bytes.Length);
using (var pdf = new LibPdf(bytes))
{
byte[] pngBytes = pdf.GetImage(0,ImageType.PNG); // image type
using (var outFile = File.Create(#"..\path\to\pdf\file.png")) // out file
{
outFile.Write(pngBytes, 0, pngBytes.Length);
}
}
}
ImageMagick, you should also look at this freely available and powerful tool. It's capable of doing what you want and also provides some .NET bindings (as well as bindings to several other languages).
In its simplest form, it's just like writing a command
convert file.pdf imagefile.png
Try Freeware.Pdf2Png, check below url:
PDF to PNG converter.
byte[] png = Freeware.Pdf2Png.Convert(pdf, 1);
https://www.nuget.org/packages/Freeware.Pdf2Png/1.0.1?_src=template
In the about info, It said MIT license, I check it on March 22, 2022.
But as said Mitya, please double check.
You can use below any one library for PDF to Image conversion
Use Aspose.pdf link below:
http://www.aspose.com/docs/display/pdfnet/Convert+all+PDF+pages+to+JPEG+Images
code sample:
Aspose.Pdf.Document pdfDocument = new Aspose.Pdf.Document(MyPdfPath));
using (FileStream imageStream = new FileStream(MyOutputImage.png, FileMode.Create))
{
Resolution resolution = new Resolution(300);
PngDevice pngDevice = new PngDevice(resolution);
pngDevice.Process(pdfDocument.Pages[PageNo], MyOutputImage);
imageStream.Close();
}
Use Bytescout PDF Renderer link below:
http://bytescout.com/products/developer/pdfrenderersdk/convert-pdf-to-png-basic-examples
code sample :
MemoryStream ImageStream = new MemoryStream();
RasterRenderer renderer = new RasterRenderer();
renderer.RegistrationName = "demo";
renderer.RegistrationKey = "demo";
// Load PDF document.
renderer.LoadDocumentFromFile(FilePath);
for (int i = 0; i < renderer.GetPageCount(); i++)
{
// Render first page of the document to PNG image file.
renderer.RenderPageToStream(i, RasterOutputFormat.PNG, ImageStream);
}
Image im = Image.FromStream(ImageStream);
im.Save("MyOutputImage.png");
ImageStream.Close();
Using docnet, based in this example on github, I did this, very simple and functional :
pdf used in this example.
//...
using Docnet.Core;
using System.IO;
using Docnet.Core.Models;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
//paths
string pathPdf = #"C:\pathToPdfFile\lorem-ipsum.pdf";
string finalPathWithFileName = #"C:\pathToFinalImageFile\finalFile.png";
//using docnet
using (var docReader = DocLib.Instance.GetDocReader(pathPdf, new PageDimensions(1080, 1920)))
{
//open pdf file
using (var pageReader = docReader.GetPageReader(0))
{
var rawBytes = pageReader.GetImage();
var width = pageReader.GetPageWidth();
var height = pageReader.GetPageHeight();
var characters = pageReader.GetCharacters();
//using bitmap to create a png image
using (var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb))
{
AddBytes(bmp, rawBytes);
using (var stream = new MemoryStream())
{
//saving and exporting
bmp.Save(stream, ImageFormat.Png);
File.WriteAllBytes(finalPathWithFileName, stream.ToArray());
};
};
};
};
//extra methods
private static void AddBytes(Bitmap bmp, byte[] rawBytes)
{
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
var bmpData = bmp.LockBits(rect, ImageLockMode.WriteOnly, bmp.PixelFormat);
var pNative = bmpData.Scan0;
Marshal.Copy(rawBytes, 0, pNative, rawBytes.Length);
bmp.UnlockBits(bmpData);
}
Spire.PDF library can be used for PDF to Image conversion, such as PDF to PNG, JPG, EMF and TIFF etc.
The following is the code example shows how to convert PDF to PNG:
//Load a PDF
PdfDocument doc = new PdfDocument();
doc.LoadFromFile("PdfFilePath");
//Save to PNG images
for (int i = 0; i < doc.Pages.Count; i++)
{
String fileName = String.Format("ToImage-img-{0}.png", i);
using (Image image = doc.SaveAsImage(i,300,300))
{
image.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);
}
}
doc.Close();
More conversion examples can be found in the library's documentation. It also provides a free community edition but with some limitations.
While using Ghostscript with ImageMagick is a potential option, it is incredibly slow, every page would take around 5 or more seconds. DocNet is a much better option to convert pdf to images. The following code would convert all pages in a pdf file into Images, and do that fast.
public void SavePDFtoJPGDocnet(string fileName)
{
string FilePath = #"C:\SampleFileFolder\doc.pdf";
string DestinationFolder = #"C:\SampleFileFolder\";
IDocLib DocNet = DocLib.Instance;
//you are specifying the max resolution of image on any side, actual resolution will be limited by longer side,
//preserving the aspect ratio
var docReader = DocNet.GetDocReader(
FilePath,
new PageDimensions(1440, 2560));
for (int i = 0; i < docReader.GetPageCount(); i++)
{
using (var pageReader = docReader.GetPageReader(i))
{
var rawBytes = pageReader.GetImage();
var width = pageReader.GetPageWidth();
var height = pageReader.GetPageHeight();
var characters = pageReader.GetCharacters();
var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
DocnetClass.AddBytes(bmp, rawBytes);
//DocnetClass.DrawRectangles(bmp, characters);
var stream = new MemoryStream();
bmp.Save(stream, ImageFormat.Png);
File.WriteAllBytes(DestinationFolder + "/page_image_" + i + ".png", stream.ToArray());
}
}
}
Freeware.Pdf2Png worked great for my needs.
It does not only convert to Png, you can save to the image format of your choice.
In MS Visual Studio run this in your Package Manager console
PM> NuGet\Install-Package Freeware.Pdf2Png -Version 1.0.1,
or just add via the NuGet Package Manager GUI, search for Freeware.Pdf2Png and it should come up.
Once the reference is added to your project, code similar to this should do what you need to convert a PDF to an Image.
using (FileStream fs = new FileStream(FullFilePath, FileMode.Open))
{
byte[] buff = Freeware.Pdf2Png.Convert(fs, 1);
MemoryStream ms = new MemoryStream(buff);
Image img = Image.FromStream(ms);
img.Save(TiffFilePath, System.Drawing.Imaging.ImageFormat.Tiff);
}
FullFilePath - a string that is the Full File Path to the PDF to be converted.
TiffFilePath - a string that is the Full File Path of the newly created Image that you would like to save.
Unfortunately I was not able to find any c# code or proper algorithm to do this conversion without a 3rd party DLL. If any of you have good information for that please do share it!
In case someone wants to use Ghostscript.NET.
Ghostscript.NET - (written in C#) is the most completed managed wrapper library around the Ghostscript library (32-bit & 64-bit), an interpreter for the PostScript language, PDF.
It is dependent on executable file you have to install on your machine. Here is a link from where you can see and download the latest version of the exe.
https://www.ghostscript.com/download/gsdnld.html
P.S. I had some troubles with the latest version 9.50 not being able to count the pages.
I prefer using the 9.26 version.
https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs926/gs926aw32.exe
https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs926/gs926aw64.exe
Next step is to find and install Ghostscript.NET from Nuget.
I download the PDF from CDN url and use the MemoryStream to open and process the PDF file. Here is a sample code:
using (WebClient myWebClient = new WebClient())
{
using (GhostscriptRasterizer rasterizer = new GhostscriptRasterizer())
{
/* custom switches can be added before the file is opened
rasterizer.CustomSwitches.Add("-dPrinted");
*/
byte[] buffer = myWebClient.DownloadData(pdfUrl);
using (var ms = new MemoryStream(buffer))
{
rasterizer.Open(ms);
var image = rasterizer.GetPage(0, 0, 1);
var imageURL = "MyCDNpath/Images/" + filename + ".png";
_ = UploadFileToS3(image, imageURL);
}
}
}
You can also use it with temporary FileStream. Here is another example. Note that the File is temporary and has DeleteOnClose mark.
using (WebClient myWebClient = new WebClient())
{
using (GhostscriptRasterizer rasterizer = new GhostscriptRasterizer())
{
/* custom switches can be added before the file is opened
rasterizer.CustomSwitches.Add("-dPrinted");
*/
byte[] buffer = myWebClient.DownloadData(pdfUrl);
int bufferSize = 4096;
using (var fileStream = System.IO.File.Create("TempPDFolder/" + pdfName, bufferSize, System.IO.FileOptions.DeleteOnClose))
{
// now use that fileStream to save the pdf stream
fileStream.Write(buffer, 0, buffer.Length);
rasterizer.Open(fileStream);
var image = rasterizer.GetPage(0, 0, 1);
var imageURL = "MyCDNpath/Images/" + filename + ".png";
_ = UploadFileToS3(image, imageURL);
}
}
}
Hope it will help someone struggling to get high quality images from pdf for free.

ArgumentException when converting byte[] to Bitmap c#

I'm trying to convert a byte array to a bitmap but it always shows me:
System.ArgumentException: Parameter is not valid.
My code is as follows:
I'm passing the bytes through a webservice with:
string DecodedString = string.Empty;
DecodedString = System.Text.Encoding.GetEncoding(1251).GetString(bytes);
sResult = sResult + "<Photo>" +XmlConvert.EncodeName(DecodedString) + "</Photo>";
and in my webPage:
byte[] bytes = (Byte[])System.Text.Encoding.GetEncoding(1251).GetBytes(XmlConvert.DecodeName(xDocument.SelectSingleNode("Response/Images/Photo").InnerText));
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
System.Drawing.Bitmap b = new System.Drawing.Bitmap(ms);//(System.Drawing.Image.FromStream(ms));
Try passing the string as a Base64:
string DecodedString = string.Empty;
DecodedString = System.Convert.ToBase64String(bytes)
sResult = sResult + "<Photo>" +XmlConvert.EncodeName(DecodedString) + "</Photo>";
...
byte[] bytes = System.Convert.FromBase64String(xDocument.SelectSingleNode("Response/Images/Photo").InnerText);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
System.Drawing.Bitmap b = System.Drawing.Image.FromStream(ms);
You also won't need to use XmlConvert to encode/decode the string.
I did it, with the help of all of you, here is my page code
byte[] bytes = System.Convert.FromBase64String(xDocument.SelectSingleNode("Response/Images/Photo").InnerText);
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytes);
System.Drawing.Bitmap b = new System.Drawing.Bitmap(ms); //(Bitmap)System.Drawing.Image.FromStream(ms);
System.Drawing.Imaging.FrameDimension frameDim;
frameDim = new System.Drawing.Imaging.FrameDimension(b.FrameDimensionsList[0]);
int NumberOfFrames = b.GetFrameCount(frameDim);
string[] paths = new string[NumberOfFrames];
for (int i = 0; i < NumberOfFrames; i++)
{
b.SelectActiveFrame(frameDim, i);
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(b);
paths[i] = imagePathfile.Remove(imagePathfile.Length - 4, 4) + i.ToString() + ".gif";
bmp.Save(paths[i], System.Drawing.Imaging.ImageFormat.Gif);
//bmp.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif);
bmp.Dispose();
}
Image1.Src = paths[0];
//Check if there's more than 1 image cause its a TIFF
if (paths.Length>1)
{
Image2.Src = paths[1];
}
I had a similar problem recently, but using Silverlight. I ended up needing to create a Custom HTTP Handler in order to pass the byte[] that defined the image back as a stream.
See http://www.dotnetcurry.com/ShowArticle.aspx?ID=220
Edit: This allows you to avoid worrying about XML encoding, and passes the image back in Binary form... YMMV
According to MSDN:
ArgumentException - The stream does not have a valid image format
I believe your problem is in the original byte[] array you are passing to the web service.
According to one of your comments, you did:
System.IO.FileStream fs = new System.IO.FileStream(sPath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
int streamLength = Convert.ToInt32(fs.Length);
bytes = new byte[streamLength];
fs.Read(bytes, 0, streamLength);
fs.Read returns the number of bytes that have been read into the byte array; it doesn't always read the entire file!
Try using the StreamFile method from http://www.dotnetspider.com/resources/4515-convert-file-into-byte-array.aspx. (First result of Google search)
Try this:
byte[] bytes = System.Convert.FromBase64String(xDocument.SelectSingleNode("Response/Images/Photo").InnerText);
System.Drawing.ImageConverter imageConverter = new System.Drawing.ImageConverter();
Image image = imageConverter.ConvertFrom(bytes) as Image;
System.Drawing.Bitmap b = new System.Drawing.BitMap(image);
EDIT
Take a look at this:
Transfer any files on Web services by c#
actually i had been meet this problem, In my case, when i use IE browser, it is ok but when use another browser it always have the same error.
"Parameter is not valid exception is always happening in the same line of code:
System.Drawing.Image.FromStream(ms));"
So i think it seems this issue depend on browser and type of image (JPEG,JPEG2000).
Here is some code I used converting bytes to an image for a unit test:
protected override Image LoadImage()
{
//get a temp image from bytes, instead of loading from disk
//data:image/gif;base64,
byte[] bytes = Convert.FromBase64String("R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==");
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
}
To my understanding, the image can not be shown because the format of the image's bytes is not correct. Every image format has its own head or something.

Categories

Resources