System.Drawing.Common.Bitmap cross platform alternatives - c#

I am looking to convert PDF files into images. Docnet is able to convert the pdf into bytes[] and their samples show how to save this byte[] into an image file using Bitmap. Documentation
However, the solution won't work on linux machine since Bitmap requires few libraries pre-installed on the system.
I've tried ImageSharp to convert the byte[] using SixLabors.ImageSharp.Image.Load<Bgra32>(rawBytes), however, it throws Unhandled exception. SixLabors.ImageSharp.InvalidImageContentException: PNG Image does not contain a data chunk.
Does anyone knows any alternative to achieve this.
PS - I'm open to explore any other cross platform FREE supported alternatives to convert PDF files to images.

This works fine with ImageSharp assuming Docnet works then ImageSharp will work fine for you.
The trick is you want to be using the Image.LoadPixelData<Bgra32>(rawBytes, width, height); API not the Image.Load<Bgra32>(encodedBytes); one.
using Docnet.Core;
using Docnet.Core.Models;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using var docReader = DocLib.Instance.GetDocReader(
"wikipedia_0.pdf",
new PageDimensions(1080, 1920));
using var pageReader = docReader.GetPageReader(0);
var rawBytes = pageReader.GetImage();
var width = pageReader.GetPageWidth();
var height = pageReader.GetPageHeight();
// this is the important line, here you are taking a byte array that
// represents the pixels directly where as Image.Load<Bgra32>()
// is expected an encoded image in png, jpeg etc format
using var img = Image.LoadPixelData<Bgra32>(rawBytes, width, height);
// you are likely going to want this as well otherwise you might end up with transparent parts.
img.Mutate(x => x.BackgroundColor(Color.White));
img.Save("wikipedia_0.png");

Related

How can I get image content as pixel and create image from it in ASP.NET Core 6 Web API?

I try to save my images on my server, but I can't let my server save file and virus because of that I want to get image content as pixels of rgb and after that I create image by myself.
I can't use bitmap (or other type in C# like bitmapImage, ... etc) and I don't know how I can do this with sixlabors.ImageSharp.
I have some code that I tried but I can't implement the exact logic that I want (code shown here):
[HttpPost("[action]")]
public async Task<IActionResult> Get([FromForm] ImageFormat file)
{
await using var memoryStream = new MemoryStream();
await file.File.CopyToAsync(memoryStream);
IImageFormat format;
using (var image = Image.Load(memoryStream.ToArray(), out format))
{
using (var output = new MemoryStream())
{
image.Save(output, format);
var responseType = format.Name.ToLower();
return File(output.ToArray(), "application/octet-stream", file.File.FileName);
}
}
return null;
}
Can anybody help me with this problem?
i don't see a reason to convert image into image: there are several format zip-algorythms etc.wich you have to support in that case. example jpg is not bitmap, there is convertion issue - quality of image becomes less each conversion time. Image itself is not executable - it can be used only as container for virus body, can't harm your OSystem itself, another executable part should works somewhere.
But even if you would like to store images on disk, in other format - you can convert image to base64 text (one line of code, like example) - it less harmful and well known way to work with any file type. you can zip image by cszip, you can change file name and extension to hide file type.
I don't see a reasson to convert one image to another for this scenario/task.

c# .NET CORE adding image with transparency to existing PDF using ITextSharp

My goal is to add company logo to every page of an existing pdf(not watermark).
Due to pdf file and logo specifics, I can only place the logo on top of the pdf content(not underneath) and the logo has to support transparency.
One more limitation is I have to use .NET Core.
Posting this with an answer, because I could not find a clear solution.
Suggestions/corrections/improvements are welcome.
Hope someone finds this useful.
The newest iTextSharp library to support .NET Core is iText7 however I cannot use it legitemately; neither making my code open source, nor purchasing the licence is an option for me. Therefore I use old, third party library:
Install-Package iTextSharp.LGPLv2.Core
Latest version, the one I'm using, at the time of this post is 1.3.2
Following usings are required
using System;
using System.Drawing.Imaging;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
To acheve image transparency in pdf, image has to be opened in a correct format
var preImage = System.Drawing.Image.FromFile(imagePath);
var image = Image.GetInstance(preImage, ImageFormat.Png);
When adding the image, it is also important to not select the image to be inline
canvas.AddImage(image);//do not put .AddImage(image, true);
Here is all the code
var imagePath = "logo.png";
var pdfPath = "edit_this.pdf";
//load pdf file
var pdfBytes = File.ReadAllBytes(pdfPath);
var oldFile = new PdfReader(pdfBytes);
//load image
var preImage = System.Drawing.Image.FromFile(imagePath);
var image = Image.GetInstance(preImage, ImageFormat.Png);
preImage.Dispose();
//optional: if image is wider than the page, scale down the image to fit the page
var sizeWithRotation = oldFile.GetPageSizeWithRotation(1);
if (image.Width > sizeWithRotation.Width)
image.ScalePercent(sizeWithRotation.Width / image.Width * 100);
//set image position in top left corner
//in pdf files, cooridinates start in the left bottom corner
image.SetAbsolutePosition(0, sizeWithRotation.Height - image.ScaledHeight);
//in production, I use MemoryStream
//I put FileStream here to test the code in console application
using (var newFileStream = new FileStream("with_logo.pdf", FileMode.Create))
{
//setup PdfStamper
var stamper = new PdfStamper(oldFile, newFileStream);
//iterate through the pages in the original file
for (var i = 1; i <= oldFile.NumberOfPages; i++)
{
//get canvas for current page
var canvas = stamper.GetOverContent(i);
//add image with pre-set position and size
canvas.AddImage(image);
}
stamper.Close();
}
This code works with local files.
In my (real world) case, I receive pdf files as Base64 string, add a logo from local storage, convert it back to Base64 string and output it on a web-page.
I open the image as PNG forcefully(hardcoded) because I control what extension does the logo have. If necessary you can dynamicaly set the image format.

Set image resolution

I have array of image bytes and I would like to set resolution. Original image can be JPEG, PNG, BMP. Output - PNG. I am using ImageMagic to convert image and do some manipulations.
using (var image = this.Convert(originalImage, height, width))
using (var stream = new MemoryStream())
{
image.Quality = 90;
image.Write(stream, MagickFormat.Png);
return stream.GetBuffer();
}
I tryed to modify image.GetExifProfile, but has no success (at least for PNG images).
I can't use any comandline tool (like ImageMagic or ExifTool) here.
There are 3 exiff tags I need to modify
XResolution
YResolution
ResolutionUnit
I can successfully achieve this with bitmap, but it also resource overhead (need to create MemoryStream ...).
I have found some Pdf specification, but it will consume time to make it all work.
Does any can point me to right direction?
Thanks.

BadImage Error When Loading Tiff CCITTv4 Via SharpDX.Direct2D1.Bitmap.FromWicBitmap

I'm using SharpDX and its accompanying WIC and Direct2D wrappers to do some serverside image manipulation.
The following code works great with JPEG images and is modeled after the SharpDX docs and this Microsoft sample using D2D directly via C++.
However, I get a BadImage error when I try to load a TIFF CCITT (bitonal 1bpp) image. The BadImage error is only thrown at EndDraw, (which happens later on in the commented DrawEndorsement function), or at this line of code which I inserted to make the point at which the issue occurs more obvious:
SharpDX.Direct2D1.Bitmap bitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(_renderTarget, _wicBitmap);
The JPEG image I pass in gets to this point and continues with no issues, but the TIFF I pass in gets to this point and causes FromWicBitmap to barf with a BadImage error.
I'm using FormatConverter to convert the TIFF/JPEG pixel formats to an appropriate and supported D2D pixel format, and the converter does change the pixel format GUID for both images, but, again, FromWicBitmap barfs only on the TIFF.
I assumed I was doing something wrong with conversion or misusing SharpDX/D2D, but when I built and ran the aforementioned Microsoft C++ D2D image viewer sample, it loaded and rendered this same TIFF file with no errors. I double checked the sample's code to verify that I was using all the same pixel formats, options, etc, and it looks like I'm doing almost exactly the same thing with SharpDX that the sample is doing with D2D directly.
Clearly Direct2D doesn't like the pixel format of the TIFF image that WIC is handing it, but why didn't the MS sample exhibit the same behavior, and why didn't FormatConverter fix it?
Am I missing something that the D2D sample code is doing?
Am I missing some trick with SharpDX?
Is this a SharpDX bug?
Thanks!
public byte[] BuildImage(byte[] image, Format saveFormat)
{
SharpDX.WIC.Bitmap _wicBitmap;
WicRenderTarget _renderTarget;
BitmapFrameDecode bSource;
FormatConverter converter = new FormatConverter(_factoryManager.WicFactory);
using (MemoryStream systemStream = new MemoryStream(image))
using (WICStream wicStream = new WICStream(_factoryManager.WicFactory, systemStream))
{
BitmapDecoder inDecoder = new BitmapDecoder(_factoryManager.WicFactory, wicStream, DecodeOptions.CacheOnLoad);
if (inDecoder.FrameCount > 0)
{
bSource = inDecoder.GetFrame(0);
converter.Initialize(bSource, SharpDX.WIC.PixelFormat.Format32bppPRGBA, BitmapDitherType.Solid, null, 0.0f, BitmapPaletteType.MedianCut);
_imageWidth = bSource.Size.Width;
_imageHeight = bSource.Size.Height;
}
else
{
throw new Exception("No frames found!");
}
}
_wicBitmap = new SharpDX.WIC.Bitmap(
_factoryManager.WicFactory,
converter,
BitmapCreateCacheOption.CacheOnDemand
);
_renderTarget = new WicRenderTarget(_factoryManager.D2DFactory, _wicBitmap, new RenderTargetProperties());
SharpDX.Direct2D1.Bitmap bitmap = SharpDX.Direct2D1.Bitmap.FromWicBitmap(_renderTarget, _wicBitmap);
//DrawEndorsement(_renderTarget);
_renderTarget.Dispose();
bSource.Dispose();
converter.Dispose();
return SaveImage(saveFormat, _wicBitmap);
}
As xoofx pointed out, turns out that this was caused by my disposing of the WIC/MemoryStreams underlying the FormatConverter while it was still in use.
This was causing JPEGs to be corrupted on write, and weirdly causing the TIFFs to fail even before that.
Extended the using scope accordingly and that fixed it.

Is there any way for get Silverlight UI Element as an image?

I want to export an image of my ArcGIS map object with the graphics layer on it. I've tried esri's own web services for export but they're not so efficient and clear, not supporting complex geometric shapes also they're not support local layers such as Google map provider. Service supports only ArcGISTiledLayer i want it in all layers. So, i searched in their forums but they say they won't support local layers until next versions.
I've tried ImageTool libraries and WritableBitmapEx libraries in codeplex. But when i try to get byte[] from a WritableBitmap i can not access its Pixels property for some security reasons all the time. Application throws a SecurityException and says that 'you can't access this pixels property'.
So, is there any way for get a UIElement control's image and save it to the disk? Or is there a workaround for this security exception?
Yes the image tools library has a method to do this into png/jpg etc.
http://imagetools.codeplex.com/
Also you can use RenderTargetBitmap - http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.rendertargetbitmap.aspx
Here is an example of how to save a file to disk. you can only do it from a dialog
http://www.silverlightshow.net/items/Using-the-SaveFileDialog-in-Silverlight-3.aspx
EDIT - Sample Code
Calling
var objImage = new WritableBitmap(MyElement, MyElement.RenderTransform);
var bytData = objImage.ToPng();
Extension Method
using ImageTools.IO.Png;
using ImageTools;
public static byte[] ToPng(this WriteableBitmap Image)
{
byte[] bytResult;
using (MemoryStream objPngStream = new MemoryStream())
{
PngEncoder objPngEncoder = new PngEncoder();
objPngEncoder.Encode(Image.ToImage(), objPngStream);
objPngStream.Seek(0, SeekOrigin.Begin);
bytResult = objPngStream.ToArray();
objPngStream.Close();
}
return bytResult;
}

Categories

Resources