iText image alignment on second page - android

I am creating a PDF document with images and text in Android using iText. Each page has an image at the top followed by some text. On the first page the image is correctly aligned to the top margin of the page, but on subsequent pages there is a gap of approximately 10 points between the top margin and the top of the image.
Here's my code:
// Create PDF document object
float pageMargin = 72;
document = new com.itextpdf.text.Document(PageSize.A4, pageMargin, pageMargin, pageMargin, pageMargin);
PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(myFile.getAbsoluteFile()));
document.open();
PdfContentByte cb = pdfWriter.getDirectContent();
for (PicturePage picPage : picPageList)
{
// Draw a border on the page
cb.moveTo(pageMargin, pageMargin);
cb.lineTo(pageMargin, (pageHeight - pageMargin));
cb.lineTo((pageWidth - pageMargin), (pageHeight - pageMargin));
cb.lineTo((pageWidth - pageMargin), pageMargin);
cb.lineTo(pageMargin, pageMargin);
cb.stroke();
// Get an image from the file system and scale to required size
String imgFileName = picPage.getImagePath();
image = Image.getInstance(imgFileName);
float fitWidth = 400;
float fitHeight = 300;
image.scaleToFit(fitWidth, fitHeight);
image.setAlignment(Image.ALIGN_CENTER | Image.ALIGN_TOP);
document.add(image);
// Add the text to the page.
String theText = picPage.getText();
String[] arrParagraphs = theText.split("\n");
for (int i=0; i<arrParagraphs.length; i++)
{
String paragraphText = arrParagraphs[i];
Paragraph p = new Paragraph(paragraphText);
document.add(p);
}
// Start a new page
document.newPage();
}
I have tried various combinations of Image.ALIGN... and Image.TEXTWRAP but none of them remove the gap. I tried changing the order of placing the image and the border but no change. I have also tried removing the text and the border but the placement of the image is still the same.
Any ideas how to fix this?
Thanks,
Declan

I hope you won't mind if I share my opinion, but I don't like your code. There are much better ways to render images followed by a caption than the way you do it.
Now let me explain what causes the small gap to appear.
When you first create your document, the value of the leading is zero. (The leading is the distance between the baselines of two consecutive lines). This value changes as soon as you add the first object that defines a leading. In your case, this object is a Paragraph.
Although you do not define a leading explicitly, your paragraph uses a default font (Helvetica) and a default font size (12). The default leading is 1.5 times the font size (18).
Now when you go to the next page, that leading is used, introducing a small gap preceding the image. You could solve this by adding an empty Paragraph with leading 0 before triggering a new page:
document.add(new Paragraph(0));
(Add this before document.newPage();.)
However: if I were you, I'd throw away my code, and I'd add my image and my caption using a PdfPTable with a fixed width and fixed heights for the cells. You can add this table either using document.add(), or using the writeSelectedRows() method. Alternatively I could add the image at an absolute position and add the caption using a ColumnText object. There are many different ways to achieve what you want. The way you do it may work, but it's not optimal.

Related

PDF checkboxes with iTextsharp

I've an Android app that needs to generate a PDF document with various data fetched from a database. Everything is working fine, included tables and checkboxes, that I generate with this snipped of code :
private PdfFormField WriteCheckbox(ref PdfContentByte pcb, float xPos, float yPos, string fldName, bool cbState)
{
yPos = yPos - 2f;
float cbDist = 1f;
Rectangle cbRect = new Rectangle(xPos, yPos, xPos + DEFAULT_CHECKBOX_SIZE, yPos + DEFAULT_CHECKBOX_SIZE);
RadioCheckField checkbox = new RadioCheckField(pcb.PdfWriter, cbRect, "", "");
checkbox.CheckType = RadioCheckField.TYPE_SQUARE;
checkbox.BorderColor = BaseColor.BLACK;
checkbox.BorderStyle = PdfBorderDictionary.STYLE_SOLID;
checkbox.BorderWidth = 0.5f;
checkbox.FieldName = fldName;
if(cbState)
{
pcb.SetLineWidth(1.2f);
pcb.MoveTo(xPos + DEFAULT_CHECKBOX_DISTANCE, yPos + cbDist);
pcb.LineTo(xPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1, yPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1);
pcb.MoveTo(xPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1, yPos + cbDist);
pcb.LineTo(xPos + DEFAULT_CHECKBOX_DISTANCE, yPos + DEFAULT_CHECKBOX_SIZE - cbDist - 1);
}
pcb.Stroke();
return(checkbox.RadioField);
}
The resulting PDF is visualize correctly on the tablet (Nexus 7), but when I copy it con my PC and open if with Acrobat Reader all is at the correct place except the squares I draw to show the checkboxes. I can se the cross I draw inside the squares, but not the surrounding square. What is happening ?
This is the link to the pdf generated :
https://www.dropbox.com/s/p388bw7egjsbi80/curit_2015_2.pdf?dl=0
This is the link to the Nexus 7 screenshot showing the very same file :
Any hint would be very appreciated.
the squares I draw to show the checkboxes
Your code doesn't draw any squares.
What your code does, actually is surprising,
it creates numerous checkbox AcroForm form fields, none of them checked, none of them named, with a square visualization selection, and
it draws a cross in the page content in positions you seem to want to have appear checked.
So even if the created PDF was valid, it could irritate people, as they apparently could not de-select the pre-selected entries, merely select them a second time resulting in two overlapping crosses.
The reason why your checkbox borders only appear on some PDF viewers and not on others, is the same as explained in this answer to the question "iText - Java Android - Adding fields to existing pdf":
AcroForm form fields need to have a non-empty name. AcroForm forms contents are meant to be sent to some service for automatic evaluation, so they must be named and they must be distinguishable by their respective names.
Some PDF viewers recognize early that they couldn't properly handle fields with empty names and, therefore, don't even show them while other viewers recognize that later when trying to save or post the form, or don't recognize it at all, producing broken outputs.
But even after naming the boxes individually, you should decide whether you want to have AcroForm form fields or not. In the former case you would merely add properly named form fields and set them selected or not, and in the latter case you would draw complete checkbox appearances (not merely the check marks) in the page content and not use form fields at all.

Corona - how to align arrows with text?

I'm using the Corona sdk to create a simple Android game. I have it almost completely done, just trying to polish now. This is something that I'm having trouble with:
This is my game's setup page. Players are able to tap the up/down arrows to increase/decrease game attributes. I want the arrows to align with the numbers. My current code does not account for this:
local numPlayerstxt = display.newText("Number of players: "..NUMPLAYERS, w/2,7*h/20,0,0,"Quattrocento-Regular",24)
numPlayerstxt:setFillColor(0,0,0)
sceneGroup:insert(numPlayerstxt)
local numMafiatxt = display.newText("Number of Mafia: "..MAFIA, w/2,12*h/20,0,0,"Quattrocento-Regular",24)
numMafiatxt:setFillColor(0,0,0)
sceneGroup:insert(numMafiatxt)
local upTotal = display.newImage( "arrow1.png")
upTotal:translate(33*w/40, 6*h/20)
upTotal:scale(0.08, 0.08)
sceneGroup:insert(upTotal)
upTotal:addEventListener("tap", increasePlayers)
local downTotal = display.newImage( "arrow1.png")
downTotal:translate(33*w/40, 8*h/20)
downTotal:scale(0.08, 0.08)
downTotal.rotation = 180
sceneGroup:insert(downTotal)
downTotal:addEventListener("tap", decreasePlayers)
local upMafia = display.newImage( "arrow1.png")
upMafia:translate(32*w/40, 11*h/20)
upMafia:scale(0.08, 0.08)
sceneGroup:insert(upMafia)
upMafia:addEventListener("tap", increaseMafia)
local downMafia = display.newImage( "arrow1.png")
downMafia:translate(32*w/40, 13*h/20)
downMafia:scale(0.08, 0.08)
downMafia.rotation = 180
sceneGroup:insert(downMafia)
downMafia:addEventListener("tap", decreaseMafia)
As you can see, my code currently only takes into account screen width and height values in order to reasonably estimate the approximate locations. Inevitably this code fails to create any illusion of polish when the app is tried on different device screens.
Any suggestions on what I might do to align the arrows with the numbers? For instance, is there a way in Corona to find the end point of a textview, and align it in that way?
Thanks for reading.
try changing the anchorX of each arrows like this:
-- suppose one of your arrows is upArrow
upArrow.anchorX = 0.4 -- even try each float between 0 - 1
this move your object's anchor in x axis of the object.

Add paragraph dynamically at the bottom with iText library in android

I am using below code but this is not working its show only one line in bottom while I want a paragraph in bottom in every page.
public void onEndPage(PdfWriter writer, Document document) {
Rectangle rect = writer.getBoxSize("art");
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, new Phrase(ActivityWaTestamentInput.pDFHeaderText,headerFont),
rect.getLeft(), rect.getTop(), 0);
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, new Paragraph(ActivityWaTestamentInput.pDFFooterText,footerFont),
rect.getLeft() , rect.getBottom() - 18, 0);
As documented, ColumnText.showTextAligned() will only show one line. If you need multiple lines, then you can also use ColumnText, but you need to use it in a different way.
Please download the free ebook The Best iText Questions on StackOverflow. In the section "Absolute positioning of text", you'll find several examples that involve ColumnText.
These are some questions and answers you should check:
How to fit a String inside a rectangle?
How to draw a rectangle around multiline text
iText placement of Phrase within ColumnText
This is a code snippet from one of the answers to these questions:
ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(120f, 500f, 250f, 780f);
Paragraph p = new Paragraph("This is a long paragraph that doesn't"
+ "fit the width we defined for the simple column of the"
+ "ColumnText object, so it will be distributed over several"
+ "lines (and we don't know in advance how many).");
ct.addElement(p);
ct.go();
I hardcoded the position:
llx = 120;
lly = 500;
urx = 250;
ury = 780;
This is a rectangle with lower left corner (120, 500), a width of 130 and a height of 380. You will need to adapt these values if you want the text to appear at the bottom of the page.

how to merge Images and impose on each other

Suppose I'm uploading two or more than two pics in some Framelayout. Hereby I'm uploading three pics with a same person in three different position in all those three pictures. Then what image processing libraries in Android or java or Native's are available to do something as shown in the pic.
I would like to impose multiple pictures on each other.
Something like these:-
One idea is to :
Do some layering in all those pictures and find mismatching areas in the pics and merge them.
How one can merge multiple picture with other? By checking the di-similarity and merge with each other?
Are there any Third party Api's or some Photoshop service which can help me in doing these kinda image processing?
In this case you are not just trying to combine the images. You really want to combine a scene containing the same object in different positions.
Therefore, it is not just a simple combination or an alpha compositve where the color of a given pixel in the output image is the sum of the value of this pixel in each image, divided by the number of images.
In this case, you might do:
Determine the scene background analysing the pixels that do not change considering multiple images.
Begin with the output image being just the background.
For each image, remove the background to get the desired object and combine it with the output image.
There is a Marvin plug-in to perform this task, called MergePhoto. The program below use that plug-in to combine a set of parkour photos.
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
import marvin.plugin.MarvinImagePlugin;
import marvin.util.MarvinPluginLoader;
public class MergePhotosApp {
public MergePhotosApp(){
// 1. load images 01.jpg, 02.jpg, ..., 05.jpg into a List
List<MarvinImage> images = new ArrayList<MarvinImage>();
for(int i=1; i<=5; i++){
images.add(MarvinImageIO.loadImage("./res/0"+i+".jpg"));
}
// 2. Load plug-in and process the image
MarvinImagePlugin merge = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.combine.mergePhotos");
merge.setAttribute("threshold", 38);
// 3. Process the image list and save the output
MarvinImage output = images.get(0).clone();
merge.process(images, output);
MarvinImageIO.saveImage(output, "./res/merge_output.jpg");
}
public static void main(String[] args) {
new MergePhotosApp();
}
}
The input images and the output image are shown below.
I don't know if this will qualify to be in your definition of "natives", but there is the following .NET library that could help: http://dynamicimage.apphb.com/
If the library itself can give you want you want, then depending on your architecture you could set up a small ASP.NET site to do the image manipulation on the server.
Check the accepted answer here.
In above link there is merging of two images which is done by openCV sdk.
If you dont want to use openCV and just want to try with your self then you will have to play little with framlayout and with three imageview. Give options to user to select specific part of the image to show for all three images. So the selected part will be shown of the selected image. on this way you will get the result like above what you have said.
Hope you got my point. If not then let me know.
Enjoy coding... :)
You can overlay the images using openCV you can check at OpenCV and here or here
// Read the main background image
cv::Mat image= cv::imread("Background.png");
// Read the mans character image to be placed
cv::Mat character= cv::imread("character.png");
// define where you want to place the image
cv::Mat newImage;
//The 10,10 are the initial coordinates in pixels
newImage= image(cv::Rect(10,10,character.cols,character.rows));
// add it to the background, The 1 is the aplha values
cv::addWeighted(newImage,1,character,1,0,newImage);
// show result
cv::namedWindow("with character");
cv::imshow("with character",image);
//Write Image
cv::imwrite("output.png", newImage);
or you can create it as a watermark effect
Or you can try it in java like merging two images
try using this class
public class MergeImages {
public static void main(String[] args) {
File inner = new File("Inner.png");
File outter = new File("Outter.png");
try {
BufferedImage biInner = ImageIO.read(inner);
BufferedImage biOutter = ImageIO.read(outter);
System.out.println(biInner);
System.out.println(biOutter);
Graphics2D g = biOutter.createGraphics();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
int x = (biOutter.getWidth() - biInner.getWidth()) / 2;
int y = (biOutter.getHeight() - biInner.getHeight()) / 2;
System.out.println(x + "x" + y);
g.drawImage(biInner, x, y, null);
g.dispose();
ImageIO.write(biOutter, "PNG", new File("Outter.png"));
} catch (Exception e) {
e.printStackTrace();
}
}
}

GPL-compatible graphing library for Android

In a similar approach to this question, I am looking for a way to plot data points on to a view in Android. Preferably, a library which will do this for arbitrary-ranged input, as well as allow panning and zooming (via pinch or zoom bar).
Right now, I have subclass-ed a view which does the following normalization:
final int width = View.MeasureSpec.getSize(this.widthMeasureSpec);
final int height = View.MeasureSpec.getSize(this.heightMeasureSpec);
final float factorA = width / (maxA - minA);
final float factorS = height / (maxS - minS);
final float constFactorA = factorA * minA;
final float constFactorS = factorS * minS;
final int dataLength = data.length;
for (int i = 0; i < dataLength; ++i) {
if (i % 2 == 0)
_data[i] = _data[i] * factorA - constFactorA;
else
_data[i] = _data[i] * factorS - constFactorS;
}
and a call in onDraw() to the drawPoints method of a canvas (also, I update this.widthMeasureSpec and this.heightMeasureSpec in onMeasure()).
This is with minA/maxA as the bounds for my independent variable and minS/maxS as the bounds for my dependent variable.
This works fine for displaying the data, but I am hoping someone else has solved the problem of drawing the axes and panning/zooming.
I have ~150,000 data points, and I would prefer to keep these as floats to save half the memory. I don't know how big decimal numbers are in JavaScript, but I really don't want to resort to passing data in through JavaScript for the Google Charts API or an HTML-based solution for memory's sake.
I'm running this on a MyTouch 3g (the original, before 3.5mm jack and it's RAM upgrade), so performance is an issue. I'd like to release the final project under the GPLv3, so this excludes GraphView.
The graphs are of the same type as this, so any optimization by excluding points that are too close together to show up on screen would definitely make a difference.
sargas , do check android-misc-widgets.It contains a widget named PlotView with an example TestInterPolator.
Hope it helps.
Original post: Chart and Graph Library for Android
With the library GraphView it's possible to create a line and bar graphs.
GraphView is a library for Android to programmatically create flexible and nice-looking line and bar diagramms. It is easy to understand, to integrate and to customize it.
First checkout the library and integrate it into your project.
Source code is hosted on github.
GraphView library on github
It's also possible to let the graph be scalable (zooming) and scrollable. More information about this library on Original post: Chart and Graph Library for Android
This is how it will look like:
Then you can easily create it with a few lines of code (see snippet):
// graph with dynamically genereated horizontal and vertical labels
GraphView graphView = new LineGraphView(
this // context
, new GraphViewData[] {
new GraphViewData(1, 2.0d)
, new GraphViewData(2, 1.5d)
, new GraphViewData(2.5, 3.0d) // another frequency
, new GraphViewData(3, 2.5d)
, new GraphViewData(4, 1.0d)
, new GraphViewData(5, 3.0d)
} // data
, "GraphViewDemo" // heading
, null // dynamic labels
, null // dynamic labels
);
LinearLayout layout = (LinearLayout) findViewById(R.id.graph1);
layout.addView(graphView);
There is http://www.jfree.org/jfreechart/ which can suit your needs, it is a Java library so it should fit nice to Android. And it is LGPL.
If you can go the JavaScript route, then you could check out ProtoVis http://vis.stanford.edu/protovis/

Categories

Resources