I am trying to create a Bitmap from a stream that has a PDF document saved with-in the stream, but I keep getting argument null exception. The MS is not null and it is positioned at 0. So I'm lost as to what else to do.
I'm testing the functionality by using a windows forms application sandbox but I cannot get the memory stream to save to a Bitmap.
Can someone point out to me where I'm going wrong?
private async void Form1_Load(object sender, EventArgs e)
{
//4355,4373
IElevation elev = await ElevationManager.GetElevationAsync(4355);
PdfSharp.Pdf.PdfDocument pdfDoc =
await (await AlumCloudPlans.Manager.GetLabelsAsync(elev)).GetPDF(new SheetInfo(/*settings for PDF, Img printing is different*/3, 10, 240, 95, 780, 1000));
System.IO.Stream ms = new MemoryStream();
pdfDoc.Save(ms, false);
ms.Position = 0;
Bitmap bm = new Bitmap(ms); <---------(Error right here, says argument null)
this.AutoScroll = true;
this.pictureBox1.Image = bm;
this.pictureBox1.BackColor = Color.White;
this.Size = new System.Drawing.Size(bm.Width, (bm.Height + 50) / 2);
this.pictureBox1.Size = new System.Drawing.Size(bm.Width, bm.Height + 5);
}
What am i missing here?
You're trying to open stream containing a PDF document, Bitmap constructor is expecting image data. PDFSharp can only create PDF document, but can't render it to image.
To render PDF document to bitmap, you have to use other libraries, e.g. lib-pdf, mupdf-converter or .NET wrapper for Ghostscript.
Related
GOAL
To open an existing PDF file with multiple pages and add background image to all pages. (Optionally the background image of the first page differs from the others)
In my current implementation (I use .NET 6 and PDFsharp btw.) I add the image to each page, which increases the size of the file dependent on the number of pages.
QUESTION
Is there a way in PDFsharp/MigraDoc to embed a background image only once into the document and then reference it for each page?
CODE
Both PDF document and the image come from a database as byte arrays.
public byte[] AddBackgroundImgToDocument(byte[] doc, byte[] imgFirstPage, byte[]? imgOtherPages=null)
{
using var ms = new MemoryStream(doc);
PdfDocument pdfDoc = PdfReader.Open(ms, PdfDocumentOpenMode.Modify);
for (int i = 0; i < pdfDoc.PageCount; i++)
{
if(i > 0 && imgOtherPages != null && imgOtherPages.Length > 0)
AddBackgroundImageFromByteArray(pdfDoc.Pages[i], imgOtherPages);
else
AddBackgroundImageFromByteArray(pdfDoc.Pages[i], imgFirstPage);
GC.Collect();
GC.WaitForPendingFinalizers();
}
using var oms = new MemoryStream();
pdfDoc.Save(oms);
ms.Dispose();
pdfDoc.Dispose();
return oms.ToArray();
}
public void AddBackgroundImageFromByteArray(PdfPage page, byte[] imgfile)
{
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
MemoryStream ms = new System.IO.MemoryStream(imgfile);
ms.Position = 0;
XImage image = XImage.FromStream(() => ms);
gfx.DrawImage(image, 0, 0, page.Width, page.Height);
ms.Dispose();
}
SOLUTION
Rewriting the method above according to accepted answer, solved my problem:
public void AddBackgroundImageFromByteArray(PdfPage page, byte[] imgfile)
{
if(!ximageLoaded)
{
MemoryStream ms = new System.IO.MemoryStream(imgfile);
ms.Position = 0;
backimg = XImage.FromStream(() => ms);
ms.Dispose();
ximageLoaded = true;
}
XGraphics gfx = XGraphics.FromPdfPage(page, XGraphicsPdfPageOptions.Prepend);
gfx.DrawImage(backimg, 0, 0, page.Width, page.Height);
}
With PDFsharp and MigraDoc this optimization is done automatically if you use them as intended.
Load the image once with PDFsharp and add it to as many pages as you like, there will be only one copy of the image in the document.
I want to download an image file via XPath using selenium. But I am getting the error that the file was not found.
var resimadresi = driveri.FindElement(By.XPath("/html/body/table[3]/tbody/tr/td/center/table/tbody/tr[2]/td[2]/center/table/tbody/tr[1]/td[4]/table/tbody/tr/td[2]/img"));
WebClient webClient = new WebClient();
webClient.DownloadFile(resimadresi.Text, #"image.png");
You can't do what you want to do with fetchin src of image. Because on every request the image changes. You can take a screenshot of your page and extract the image with some bitmap operations.
void SomeMethod() {
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("https://ebildirge.sgk.gov.tr/WPEB/amp/loginldap");
Screenshot ss = driver.GetScreenshot();
byte[] screenshotAsByteArray = ss.AsByteArray;
Bitmap bmp;
using (var ms = new MemoryStream(screenshotAsByteArray))
{
bmp = new Bitmap(ms);
}
Bitmap cropped = cropAtRect(bmp, new Rectangle(530, 350, 60, 40));
cropped.Save("test.jpeg", ImageFormat.Jpeg);
}
static Bitmap cropAtRect(Bitmap b, Rectangle r)
{
Bitmap nb = new Bitmap(r.Width, r.Height);
Graphics g = Graphics.FromImage(nb);
g.DrawImage(b, -r.X, -r.Y);
return nb;
}
Here is the downloaded image :
Try:
var resimadresi = driveri.FindElement(By.XPath("//td[contains(text(), "Güvenlik Anahtarı")]/following-sibling::node()[img]"));
WebClient webClient = new WebClient();
webClient.DownloadFile(resimadresi.Text, #"image.png");
Güvenlik Anahtarı is the text that I see beside the Verification code, feel free to replace it to whatever you see beside it. There was no translation to english option for me so, I can't really have an accurate text for the xpath.
I have two images on my web page that I have created using the iTextSharp Image function that converts the image byte data in the database to images. Now I want to convert both images into a single PDF and then print the PDF. The converting of the PDF is working but the print dialog box does not open. My code is as below. Here image1 and image2 are the asp:Images in the web page where the two images are displayed.
protected void button_print_Click(object sender, EventArgs e)
{
try
{
byte[] img1 = null;
byte[] img2 = null;
try
{
SqlCommand select = new SqlCommand("select Image1, Image2 from Images where ID=#id", con);
select.Parameters.AddWithValue("#id", ViewState["ImageID"].ToString());
if (con.State != ConnectionState.Open)
{
con.Open();
}
using (SqlDataReader da = select.ExecuteReader())
{
while (da.Read())
{
img1 = (byte[])da["Image1"];
img2 = (byte[])da["Image2"];
}
}
}
catch
{
// throws exception
}
finally
{
if (con.State == ConnectionState.Open || con.State == ConnectionState.Broken)
{
con.Close();
}
}
image1.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(img1, 0, img1.Length);
image2.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(img2, 0, img2.Length);
iTextSharp.text.Image imageOne = iTextSharp.text.Image.GetInstance(CreateThumbnail(img1));
iTextSharp.text.Image imageTwo = iTextSharp.text.Image.GetInstance(CreateThumbnail(img2));
Document document = new Document(PageSize.A4, 0f, 0f, 0f, 0f);
using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
{
PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
document.Add(imageOne);
Paragraph line = new Paragraph("----------------------------------------------------------------------------------------------------------------------------------------------------");
line.Alignment = Element.ALIGN_CENTER;
document.Add(line);
document.Add(imageTwo);
document.Close();
byte[] bytes = memoryStream.ToArray();
memoryStream.Close();
}
// CODE FOR PRINTING THE PDF DOCUMENT
}
catch
{
// throws exception
}
}
I am not sure what functions to use for opening the print dialog boxes. I tried a few such as PrintDialog but not sure how it works. Can someone suggest me a better way to print the PDF document that works in all web browsers and all printers? If possible with the code for printing the PDF document.
Since this is a web application it is running in a web browser. You can't instruct a web browser to print a PDF object without downloading it first. Even after downloading the PDF document you can't have the web application print the PDF automatically after download.
A better approach for web is to convert the PDF to HTML or even better make sure the document and it's content is a webpage by itself. You can have the webbrowser show the print dialog by running one line of javascript. If you want to have this automatically you can put it in the page load event.
document.addEventListener("DOMContentLoaded", function() {
window.print();
});
i am a new to c# programming and i am doing a project that can capture the screen and attach it to a pdf,in my project i need to attach an screenshot of my desktop or application directly to PDF file, i know how to attached a image that has been saved in to the Hard Drive, in this case i used iTextsharp library. what i need to know is there a way to attach the image directly to PDF without saving the image to Hard Drive. till now I can capture my screen and save it to the hard drive. please direct me to a path, Thanx In Advance , code i used is bellow
this is the code i used to capture the screen
string pHotoTime = DateTime.Now.ToString("yyyy-MM-dd, HH mm ss");
Size s = Screen.PrimaryScreen.Bounds.Size;
Bitmap bmp = new Bitmap(s.Width, s.Height);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(0, 0, 0, 90, s);
System.IO.Stream stream = new System.IO.MemoryStream();
bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
// later:
//bmp.Save(#"C:\Users\NiyNLK\Documents\TESTs\" + pHotoTime + ".jpg");
bmp.Save(#"C:\Users\NiyNLK\Documents\TESTs\MyImage.jpg");
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = bmp;
below code is used to attached the image
enter code here
iTextSharp.text.Rectangle r = new iTextSharp.text.Rectangle(400, 400);
var doc = new Document(r);
string path = #"c:\users\niynlk\documents\tests";
string Imagepath = #"C:\Users\NiyNLK\Documents\TESTs";
try
{
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(path + "/Images.pdf", FileMode.Create));
doc.Open();
doc.Add(new Paragraph("Image"));
Image img = Image.GetInstance(Imagepath + "/MyImage.jpg");
img.ScalePercent(25f);
doc.Add(img);
}
catch (Exception)
{
throw;
}
finally
{
doc.Close();
}
protected void btnCropIt_Click(object s, EventArgs e)
{
System.Drawing.Image img = System.Drawing.Image.FromFile(Server.MapPath("../upload/" + u.Avatar));
var m = cropImage(img, new Rectangle(0, 0, 50, 50));
System.IO.File.Delete(Server.MapPath("../upload/" + u.Avatar));
m.Save(Server.MapPath("../upload/" + u.Avatar));
}
private static System.Drawing.Image cropImage(System.Drawing.Image img, Rectangle cropArea)
{
Bitmap bmpImage = new Bitmap(img);
Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);
return (System.Drawing.Image)(bmpCrop);
}
System.IO.File.Delete(Server.MapPath("../upload/" + u.Avatar));
This line of code throws exception that it can't delete image, it's used by another process. Any Idea? How to overwrite it?
Your code is still using it. FromFile() keeps it locked until the image is disposed. It's kind of an obscure semantic, but the MSDN documentation does mention it.
You might try img.Finalize() right after cropImage() as a simple fix. If that doesn't work, pull it in with a FileStream, use the System.Drawing.Bitmap Stream constructor overload, then close the FileStream immediately.