How to get the total page number in iText7 when adding that info to the document footer? - footer

In iTextSharp, we can override the OnCloseDocument() event and add the Page # of #total on the footer of the document. However, the PdfDocument does not have this document close event anymore. Since we cannot determine the total number of pages while adding new pages, how can we determine this total number and put it on the footer while generating the document?
I've seen some suggestions with brute force method: after the PDF document is generated and before it's flushed, use PdfReader to read through it to get the total number before updating the footer. Is this the only way? Is there any better way of doing this?
Thanks.

That is one of the ways of doing it.
Another way of doing that is described in this code sample:
protected void manipulatePdf(String dest) throws Exception {
PdfDocument pdfDoc = new PdfDocument(new PdfReader(SRC), new PdfWriter(dest));
Document doc = new Document(pdfDoc);
int numberOfPages = pdfDoc.getNumberOfPages();
for (int i = 1; i <= numberOfPages; i++) {
// Write aligned text to the specified by parameters point
doc.showTextAligned(new Paragraph(String.format("page %s of %s", i, numberOfPages)),
559, 806, i, TextAlignment.RIGHT, VerticalAlignment.TOP, 0);
}
doc.close();
}
In that code sample you would add the footer after creating and flushing the PDF. This is a very simple and easy way of doing this request.

Another way of doing that is with IEventHandler.
PdfWriter writer = new PdfWriter(myMemoryStream);
pdf.AddEventHandler(PdfDocumentEvent.END_PAGE, new TextFooterEventHandler(document));
then :
public class TextFooterEventHandler : IEventHandler
{
protected Document doc;
public TextFooterEventHandler(Document doc)
{
this.doc = doc;
}
public void HandleEvent(Event currentEvent)
{
var docEvent = (PdfDocumentEvent)currentEvent;
var pageSize = docEvent.GetPage().GetPageSize();
var fonts = new FontHelper();
var font = fonts.Label();
int pageNum = docEvent.GetDocument().GetPageNumber(docEvent.GetPage());
float coordX = ((pageSize.GetLeft() + doc.GetLeftMargin())
+ (pageSize.GetRight() - doc.GetRightMargin())) / 2;
float footerY = doc.GetBottomMargin();
Canvas canvas = new Canvas(docEvent.GetPage(), pageSize);
canvas
.SetFont(font)
.SetFontSize(8)
.ShowTextAligned((("Page " + pageNum.ToString())), coordX + 250, footerY - 40, TextAlignment.CENTER)
.SetLineThrough()
.Close();
}
}

Related

iText - is it possible to parse text within a given width and height specific area?

I'm using iText version 5 and would like to know if this is possible for documents and if so how would I do it? Thanks.
You can find an example for that task on the iText web site: ExtractPageContentArea.
The pivotal code:
PdfReader reader = new PdfReader(pdf);
PrintWriter out = new PrintWriter(new FileOutputStream(txt));
Rectangle rect = new Rectangle(70, 80, 490, 580);
RenderFilter filter = new RegionTextRenderFilter(rect);
TextExtractionStrategy strategy;
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
strategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), filter);
out.println(PdfTextExtractor.getTextFromPage(reader, i, strategy));
}
out.flush();
out.close();
reader.close();
This example stores the text from the (hard coded) rectangle in a file but you can obviously also handle it differently.

How to print bitmap without zoom from MVC controller in Debian

Document is printed from MVC controller to Debian Squeeze Linux server printer using code below in Mono.
Page in printer is A4.
Printed text in paper is too big and unsharp. Rightmost part of text is not visible since it does not fit to page.
If printed from Windows from .NET to HP Laserjet, output is correct.
So it looks like Mono or Samsung ML-331x Series printer zooms bitmap for unknown reason which causes too big and unsharp output.
How to fix this so that bitmap is printed like in windows ?
Possible solutions:
Best way would be to print formatted html directly. How to do it in server where there are no browser installed? wkhtmltopdf does not support printing. I posted it in How to print formatted html in Linux server
Maybe it is possible to use wkhtmltopdf convert html to pdf instead of bitmap I posted it as separate question in How to print pdf in debian linux from MVC controller
wkhtmltoimage can produce also other image formats. Maybe some other format is better ?
Maybe some wkhtmltoimage command line swithches like --width=750 or --dpi can fix this ?
public class Test: Controller
{
public ActionResult Print()
{
PrintOrderVormiga();
return new ContentResult() { Content = "OK" };
}
void PrintOrderVormiga()
{
StringBuilder sb = new StringBuilder();
sb.Insert(0, " test ", 500);
var bmp = ConvertHtmlToBMP("<html><body>" +sb.Tostring()+ "</body></html>");
var doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "Samsung ML-331x Series";
doc.PrintPage += new PrintPageEventHandler(ProvideContent);
pageHeight = doc.DefaultPageSettings.PaperSize.Height;
using (bm = new Bitmap(new MemoryStream(bmp)))
{
lehti = (int)Math.Ceiling(bm.Height / (double)pageHeight);
doc.PrinterSettings.FromPage = 1;
doc.PrinterSettings.ToPage = lehti;
pageno = 0;
doc.Print();
}
}
int pageno, lehti;
int pageHeight;
Bitmap bm;
void ProvideContent(object sender, PrintPageEventArgs e)
{
Rectangle cropRect = new Rectangle(0, pageHeight * pageno++,
bm.Width, pageHeight);
Bitmap target = new Bitmap(cropRect.Width, cropRect.Height);
e.Graphics.DrawImage(bm, new Rectangle(0, 0, target.Width, target.Height),
cropRect,
GraphicsUnit.Pixel);
e.HasMorePages = pageno < lehti;
}
static byte[] ConvertHtmlToBMP(string html)
{
string programm = "wkhtmltoimage";
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
programm = "wkhtmltoimage-amd64";
}
var p = new Process
{
StartInfo =
{
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true,
UseShellExecute = false,
FileName = Environment.OSVersion.Platform == PlatformID.Win32NT ?
"C:\\Program Files\\wkhtmltopdf\\bin\\" + programm + ".exe" : "/usr/bin/" + programm
}
};
p.StartInfo.Arguments = "--format bmp --disable-javascript --quality 10";
p.StartInfo.Arguments += " - -";
p.Start();
using (var stream = p.StandardInput)
{
byte[] ibuffer = System.Text.Encoding.UTF8.GetBytes(html);
stream.BaseStream.Write(ibuffer, 0, ibuffer.Length);
stream.WriteLine();
}
var buffer = new byte[32768];
byte[] file;
using (var ms = new MemoryStream())
{
while (true)
{
var read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if (read <= 0)
{
break;
}
ms.Write(buffer, 0, read);
}
file = ms.ToArray();
}
p.WaitForExit(60000);
var returnCode = p.ExitCode;
p.Close();
return file;
}
}
You can use this HTML to PDF Converter for Mono solution from EvoPdf. The C# code for converting a HTML to PDF in Mono is:
// create the HTML to PDF converter object
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter(serverIPAddress, serverPortNumber);
// set service password if necessary
if (serverPassword.Length > 0)
htmlToPdfConverter.ServicePassword = serverPassword;
// set PDF page size
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
// set PDF page orientation
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
// convert the HTML page from given URL to PDF in a buffer
byte[] pdfBytes = htmlToPdfConverter.ConvertUrl(urlToConvert);

Android Attach Image between text with SpannableStringBuilder

Sory for my english. I want attach image from gallery and show in edit text with SpannableStringBuilder. I have success for get Image Path from Gallery. After picture selected, Picture Show. But, for the second attach image picture not show and first image attach became a text. any one give me solution ? big thanks.
this is my code:
private void IntentPict() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select File"),MY_INTENT_CLICK);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK){
if (requestCode == MY_INTENT_CLICK){
if (null == data) return;
String selectedImagePath;
Uri selectedImageUri = data.getData();
//there is no problem with get path
selectedImagePath = ImageFilePath.getPath(getApplicationContext(), selectedImageUri);
//pathImag is ListArray<String>
pathImg.add(selectedImagePath);
addImageBetweentext(pathImg);
}
}
}
private void addImageBetweentext(ArrayList<String> listPath) {
SpannableStringBuilder ssb = new SpannableStringBuilder();
for(int i=0;i<listPath.size();i++){
String path = listPath.get(i);
Drawable drawable = Drawable.createFromPath(path);
drawable.setBounds(0, 0, 400, 400);
ssb.append(mBodyText+"\n");
ssb.setSpan(new ImageSpan(drawable), ssb.length()-(path.length()+1),
ssb.length()-1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
mBodyText.setText(ssb);
}
Here's something that should work. I am loading resource drawables instead, just because it was quicker for me to validate, but I tried to keep as mich as possible for your original flow and variable names:
Drawable[] drawables = new Drawable[2];
drawables[0] = getResources().getDrawable(R.drawable.img1);
drawables[1] = getResources().getDrawable(R.drawable.img2);
SpannableStringBuilder ssb = new SpannableStringBuilder();
for (int i = 0; i < drawables.length; i++) {
Drawable drawable = drawables[i];
drawable.setBounds(0, 0, 400, 400);
String newStr = drawable.toString() + "\n";
ssb.append(newStr);
ssb.setSpan(
new ImageSpan(drawable),
ssb.length() - newStr.length(),
ssb.length() - "\n".length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
mBodyText.setText(ssb);
Long story short: the start position for the incremental builder needs to be set to the current length of it, minus what you just added.

iTextsharp: Add image and text in a loop (IE, Firefox, Chrome)

I have a form with a button that generates a pdf file. The file loops through an array of images and text and insert each image and text on an absolute position of the document. I can add the image, without the text and it works well. I can also add the text without the image and all work well. However, When I add both at the same time, I get the error that
there was an error processing the document.
Here is the code
[HttpPost]
public FileStreamResult ff(MyModel model)
{
MemoryStream workStream = new MemoryStream();
Document doc = new Document();
doc.SetMargins(50, 25, 25, 30);
PdfWriter.GetInstance(doc, workStream).CloseStream = false;
PdfWriter writer = PdfWriter.GetInstance(doc, workStream);
writer.CloseStream = false;
doc.Open();
PdfContentByte cb = writer.DirectContent;
string path = "";
Image Img;
int num = 0;
float imageSize = 160f, margin = 5f, position = 600;
ColumnText ct;
foreach (var item in model)
{
/*ct = new ColumnText(cb);
myText = new Phrase(new Chunk(numbering[num] + " " + item.Caption, FontFactory.GetFont(FontFactory.TIMES, 9, Font.ITALIC)));
ct.SetSimpleColumn(myText, doc.LeftMargin + margin, position + 5f, imageSize, 2, 15, Element.ALIGN_LEFT);
ct.Go();
x += 10;
y += 12;*/
/////The code above and the code below(withing the loop) do not work when they are together but work well when they are not together
path = item.path;
Img = Image.GetInstance(path);
Img.ScaleToFit(imageSize, imageSize);
Img.SetAbsolutePosition(doc.LeftMargin + margin, position);
Img.Border = Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.BOTTOM_BORDER | Rectangle.LEFT_BORDER;
Img.BorderWidth = 1f;
doc.Add(Img);
num++;
position -= imageSize;
}
document.Close();
byte[] byteInfo = workStream.ToArray();
workStream.Write(byteInfo, 0, byteInfo.Length);
workStream.Position = 0;
return new FileStreamResult(workStream, "application/pdf");
}
Internet explorer and firefox display an error There was an error processing the page. There was an error reading this document(18).
Chrome does display the page, but the arrangement of the pictures is wrong. The second picture appears first and the last picture fails to show up, but is border is displayed as the last image(like an empty canvas)
what am I doing wrong please?
Does it help if you set the filename of the result?
var result = new FileStreamResult(workStream, "application/pdf");
result.FileDownloadName = "test.pdf";
return result;

POST image from webcam in Silverlight window to MVC Controller

I have an MVC 4 application with a button for taking a photo that opens up a new window with javascript which contains a silverlight application in it. The silverlight application can then take a photo using the webcam and store it as a Writeable Bitmap. What I would like to do is then push that bitmap onto an action in my controller for saving to the database and refreshing the view.
I know I need to send the image as a post to my controller, but any code examples or suggestions on how I would go about doing that would be greatly appreciated. I think it should work as follows, Button Click for saving the image in my silverlight application would call a POST to the MVC controller and attach the image stream as a parameter in the controller, and the controller can then take the stream and push it up to the database then I can close the silverlight window. Just not sure how to go about coding that.
You could send the image using a WebClient. Let's suppose that you have the image inside your Silverlight application in a byte array:
byte[] image = ... get the image from your webcam
var client = new WebClient();
var uri = new Uri("http://example.com/photos/upload");
client.OpenWriteCompleted += (sender, e) =>
{
var buffer = (byte[])e.UserState;
e.Result.Write(buffer, 0, buffer.Length);
e.Result.Close();
};
client.OpenWriteAsync(uri, "POST", image);
and on the MVC side:
[HttpPost]
public ActionResult Upload()
{
byte[] image = new byte[Request.InputStream.Length];
Request.InputStream.Read(image, 0, image.Length);
// TODO: do something with the uploaded image here ...
}
Thank you for the reply. This is exactly what I was looking for, however ive run into a problem. Silverlight gives me the webcam snapshot as a WriteableBitmap type. Which I then tried to convert to a byte[] array before sending it over to MVC. It is saving to the database successfully, however it does not appear to be a valid image when I try to pull it back out from the database and display it. Is there an issue that you can see with my conversion code? Or perhaps can I send it over as an image type, or can I only send over byte[] arrays through http posts like this?
In my Silverlight application:
private void SendImage()
{
var client = new WebClient();
var uri = new Uri("http://localhost:4600/GuestBadge/GetCameraImage");
client.OpenWriteCompleted += (sender, e) =>
{
var buffer = (byte[])e.UserState;
e.Result.Write(buffer, 0, buffer.Length);
e.Result.Close();
};
client.OpenWriteAsync(uri, "POST", ToByteArray(SnapShot));
}
public static byte[] ToByteArray(WriteableBitmap bmp)
{
// Init buffer
int w = bmp.PixelWidth;
int h = bmp.PixelHeight;
int[] p = bmp.Pixels;
int len = p.Length;
byte[] result = new byte[4 * w * h];
// Copy pixels to buffer
for (int i = 0, j = 0; i < len; i++, j += 4)
{
int color = p[i];
result[j + 0] = (byte)(color >> 24); // A
result[j + 1] = (byte)(color >> 16); // R
result[j + 2] = (byte)(color >> 8); // G
result[j + 3] = (byte)(color); // B
}
return result;
}
And in my controller:
[HttpPost]
public ActionResult GetCameraImage()
{
byte[] image = new byte[Request.InputStream.Length];
Request.InputStream.Read(image, 0, image.Length);
var getPerson = (from a in db.Persons where a.PersonID == 3 select a).FirstOrDefault();
getPerson.Picture = image;
db.SaveChanges();
return null;
}
I ended up using FJCore http://code.google.com/p/fjcore/ to encode my WriteableBitmap into JPEG and then converted that to BASE64 using code I found at this question Using FJCore to encode Silverlight WriteableBitmap THANKS!. Then in turn converted that out to a byte[] array and sent it to MVC using your code and now its working great. I'm pretty new at all this stuff and didn't quite understand the encoding process enough before. Below is the code I used for this. Thanks again for your help!
private static string GetBase64Jpg(WriteableBitmap bitmap)
{
int width = bitmap.PixelWidth;
int height = bitmap.PixelHeight;
int bands = 3;
byte[][,] raster = new byte[bands][,];
for (int i = 0; i < bands; i++)
{
raster[i] = new byte[width, height];
}
for (int row = 0; row < height; row++)
{
for (int column = 0; column < width; column++)
{
int pixel = bitmap.Pixels[width * row + column];
raster[0][column, row] = (byte)(pixel >> 16);
raster[1][column, row] = (byte)(pixel >> 8);
raster[2][column, row] = (byte)pixel;
}
}
ColorModel model = new ColorModel { colorspace = ColorSpace.RGB };
FluxJpeg.Core.Image img = new FluxJpeg.Core.Image(model, raster);
MemoryStream stream = new MemoryStream();
JpegEncoder encoder = new JpegEncoder(img, 90, stream);
encoder.Encode();
stream.Seek(0, SeekOrigin.Begin);
byte[] binaryData = new Byte[stream.Length];
long bytesRead = stream.Read(binaryData, 0, (int)stream.Length);
string base64String =
System.Convert.ToBase64String(binaryData,
0,
binaryData.Length);
return base64String;
}
private void SendImage()
{
var client = new WebClient();
var uri = new Uri("http://localhost:4600/GuestBadge/GetCameraImage");
client.OpenWriteCompleted += (sender, e) =>
{
var buffer = (byte[])e.UserState;
e.Result.Write(buffer, 0, buffer.Length);
e.Result.Close();
};
client.OpenWriteAsync(uri, "POST", Convert.FromBase64String(GetBase64Jpg(SnapShot)));
}

Resources