I have two images and I want to convert it to one pdf file with one image in a page...
what is the easiest way of doing it in C#?
Edit: I tried the following code (added the PdfSharp reference):
string source1 = #"MySource1.JPG";
string source2 = #"MySource2.JPG";
string destinaton = #"MyDest.pdf";
PdfDocument doc = new PdfDocument();
doc.Pages.Add(new PdfPage());
doc.Pages.Add(new PdfPage());
XGraphics xgr = XGraphics.FromPdfPage(doc.Pages[0]);
XImage img = XImage.FromFile(source1);
XGraphics xgr2 = XGraphics.FromPdfPage(doc.Pages[1]);
XImage img2 = XImage.FromFile(source2);
xgr.DrawImage(img, 0, 0);
xgr2.DrawImage(img2, 0, 0);
doc.Save(destinaton);
doc.Close();
Now it is create a pdf with my two pages but the problem now is that the images are cut and not in their original size! the size of the pictures is 3264x2448.
How can I fix the image size to the pdf document size?
There are several overloads of DrawImage. Use an overload that allows you to specify the destination size of the image.
Three lines of code allow to calculate the image size to use the complete page (with a margin if wanted) while keeping the aspect ratio.
If you know the pdf document size, you can resize your image as:
Bitmap objBitmap = new Bitmap(objImage, new Size(size1, size2));
where objImage is your original image.
or like:
public static Image resizeImage(Image imgToResize, Size size)
{
return (Image)(new Bitmap(imgToResize, size));
}
objBitmap = resizeImage(objBitmap, new Size(size1,size2));
Related
I am using an SVGDocument to convert a graph created using Mermaid to bitmap format so it can be copied to the clipboard, saved as a bitmaps to disk etc. The code I am using is shown below. I fill the bitmap with white first as if not the image has a light grey background when copied to the clipboard.
var HTMLDocument = new HtmlAgilityPack.HtmlDocument();
HTMLDocument.LoadHtml(HTML);
// Get the SVG representing the diagram
var SVGElement = HTMLDocument.DocumentNode.Descendants("svg").FirstOrDefault();
if (SVGElement == null)
{
return;
}
// Create a SVG document from the svg element in the HTML
var Document = SvgDocument.FromSvg<SvgDocument>(SVGElement.OuterHtml);
// Get the size of the SVG element so we can create a bitmap
// to match
var Bounds = Document.Bounds;
// Adjust the width and height to take account of the position
var Width = Bounds.Width + Bounds.Left + 10;
var Height = Bounds.Height + Bounds.Top + 100;
// Create a new bitmap of the correct size
var Bitmap = new Bitmap((int)Width, (int)Height);
// Fill it with white and then draw the SVG diagram
using (var BitMapGraphics = Graphics.FromImage(Bitmap))
{
BitMapGraphics.FillRectangle(new SolidBrush(Color.White), 0, 0, Width, Height);
Document.Draw(BitMapGraphics);
}
However, when pasted from the clipboard, the image does not show any text within the graph shapes. The original Mermaid diagram is:
When pasted from the clipboard using the bitmap created above becomes:
Any thoughts on why the text within the shapes is not being rendered would be much appreciated.
I'm currently using the below code to put an image on top of another image
Stream stream = client.OpenRead(some URL here);
Bitmap baseimg = (Bitmap)System.Drawing.Image.FromStream(stream);
Bitmap ovlimg = (Bitmap)System.Drawing.Image.FromFile("fanmade.png");
var finalImage = new Bitmap(baseimg.Width, baseimg.Height);
var graphics = Graphics.FromImage(finalImage);
graphics.CompositingMode = CompositingMode.SourceOver;
graphics.DrawImage(baseimg, 0, 0);
graphics.DrawImage(ovlimg, 0, 0);
finalImage.Save("1.png", System.Drawing.Imaging.ImageFormat.Png);
However, the file size turns out to be a lot bigger than expected from 6-9 Mb to 16Mb. So I'm trying to find a more efficient way that would make the file size smaller while still keeping the image quality
Here are both the images
The Base IMG (Changes based on the user input but here's an example): https://pasteboard.co/K6hCXng.png
The overlay IMG: https://pasteboard.co/K6hDvIc.png
I need a method or library that convert a image jpg to file pdf. I tried find in web, but I did find only the SautinSoft, but this is to pdf to jpg and is not free.
Can someone help me?
This function is for C# 3.5.
What you need is a library to create PDFs, like http://www.pdfsharp.net/
Then you can create a pdf document and inject your image into it. You're not looking to convert a JPG to a PDF, that doesn't make much sense, you're trying to create a PDF with your JPG inside it.
Sample code from another answer: Overlay image onto PDF using PDFSharp
private void GeneratePDF(string filename, string imageLoc)
{
PdfDocument document = new PdfDocument();
// Create an empty page or load existing
PdfPage page = document.AddPage();
// Get an XGraphics object for drawing
XGraphics gfx = XGraphics.FromPdfPage(page);
DrawImage(gfx, imageLoc, 50, 50, 250, 250);
// Save and start View
document.Save(filename);
Process.Start(filename);
}
void DrawImage(XGraphics gfx, string jpegSamplePath, int x, int y, int width, int height)
{
XImage image = XImage.FromFile(jpegSamplePath);
gfx.DrawImage(image, x, y, width, height);
}
I'm able to save the captured image from a barcode scanner using this code:
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.DefaultExt = ".jpg";
dlg.Filter = "JPEG Images (.jpg)|*.jpg|All files (*.*)|*.*";
if (dlg.ShowDialog() == true)
{
using (FileStream file = File.OpenWrite(dlg.FileName))
{
file.Write(e.ImageBuffer, 0, e.ImageSize);
}
}
However, I would like to display the captured image using WPF but I get a distorted image.
private void _barcodeScannerInstance_SavePhotoEvent(object sender, ImageEventArgs e)
{
SetBitmap(e.ImageBuffer, 350, 263, 96);
}
private void SetBitmap(byte[] image, int width, int height, int dpi)
{
MainWindow.Instance.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
BitmapSource bitmapSource = BitmapSource.Create(
width, height, (double)dpi, (double)dpi, PixelFormats.Bgr24, null, image, ((width * 24 + 31) & ~31) >> 3);
HwModeScreen.BarcodeImageCanvas.Children.Clear();
Image myImage = new Image();
myImage.Width = HwModeScreen.BarcodeImageCanvas.ActualWidth;
myImage.Height = HwModeScreen.BarcodeImageCanvas.ActualHeight;
myImage.Stretch = Stretch.Fill;
myImage.Source = bitmapSource;
HwModeScreen.BarcodeImageCanvas.Children.Add(myImage);
});
Here is the image I see. It should be a black and white picture of a kleenex box.
Here is the saved jpg file:
did you mix up width and height? are you sure your dpi value is correct?
I suspect the whole problem is this line:
BitmapSource bitmapSource = BitmapSource.Create(
width, height, (double)dpi, (double)dpi, PixelFormats.Bgr24, null, image, ((width * 24 + 31) & ~31) >> 3)
What I would do to debug the issue is to write out the image to file and confirm all the inputs. Use photoshop, paint.net, file properties...
Are you sure you are working with bitmap format?
Are you sure you are working with 24bits per pixel?
Are you sure you have height and width correct, and you are feeding the values into the correct argument
What is this line all about, and why are you doing it? I am slightly suspicious.
((width * 24 + 31) & ~31) >> 3)
Basically, the way I look at this is that you are feeding the bitmap library a stream of bits... it doesn't know what the bits are but it will attempt to create the image from the information you give it: bits per pixel, size, etc. If you give it incorrect information, it will create a corrupted image as you have shown.
I am slightly suspicious that the problem is not with width and height; even if you mix those two values up-- I think you would get at least part of the first row of pixels to be rendered correctly. I see static / noise / snow, which tells me that there is something about the way the stream of bits was interpreted-- it is rendered as random blacks and whites.
Another thing: in your screen cap, I see color. this is another hint that there is something incorrect about your assumptions about the image. The values should probably 1 to 256 ( 8 bits per pixel I think? ) I would try creating a 8 bit per pixel black and white bitmap. Somehow the library thinks this is a color image.
I just noticed that you are assuming jpeg. jpeg is a lossy format-- I would have assumed that you would end up with a bitmap or tiff image. double check that you are indeed getting back a jpeg image (check the barcode api documentation)
The JPEG compression algorithm is quite unsuitable for the kind of image you are capturing. It works well for photos, it behaves poorly on images containing fine lines. The slight artifacts the compression produces makes it a lot harder to properly scan the barcode.
You don't see the Kleenex box because you are writing the raw image bytes. You need to use an image encoder. I recommend you use the PngBitmapEncoder class. GifBitmapEncoder should work too since you don't need a lot of colors, it makes smaller files. A code snippet that shows how to use an encoder is available here.
this is likely distorting it
myImage.Stretch = Stretch.Fill;
I used a jpeg decoder to fix the problem.
private void SetBitmap(byte[] image, int width, int height, int dpi)
{
MainWindow.Instance.Dispatcher.Invoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
BMemoryStream ms = new MemoryStream(image);
JpegBitmapDecoder decoder = new JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
HwModeScreen.BarcodeImageCanvas.Children.Clear();
Image myImage = new Image();
myImage.Width = HwModeScreen.BarcodeImageCanvas.ActualWidth;
myImage.Height = HwModeScreen.BarcodeImageCanvas.ActualHeight;
myImage.Stretch = Stretch.Fill;
myImage.Source = bitmapSource;
HwModeScreen.BarcodeImageCanvas.Children.Add(myImage);
});
Alright, I have an image coming through from an external application in an 8-bit indexed format. I need this image converted to a 24-bit format of the exact same size.
I've tried creating a new Bitmap of the same size and of type Format24bppRgb and then using a Graphics object to draw the 8-bit image over it before saving it as a Bmp. This approach doesn't error out but when I open the resulting image the BMP header has all kinds of funky values. The height and width are HUGE and, in addition, there are funny (and large) values for the compression flags and a few others. Unfortunately my particular requirements are to pass this file off to a specific printer driver that demands a 24-bit image with specific header values (which I'm trying to achieve through GDI+)
Anyone know of an example on "up-converting" an indexed file to a not-indexed 24-bit file? If not an example, which path should I start down to write my own?
-Kevin Grossnicklaus
kvgros#sseinc.com
I used the code below to "up-convert" an image from 8bpp to 24bpp. Inspecting the generated 24bpp file with a hex editor and comparing against the 8bpp file shows no difference in height and width in the two files. That is, the 8bpp image was 1600x1200, and the 24bpp image has the same values.
private static void ConvertTo24(string inputFileName, string outputFileName)
{
Bitmap bmpIn = (Bitmap)Bitmap.FromFile(inputFileName);
Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format24bppRgb);
using (Graphics g = Graphics.FromImage(converted))
{
// Prevent DPI conversion
g.PageUnit = GraphicsUnit.Pixel
// Draw the image
g.DrawImageUnscaled(bmpIn, 0, 0);
}
converted.Save(outputFileName, ImageFormat.Bmp);
}
Everything else in the headers looks reasonable, and the images display identical on my system. What "funky values" are you seeing?
This is my conversion code. Notice the matching of resolution between source image and resulting image.
private void ConvertTo24bppPNG(Stream imageDataAsStream, out byte[] data)
{
using ( Image img = Image.FromStream(imageDataAsStream) )
{
using ( Bitmap bmp = new Bitmap(img.Width, img.Height, PixelFormat.Format24bppRgb) )
{
// ensure resulting image has same resolution as source image
// otherwise resulting image will appear scaled
bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution);
using ( Graphics gfx = Graphics.FromImage(bmp) )
{
gfx.DrawImage(img, 0, 0);
}
using ( MemoryStream ms = new MemoryStream() )
{
bmp.Save(ms, ImageFormat.Png);
data = new byte[ms.Length];
ms.Position = 0;
ms.Read(data, 0, (int) ms.Length);
}
}
}
}
It seems odd that you're creating a Bitmap of the same width and height as your input, yet the generated BMP is much larger. Can you post some code?
The problem is probably the difference between the Vertical- and HorizontalResolution of your source image and your output image. If you load a 8bpp indexed bitmap with a resolution of 72 DPI, and then create a new 24bpp bitmap (default resolution will be 96 DPI... at least it is on my system) and then use Graphics.DrawImage to blit to the new bitmap, your image will appear slightly zoomed in and cropped.
Having said that, I don't know off the top of my head how to properly create the output Bitmap and/or Graphics object to scale properly when saved. I suspect it will have something to do with creating the images using a common scale like inches instead of pixels.