Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 72 additions & 9 deletions openpdf-core/src/main/java/org/openpdf/text/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,32 +108,58 @@ public abstract class Image extends Rectangle {
private static final Pattern imageDataPattern = Pattern.compile("data:(image\\/[a-zA-Z0-9+-]+);.*(base64),(.*)");

/**
* this is a kind of image alignment.
* Image alignment: Default alignment (same as LEFT).
* The image will be placed on the left side of the page.
*/
public static final int DEFAULT = 0;

/**
* this is a kind of image alignment.
* Image alignment: Right-align the image.
* The image will be placed on the right side of the page.
* Can be combined with TEXTWRAP or UNDERLYING using bitwise OR.
* Example: {@code image.setAlignment(Image.RIGHT | Image.TEXTWRAP);}
*/
public static final int RIGHT = 2;

/**
* this is a kind of image alignment.
* Image alignment: Left-align the image.
* The image will be placed on the left side of the page.
* Can be combined with TEXTWRAP or UNDERLYING using bitwise OR.
* Example: {@code image.setAlignment(Image.LEFT | Image.TEXTWRAP);}
*/
public static final int LEFT = 0;

/**
* this is a kind of image alignment.
* Image alignment: Center the image horizontally on the page.
* The image will be placed in the middle of the page width.
*/
public static final int MIDDLE = 1;

/**
* this is a kind of image alignment.
* Image alignment modifier: Allow text to wrap around the image.
* When combined with LEFT or RIGHT, text will flow around the image on the opposite side.
* This is useful for creating inline images where text continues alongside the image
* instead of the image occupying its own line.
* <p>
* Example for an image with text wrapping on the right:
* {@code image.setAlignment(Image.LEFT | Image.TEXTWRAP);}
* <p>
* Example for an image with text wrapping on the left:
* {@code image.setAlignment(Image.RIGHT | Image.TEXTWRAP);}
*/
public static final int TEXTWRAP = 4;

/**
* this is a kind of image alignment.
* Image alignment modifier: Place the image behind (underneath) the text.
* When combined with other alignment flags, the image will be rendered as a background
* element with text overlaying it. This is useful for watermarks, seals, or stamps
* that should appear behind text content.
* <p>
* Example for a background image on the left:
* {@code image.setAlignment(Image.LEFT | Image.UNDERLYING);}
* <p>
* Example for a seal that appears behind text:
* {@code image.setAlignment(Image.RIGHT | Image.UNDERLYING);}
*/
public static final int UNDERLYING = 8;

Expand Down Expand Up @@ -1221,17 +1247,54 @@ public void setTemplateData(PdfTemplate template) {

/**
* Gets the alignment for the image.
* <p>
* The returned value may be a combination of alignment flags combined using bitwise OR.
* Use bitwise AND (&amp;) to check for specific flags:
* <pre>{@code
* int alignment = image.getAlignment();
* boolean hasTextwrap = (alignment & Image.TEXTWRAP) != 0;
* boolean isUnderlying = (alignment & Image.UNDERLYING) != 0;
* }</pre>
*
* @return a value
* @return the alignment value (possibly a combination of flags)
* @see #setAlignment(int)
*/
public int getAlignment() {
return alignment;
}

/**
* Sets the alignment for the image.
*
* @param alignment the alignment
* <p>
* The alignment parameter can be one of the following base values:
* <ul>
* <li>{@link #LEFT} or {@link #DEFAULT} - Align the image to the left</li>
* <li>{@link #RIGHT} - Align the image to the right</li>
* <li>{@link #MIDDLE} - Center the image horizontally</li>
* </ul>
* <p>
* The base alignment can be combined with modifiers using bitwise OR (|):
* <ul>
* <li>{@link #TEXTWRAP} - Allow text to wrap around the image (useful for inline images)</li>
* <li>{@link #UNDERLYING} - Place the image behind text (useful for watermarks, seals, stamps)</li>
* </ul>
* <p>
* Examples:
* <pre>{@code
* // Image aligned left with text wrapping around it on the right
* image.setAlignment(Image.LEFT | Image.TEXTWRAP);
*
* // Image aligned right with text wrapping around it on the left
* image.setAlignment(Image.RIGHT | Image.TEXTWRAP);
*
* // Seal or stamp that appears behind text on the right
* image.setAlignment(Image.RIGHT | Image.UNDERLYING);
*
* // Watermark that appears behind centered text
* image.setAlignment(Image.MIDDLE | Image.UNDERLYING);
* }</pre>
*
* @param alignment the alignment value (can be a combination of flags using bitwise OR)
*/

public void setAlignment(int alignment) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* This code is part of the 'OpenPDF Tutorial'.
* You can find the complete tutorial at the following address:
* https://github.com/LibrePDF/OpenPDF/wiki/Tutorial
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/
package org.openpdf.examples.objects.images;

import java.io.FileOutputStream;
import java.io.IOException;
import org.openpdf.text.Chunk;
import org.openpdf.text.Document;
import org.openpdf.text.DocumentException;
import org.openpdf.text.Font;
import org.openpdf.text.FontFactory;
import org.openpdf.text.Image;
import org.openpdf.text.Paragraph;
import org.openpdf.text.Phrase;
import org.openpdf.text.pdf.PdfWriter;

/**
* Demonstrates how to place images inline with text, including seals and stamps.
* This example addresses the common use case of placing an official seal on a signature line
* without the image occupying its own line.
*/
public class InlineImageWithText {

/**
* Creates a PDF demonstrating inline image placement with text wrapping and underlying images.
*
* @param args no arguments needed
*/
public static void main(String[] args) {
System.out.println("Inline images with text - seals, stamps, and text wrapping");
Document document = new Document();
try {
PdfWriter.getInstance(document, new FileOutputStream("inlineImageWithText.pdf"));
document.open();

// Create fonts for demonstration
Font boldFont = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 14);
Font normalFont = FontFactory.getFont(FontFactory.HELVETICA, 12);

// Example 1: Official seal placed inline with signature text (TEXTWRAP)
document.add(new Paragraph("Example 1: Seal inline with signature using TEXTWRAP", boldFont));
document.add(Chunk.NEWLINE);

// Load the seal image (using a sample image as a seal)
Image sealImage = Image.getInstance("hitchcock.png");
sealImage.scaleToFit(80f, 80f); // Scale to appropriate size
// Use RIGHT | TEXTWRAP to place seal on the right with text wrapping on the left
sealImage.setAlignment(Image.RIGHT | Image.TEXTWRAP);

// Add seal image
document.add(sealImage);

// Add signature text that will wrap around the seal
Paragraph signature = new Paragraph();
signature.setFont(normalFont);
signature.add("Signature: John Smith\n");
signature.add("Date: January 1, 2025\n");
signature.add("Title: Director\n");
signature.add("This contract is hereby approved and sealed with the official company seal.\n");
document.add(signature);

document.add(Chunk.NEWLINE);
document.add(Chunk.NEWLINE);

// Example 2: Watermark/stamp behind text (UNDERLYING)
document.add(new Paragraph("Example 2: Stamp placed behind text using UNDERLYING", boldFont));
document.add(Chunk.NEWLINE);

Image stampImage = Image.getInstance("hitchcock.png");
stampImage.scaleToFit(100f, 100f);
// Use RIGHT | UNDERLYING to place stamp behind text on the right
stampImage.setAlignment(Image.RIGHT | Image.UNDERLYING);

document.add(stampImage);

Paragraph content = new Paragraph();
content.setFont(normalFont);
content.add("This is important content that needs to be stamped. ");
content.add("The stamp will appear behind this text, acting as a watermark or official seal. ");
content.add("This technique is particularly useful for contracts, certificates, and official documents ");
content.add("where you want the seal to be visible but not disrupt the text flow.\n");
document.add(content);

document.add(Chunk.NEWLINE);
document.add(Chunk.NEWLINE);

// Example 3: Image on left with text wrapping on the right
document.add(new Paragraph("Example 3: Image on left with text wrapping using LEFT | TEXTWRAP", boldFont));
document.add(Chunk.NEWLINE);

Image leftImage = Image.getInstance("vonnegut.gif");
leftImage.scaleToFit(100f, 100f);
// Use LEFT | TEXTWRAP to place image on left with text wrapping on the right
leftImage.setAlignment(Image.LEFT | Image.TEXTWRAP);

document.add(leftImage);

for (int i = 0; i < 50; i++) {
document.add(new Phrase("This text wraps around the image on the left. ", normalFont));
}

document.add(Chunk.NEWLINE);
document.add(Chunk.NEWLINE);

// Example 4: Multiple signatures with seals
document.add(new Paragraph("Example 4: Contract with multiple signatures and seals", boldFont));
document.add(Chunk.NEWLINE);

document.add(new Paragraph("This contract is hereby signed by:", normalFont));
document.add(Chunk.NEWLINE);

// First signature with seal
Image seal1 = Image.getInstance("hitchcock.png");
seal1.scaleToFit(60f, 60f);
seal1.setAlignment(Image.RIGHT | Image.TEXTWRAP);
document.add(seal1);

Paragraph sig1 = new Paragraph();
sig1.setFont(normalFont);
sig1.add("Signature 1: Jane Doe\n");
sig1.add("Position: CEO\n");
sig1.add("Date: January 1, 2025\n");
document.add(sig1);

document.add(Chunk.NEWLINE);

// Second signature with seal (position varies based on content)
Image seal2 = Image.getInstance("hitchcock.png");
seal2.scaleToFit(60f, 60f);
seal2.setAlignment(Image.RIGHT | Image.TEXTWRAP);
document.add(seal2);

Paragraph sig2 = new Paragraph();
sig2.setFont(normalFont);
sig2.add("Signature 2: Robert Johnson\n");
sig2.add("Position: CFO\n");
sig2.add("Date: January 1, 2025\n");
document.add(sig2);

document.add(Chunk.NEWLINE);
document.add(Chunk.NEWLINE);

// Summary paragraph
Paragraph summary = new Paragraph();
summary.setFont(normalFont);
summary.add("Summary of alignment flags:\n\n");
summary.add("• Image.TEXTWRAP - Allows text to flow around the image (useful for inline images)\n");
summary.add("• Image.UNDERLYING - Places the image behind text (useful for watermarks/stamps)\n");
summary.add("• Image.LEFT | Image.TEXTWRAP - Image on left, text wraps on right\n");
summary.add("• Image.RIGHT | Image.TEXTWRAP - Image on right, text wraps on left\n");
summary.add("• Image.LEFT | Image.UNDERLYING - Image behind text on left\n");
summary.add("• Image.RIGHT | Image.UNDERLYING - Image behind text on right\n");
summary.add("\nThese flags can be combined using the bitwise OR operator (|).\n");
document.add(summary);

} catch (DocumentException | IOException e) {
System.err.println(e.getMessage());
}
document.close();
System.out.println("PDF created successfully: inlineImageWithText.pdf");
}
}
Loading