I have seen many issues involving the GDI+ Generic Error, but I have not seen this particular matter raised before. We are consistently getting the error, on Windows systems other than Windows 8, when attempting to read (System.Drawing.Image.SelectActiveFrame) a multiple-frame tiff that includes frames in mixed Photometric Interpretation formats. That is to say, the file includes both RGB color and min-is-white formats, with corresponding differences in the Bits/Sample and Samples/Pixel frame parameters. The error is consistently raising as soon as a frame is encountered with a format that is different from that of the first frame.
// Convert File from .tiff to .PDF
static void ConvertFile(string file, string pdffilename)
{
string localMessage = string.Empty;
try
{
//if it's a PDF Just renamed it and continue
if (file.ToLower().Contains(".pdf"))
{
File.Copy(file, pdffilename);
return;
}
// If file exists return
if (File.Exists(pdffilename)) { return; }
using (var stream = new FileStream(pdffilename, FileMode.Create))
{
localMessage = "01";
var document = new iTextSharp.text.Document();
localMessage = "01";
var writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, stream);
localMessage = "02";
var bm = Bitmap.FromFile(file);
localMessage = "03";
var total = bm.GetFrameCount(FrameDimension.Page);
localMessage = "04";
document.Open();
//iTextSharp.text.pdf.PdfContentByte cb = writer.DirectContent;
localMessage = "05";
iTextSharp.text.Image img = null;
for (var currentframe = 0; currentframe < total; ++currentframe)
{
localMessage = "06=>" + currentframe.ToString();
bm.SelectActiveFrame(FrameDimension.Page, currentframe);
localMessage = "07=>" + currentframe.ToString();
img = iTextSharp.text.Image.GetInstance(bm, ImageFormat.Bmp);
localMessage = "08=>" + currentframe.ToString();
img.ScalePercent(72f / img.DpiX * 100);
localMessage = "09=>" + currentframe.ToString();
img.SetAbsolutePosition(0, 0);
localMessage = "10=>" + currentframe.ToString();
iTextSharp.text.Rectangle pageRect = new iTextSharp.text.Rectangle(0, 0, img.ScaledWidth, img.ScaledHeight);
localMessage = "11=>" + currentframe.ToString();
document.SetPageSize(pageRect);
localMessage = "12=>" + currentframe.ToString();
document.NewPage();
localMessage = "13=>" + currentframe.ToString();
document.Add(img);
}
localMessage = "14";
bm.Dispose();
localMessage = "15";
document.Close();
localMessage = "16";
stream.Close();
}
}
catch (Exception exception)
{
string msg = exception.Message + "\r\n" +
"Coversion Error--\r\n" +
"\tinput file name: " + file + "\r\n" +
"\toutput file name: " + pdffilename + "\r\n" +
"\tlocal message" + localMessage + "\r\n";
Console.WriteLine(msg);
SaveError(msg);
throw;
}
}
The "local message" is always "06=>n", where n is the 0-based index of the frame that transitions to a new format.
Does anyone know why this is happening or how to fix it?
Related
I have a function in my controller which receives an object and uses the object's data to fill a PDF. I want to send this PDF to the client so he can download it.However When I submit the form and download the generated PDF i get an error saying "ERROR: Failed to load PDF document."
Here is my code so far:
private void crear_pdf_ZURICH(Seguro seguro)
{
var nombre_pdf = seguro.Nombre + ".pdf";
string oldFile = Server.MapPath("pdf") + "\\" + nombre_pdf;
string newFile = Server.MapPath("pdf") + "\\" + "nuevo_" + nombre_pdf;
using (var reader = new PdfReader(oldFile))
{
using (var fileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
//VARIABLES
for (var i = 1; i <= reader.NumberOfPages; i++)
{
document.NewPage();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
var importedPage = writer.GetImportedPage(reader, i);
var contentByte = writer.DirectContent;
contentByte.AddTemplate(importedPage, 0, 0);
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 10);
if (reader.NumberOfPages - (reader.NumberOfPages - i) == 1)
{
//WRITE SOME STUFF
}
else if (reader.NumberOfPages - (reader.NumberOfPages - i) == 2)
{
//WRITE SOME OTHER STUFF
}
contentByte.EndText();
}
document.Close();
writer.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename="+newFile));
}
}
}
And this is my code working properly, it creates the PDF and I can open it without any problem, however I'm saving it on the server which can cause problems if multiple users are trying to create and download the generated PDF directly from the server.
Here is my code:
private void crear_pdf_ZURICH(Seguro seguro)
{
var nombre_pdf = seguro.Nombre + ".pdf";
string oldFile = Server.MapPath("pdf") + "\\" + nombre_pdf;
string newFile = Server.MapPath("pdf") + "\\" + "nuevo_" + nombre_pdf;
using (var reader = new PdfReader(oldFile))
{
using (var fileStream = new FileStream(newFile, FileMode.Create, FileAccess.Write))
{
var document = new Document(reader.GetPageSizeWithRotation(1));
var writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
//VARIABLES
for (var i = 1; i <= reader.NumberOfPages; i++)
{
document.NewPage();
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
var importedPage = writer.GetImportedPage(reader, i);
var contentByte = writer.DirectContent;
contentByte.AddTemplate(importedPage, 0, 0);
contentByte.BeginText();
contentByte.SetFontAndSize(baseFont, 10);
if (reader.NumberOfPages - (reader.NumberOfPages - i) == 1)
{
//WRITE SOME STUFF
}
else if (reader.NumberOfPages - (reader.NumberOfPages - i) == 2)
{
//WRITE SOME STUFF
}
contentByte.EndText();
}
document.Close();
writer.Close();
}
}
}
Thanks in advance if someone can help/explain me how to solve this issue.
I have a process that accepts data from an HTML page, and stamps that data onto a PDF and saves the PDF to a 3rd party imaging system.
The HTML page accepts info for up to 8 users. However, the PDF only has room for up to 4 users. So if info for more than 4 is entered, I need to fill out the PDF twice and merge those two PDFs into one file to submit to the imaging system.
I've tried nesting streams, pdfReaders, pdfStampers, but the resulting PDF is always corrupt. Any help would be greatly appreciated. Thanks in advance.
Here's the code I have currently that handles stamping the PDF if there are 1 - 4 users entered:
var pdfTemplate = ConfigurationManager.AppSettings["PdfFileLocation"] + formName + ".pdf";
var pdfReader = new PdfReader(pdfTemplate);
using (var stream = new MemoryStream())
{
using (var pdfStamper = form == null
? new PdfStamper(pdfReader, stream, '\0', false)
: processType == 1 // printing form
? new PdfStamper(pdfReader, new FileStream(Path.GetTempPath() + "UserForm_" + UserNumber + ".pdf", FileMode.Create)) // temporarily save form
: new PdfStamper(pdfReader, stream, '\0', false)) // use a stream if submitting
{
var overContent1 = pdfStamper.GetOverContent(1);
var overContent2 = pdfStamper.GetOverContent(2);
var overContent3 = pdfStamper.GetOverContent(3);
var overContent4 = pdfStamper.GetOverContent(4);
var pdfFormFields = pdfStamper.AcroFields;
... Code to fill out other pages of the PDF goes here ...
#region User Form Page #3
foreach (var user in users)
{
var eligibility = _sharedFormService.GetEligibility(user.Eligibility);
pdfFormFields.SetField("User" + nameof(user.Name) + user.Id, user.Name);
pdfFormFields.SetField("User" + nameof(user.Eligibility) + user.Id, eligibility);
pdfFormFields.SetField("User" + nameof(user.Title) + user.Id, user.Title);
pdfFormFields.SetField("User" + nameof(user.Type) + user.Id, user.Type);
pdfFormFields.SetField("User" + nameof(user.FamilyMemberName) + user.Id, user.FamilyMemberName);
try
{
if (user.Signature != null)
{
var sigImage = _imageHelpers.LoadImage(user.Signature);
var image = Image.GetInstance(sigImage, System.Drawing.Imaging.ImageFormat.Gif);
var sigPostitions = pdfFormFields.GetFieldPositions("User" + nameof(user.Signature) + user.Id)[0].position;
image.Transparency = new int[] { 255, 255 };
image.SetAbsolutePosition(sigPostitions.Left, sigPostitions.Bottom);
image.ScalePercent(15);
overContent3.AddImage(image);
}
}
catch (DocumentException dex)
{
response.Success = false;
response.ErrorMessage += "StampPdf - UserSignature" + user.Id + ": " + (dex.InnerException != null
? dex.InnerException.Message
: dex.Message) + ", ";
}
catch (IOException ioex)
{
response.Success = false;
response.ErrorMessage += "StampPdf - UserSignature" + user.Id + ": " + (ioex.InnerException != null
? ioex.InnerException.Message
: ioex.Message) + ", ";
}
}
#endregion
pdfStamper.FormFlattening = true;
}
response.Stream = stream.ToArray();
}
After a few more days of Googling, I finally found the answer I was looking for from the iText FAQ Site, under "Merging identical forms (having identical fields)" (http://developers.itextpdf.com/question/how-merge-forms-different-files-one-pdf)
Here's the code I ended up using:
public static byte[] ManipulatePdf(string src, string dest)
{
var ms = new MemoryStream();
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, ms);
copy.SetMergeFields();
document.Open();
List<PdfReader> readers = new List<PdfReader>();
for (int i = 0; i < 2;)
{
PdfReader reader = new PdfReader(RenameFields(src, ++i));
readers.Add(reader);
copy.AddDocument(reader);
}
document.Close();
foreach (var reader in readers)
{
reader.Close();
}
return ms.ToArray();
}
public static byte[] RenameFields(String src, int i)
{
MemoryStream baos = new MemoryStream();
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, baos);
AcroFields form = stamper.AcroFields;
var keys = new HashSet<string>(form.Fields.Keys);
foreach (var key in keys)
{
form.RenameField(key, string.Format("{0}_{1}", key, i));
}
stamper.Close();
reader.Close();
return baos.ToArray();
}
I'm comparing two images; the source is in my solution (and saving it to memory stream) and other I am downloading using 'WebClient' converting it to bytes and then saving it in a stream, then comparing the streams.
They are exactly the same image. However my code produces different hash strings, so the 'If Equals' produces a false.
I'm thinking the downloading and saving of the image is altering the string.
The code:
public void CompareImages(string icon)
{
WebClient wc = new WebClient();
MemoryStream ms = new MemoryStream();
Image expectedImage = Image.FromFile(AppConfig.ToolsFilesFolderName + string.Format("\\" + icon +".png"));
expectedImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
String firstBitmap = Convert.ToBase64String(ms.ToArray());
ms.Position = 0;
MemoryStream ms2 = null;
byte[] bytes;
var baseEventType = _driver.FindElement(By.XPath("//div[#id='EventsView2_tv']/div/div")); ///div/div/div[19] //what i need to do is expand all of them and then
int count = 0;
var eventTypeExists = baseEventType.FindElements(By.TagName("tr"));
for (int i = 0; i < eventTypeExists.Count; i++)
{
if (i>30)
return;
if (eventTypeExists[i].Text.Trim().ToLower().Equals(icon.ToLower()))
{
var imgPath = eventTypeExists[i].FindElement(By.XPath("td[3]/img"));
var imageUrl = imgPath.GetAttribute("src");
bytes = wc.DownloadData(imageUrl);
ms2 = new MemoryStream(bytes);
Image actualImage = Image.FromStream(ms2);
actualImage.Save(ms2, System.Drawing.Imaging.ImageFormat.Png);
String secondBitmap = Convert.ToBase64String(ms2.ToArray());
if (firstBitmap.Equals(secondBitmap))
{
Reporter.ReportNote(string.Format("'{0}' icon in '{1}' is correct",
icon, ScenarioContext.Current["contractName"] + "/" + eventTypeExists[i].FindElement(By.XPath("../../../../table[" + (i - 2) + "]")).Text),
Status.Pass);
}
else
{
Reporter.ReportNote(string.Format("Icons are not correct, offending image is located within '{0}'",
ScenarioContext.Current["contractName"] + "/" + eventTypeExists[i].FindElement(By.XPath("../../../../table[" + (i - 2) +"]")).Text),
Status.Done);
}
ms2.Dispose();
}
count++;
}
ms.Dispose();
wc.Dispose();
}
I'm new to creating pdfs, and successfully had one working but no footer, so I've been looking around and based myself on this
This is the code I have of it:
string nome = "MapaAnual" + DateTime.Now.Year.ToString() + "_" + DateTime.Now.Month.ToString() + "" + DateTime.Now.Day.ToString() + ".pdf";
string outputFile = "C:\\Users\\sies4578\\Documents\\Visual Studio 2012\\Projects\\ULSM_Equipamentos\\REL\\" + nome.ToString();
try
{
//Create a standard .Net FileStream for the file, setting various flags
//FileStream fs = new FileStream(outputFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
System.IO.FileStream fs = new System.IO.FileStream(outputFile + DateTime.Now.ToString("ddMMyyHHmmss") + ".pdf", System.IO.FileMode.OpenOrCreate);
//Create a new PDF document setting the size to A4
Document doc = new Document(PageSize.A4.Rotate());
//Bind the PDF document to the FileStream using an iTextSharp PdfWriter
PdfWriter w = PdfWriter.GetInstance(doc, fs);
w.PageEvent = new MyPageEventHandler();
//Open the document for writing
doc.Open();
for (int i = 0; i < listaServicos.Count; i++)
{
doc.NewPage(); //where it goes to the catch giving that error
#region Calibracoes
//Code that doesn't matter
#endregion
}
doc.Close();
Process.Start(outputFile);
return "PDF criado com sucesso";
}
catch (Exception ex)
{
Console.WriteLine("An error ocurred, the PDF-document could not be created.");
return ex.Message;
}
I doubt it's related but as asked here is the code of MyPageEventHandler:
public class MyPageEventHandler : iTextSharp.text.pdf.PdfPageEventHelper
{
// This is the contentbyte object of the writer
PdfContentByte cb;
// we will put the final number of pages in a template
PdfTemplate template;
// this is the BaseFont we are going to use for the header / footer
BaseFont bf = null;
// This keeps track of the creation time
DateTime PrintTime = DateTime.Now;
protected iTextSharp.text.Font footer
{
get
{
// create a basecolor to use for the footer iTextSharp.text.Font, if needed.
BaseColor grey = new BaseColor(128, 128, 128);
iTextSharp.text.Font font = iTextSharp.text.FontFactory.GetFont("Arial", 9, iTextSharp.text.Font.NORMAL, grey);
return font;
}
}
public override void OnStartPage(PdfWriter writer, Document doc)
{
//Inicio Cabeçalho Logo
//Inicio Cabeçalho Logo
PdfPTable cabecalho = new PdfPTable(3);
cabecalho.DefaultCell.Border = 0;
cabecalho.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
cabecalho.TotalWidth = 700;
float[] width1 = { 150.0F, 550.0F, 550.0F };
cabecalho.SetWidths(width1);
cabecalho.LockedWidth = true;
iTextSharp.text.Image im = iTextSharp.text.Image.GetInstance("C:\\ULSMatosinhos\\Software\\ULS-Matosinhos\\Images\\logopro.png");
cabecalho.AddCell(im);
iTextSharp.text.Font cabeca = new iTextSharp.text.Font(iTextSharp.text.FontFactory.GetFont("arial", 14, iTextSharp.text.Font.BOLDITALIC, new BaseColor(23, 181, 150)));
PdfPCell linha = new PdfPCell(new Phrase("PLANO DE CALIBRAÇÕES - " + anoCalibracao.ToString(), cabeca));
linha.Border = 0;
linha.HorizontalAlignment = 1;
linha.VerticalAlignment = Element.ALIGN_MIDDLE;
cabecalho.AddCell(linha);
iTextSharp.text.Font cd = new iTextSharp.text.Font(iTextSharp.text.FontFactory.GetFont("arial", 8, iTextSharp.text.Font.NORMAL, BaseColor.BLACK));
PdfPCell codigoDoc = new PdfPCell(new Phrase(" 591_00_SIE_1191", cd));
codigoDoc.Border = 0;
codigoDoc.HorizontalAlignment = 1;
codigoDoc.VerticalAlignment = Element.ALIGN_MIDDLE;
cabecalho.AddCell(codigoDoc);
doc.Add(cabecalho);
}
public override void OnEndPage(PdfWriter writer, Document document)
{
base.OnEndPage(writer, document);
int pageN = writer.PageNumber;
String text = "Page " + pageN + " of ";
float len = bf.GetWidthPoint(text, 8);
iTextSharp.text.Rectangle pageSize = document.PageSize;
cb.SetRGBColorFill(100, 100, 100);
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
cb.ShowText(text);
cb.EndText();
cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
"Printed On " + PrintTime.ToString(),
pageSize.GetRight(40),
pageSize.GetBottom(30), 0);
cb.EndText();
}
public override void OnCloseDocument(PdfWriter writer, Document document)
{
base.OnCloseDocument(writer, document);
template.BeginText();
template.SetFontAndSize(bf, 8);
template.SetTextMatrix(0, 0);
template.ShowText("" + (writer.PageNumber - 1));
template.EndText();
}
}
I need to add text to the lower right corner of a pdf. I was able to successfully do this with an annotation but I couldn't flatten it so I attempted to add the text via a paragraph instead. Now none of my text is showing up. Could anyone point out where I'm going wrong with my code below? (Or maybe just tell me how to flatten an annotation... the commented out portion works fine I just need it flattened)
private MemoryStream AddPageNumbers(MemoryStream stream)
{
MemoryStream ms = new MemoryStream();
PdfStamper Stamper = null;
PdfReader Reader = new PdfReader(stream);
try
{
PdfCopyFields Copier = new PdfCopyFields(ms);
Copier.AddDocument(Reader);
Copier.Close();
PdfReader docReader = new PdfReader(ms.ToArray());
ms = new MemoryStream();
Stamper = new PdfStamper(docReader, ms);
for (int i = 1; i <= Reader.NumberOfPages; i++)
{
//iTextSharp.text.Rectangle newRectangle = new iTextSharp.text.Rectangle(315, 19, 560, 33);
//var pcb = new iTextSharp.text.pdf.PdfContentByte(Stamper.Writer);
//string PageNumber = "Confirmation of Completion Report " + i.ToString() + " of " + Reader.NumberOfPages.ToString();
//FontFactory.RegisterDirectories();
//Font fontNormalArial = new Font(FontFactory.GetFont("Arial", 8f, Font.NORMAL));
//Paragraph para = new Paragraph(PageNumber, fontNormalArial);
//var annot = iTextSharp.text.pdf.PdfAnnotation.CreateFreeText(Stamper.Writer, newRectangle, para.Content, pcb);
//annot.Flags = iTextSharp.text.pdf.PdfAnnotation.FLAGS_PRINT;
//annot.BorderStyle = new iTextSharp.text.pdf.PdfBorderDictionary(0, 0);
//Stamper.AddAnnotation(annot, i);
//Stamper.FreeTextFlattening = true;
//Stamper.FormFlattening = true;
PdfContentByte cb = new PdfContentByte(Stamper.Writer);
string PageNumber = "Confirmation of Completion Report " + i.ToString() + " of " + Reader.NumberOfPages.ToString();
FontFactory.RegisterDirectories();
Font fontNormalArial = new Font(FontFactory.GetFont("Arial", 10, Font.NORMAL));
Paragraph para = new Paragraph(PageNumber, fontNormalArial);
para.Alignment = Element.ALIGN_RIGHT;
ColumnText ct = new ColumnText(cb);
ct.AddText(para);
ct.SetSimpleColumn(315, 19, 560 , 38);
ct.SetIndent(316, false);
ct.Go();
}
}
catch (Exception ex)
{
string querystring = "?error=" + ex.Message.ToString();
Response.Redirect("~/ErrorPage.aspx" + querystring);
}
finally
{
if (Stamper != null)
{
Stamper.Close();
}
}
return ms;
}