Question
How can a PDF with text and images be generated
The following snippet generates a pdf with text but the image is distorted like this
Seems the required image should be a .jpg
. When I used a .png
, not even a distorted image was showing in the pdf.
public static void createPdf() {
try {
//Image image = Image.createImage("/icon.png");
Image image = Image.createImage("/Logo.jpg");
EncodedImage encodedImage = EncodedImage.createFromImage(image, true);
byte[] imageData = encodedImage.getImageData();
StringBuilder content = new StringBuilder();
content.append("%PDF-1.4\n");
content.append("1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n");
content.append("2 0 obj<</Type/Pages/Kids [3 0 R]/Count 1>>endobj\n");
content.append("3 0 obj<</Type/Page/Parent 2 0 R/Resources 4 0 R/MediaBox [0 0 520 800]/Contents 6 0 R>>endobj\n");
content.append("4 0 obj<</Font<</F1 5 0 R>>/XObject<</Im0 7 0 R>>>>endobj\n");
content.append("5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\n");
content.append("6 0 obj<</Length 219>>stream\n");
content.append("BT /F1 24 Tf 175 720 Td (Codename One)Tj ET\n");
content.append("BT /F1 20 Tf 100 700 Td (Using one codebase, build)Tj ET\n");
content.append("BT /F1 20 Tf 0 660 Td (Android apps)Tj ET\n");
content.append("BT /F1 20 Tf 0 640 Td (iOS apps)Tj ET\n");
content.append("BT /F1 20 Tf 0 600 Td (UWP apps)Tj ET\n");
content.append("512 0 0 512 4 50 cm\n");
content.append("/Im0 Do\n");
content.append("endstream\n");
content.append("endobj\n");
content.append("7 0 obj<</Type/XObject/Subtype/Image/Width 512/Height 512/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length 132959>>stream\n");
content.append(new String(imageData));
content.append("endstream\n");
content.append("endobj\n");
content.append("\n");
content.append("xref\n");
content.append("0 8\n");
content.append("0000000000 65535 f \n");
content.append("0000000009 00000 n \n");
content.append("0000000052 00000 n \n");
content.append("0000000102 00000 n \n");
content.append("0000000197 00000 n \n");
content.append("0000000255 00000 n \n");
content.append("0000000316 00000 n \n");
content.append("0000000609 00000 n \n");
content.append("trailer\n");
content.append("<</Size 8/Root 1 0 R>>\n");
content.append("startxref\n");
content.append("133724\n");
content.append("%%EOF\n");
FileSystemStorage fss = FileSystemStorage.getInstance();
String pdfPath = fss.getAppHomePath() + "Test2.pdf";
try (Writer w = new OutputStreamWriter(fss.openOutputStream(pdfPath))) {
w.write(content.toString());
} catch (Exception e) {
Log.p("Error " + e);
}
} catch (Exception e) {
Log.p("Error " + e);
}
}
The generated pdf is saved in app storage directory home/.cn1
How can the required raw image data be extracted from the image so that image can show without distortion?
Edit: This question is a bit different from this since I need the image binary data to be generated/created and inserted to the pdf programmatically not manually
EDIT
Writing pdf content directly without appending to a StringBuilder
results to this Test7.pdf. That is
private void createPdf7() {
try {
FileSystemStorage fss = FileSystemStorage.getInstance();
String pdfPath = fss.getAppHomePath() + "Test7.pdf";
try (Writer w = new OutputStreamWriter(fss.openOutputStream(pdfPath))) {
w.write("%PDF-1.4\n");
w.write("1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n");
w.write("2 0 obj<</Type/Pages/Kids [3 0 R]/Count 1>>endobj\n");
w.write("3 0 obj<</Type/Page/Parent 2 0 R/Resources 4 0 R/MediaBox [0 0 520 800]/Contents 6 0 R>>endobj\n");
w.write("4 0 obj<</Font<</F1 5 0 R>>/XObject<</Im0 7 0 R>>>>endobj\n");
w.write("5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\n");
w.write("6 0 obj<</Length 219>>stream\n");
w.write("BT /F1 24 Tf 175 720 Td (Codename One)Tj ET\n");
w.write("BT /F1 20 Tf 100 700 Td (Using one codebase, build)Tj ET\n");
w.write("BT /F1 20 Tf 0 660 Td (Android apps)Tj ET\n");
w.write("BT /F1 20 Tf 0 640 Td (iOS apps)Tj ET\n");
w.write("BT /F1 20 Tf 0 600 Td (UWP apps)Tj ET\n");
w.write("512 0 0 512 4 50 cm\n");
w.write("/Im0 Do\n");
w.write("endstream\n");
w.write("endobj\n");
w.write("7 0 obj<</Type/XObject/Subtype/Image/Width 50/Height 50/ColorSpace/DeviceRGB/BitsPerComponent 8/Length 132959>>stream\n");
InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/Logo.jpg");
//InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/icon.jpeg");
//InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/icon.png");
int nextChar = is.read();
if (nextChar == -1) {
//return null;
}
while (nextChar > -1) {
//Log.p("Char " + (char) nextChar);
char[] charArray = {(char) nextChar};
w.write(charArray);
nextChar = is.read();
}
w.write("\nendstream\n");
w.write("endobj\n");
w.write("\n");
w.write("xref\n");
w.write("0 8\n");
w.write("0000000000 65535 f \n");
w.write("0000000009 00000 n \n");
w.write("0000000052 00000 n \n");
w.write("0000000102 00000 n \n");
w.write("0000000197 00000 n \n");
w.write("0000000255 00000 n \n");
w.write("0000000316 00000 n \n");
w.write("0000000609 00000 n \n");
w.write("trailer\n");
w.write("<</Size 8/Root 1 0 R>>\n");
w.write("startxref\n");
w.write("133724\n");
w.write("%%EOF\n");
} catch (Exception e) {
Log.p("Error " + e);
}
} catch (Exception e) {
Log.p("Error " + e);
}
}
What I am still missing for the image to show correctly?
EDIT
Opening this JSjpegSample-with image.pdf with Linux Text Editor shows the following image data stream encoding. Note some readable text like JFIF
Photoshop 7.0
In Codename One simulator, this encoding is close to how SQLite database file is encoded. SQLite database open with Linux Text Editor shows the following. Note some readable text like SQLite format 3
CREATE TABLE
How can a .jpeg
to be added to a pdf be encoded same way as SQLite database file?