Page-level PDF editing — removing extra pages, reordering pages, fixing pages with the wrong orientation, or cropping out unwanted margins — comes up pretty often in day-to-day development. It sounds simple, but once you actually write the code, index shifting and coordinate system direction are the kind of details that trip people up. This post walks through the implementation for each of these operations with Java code examples.
Setup
The library used here is Spire.PDF for Java. If you're using Maven, add the following to your pom.xml:
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.pdf</artifactId>
<version>12.7.0</version>
</dependency>
</dependencies>
If you're not using Maven, you can also download the jar directly from the vendor's site and add it to your project manually.
Once the dependency is in place, pretty much everything page-related revolves around the PdfDocument class and its getPages() collection. Let's go through each operation.
1. Deleting Pages
Deleting a page is the most common operation. Use PdfDocument.getPages().removeAt(int index), passing in the zero-based index of the page you want to remove.
import com.spire.pdf.PdfDocument;
public class DeletePage {
public static void main(String[] args) {
// Create a PdfDocument instance
PdfDocument pdf = new PdfDocument();
// Load the PDF document
pdf.loadFromFile("sample.pdf");
// Remove the second page (index is zero-based, so 1 means the second page)
pdf.getPages().removeAt(1);
// Save the result
pdf.saveToFile("output/deletePage.pdf");
pdf.close();
}
}
Page indices start at 0, which is easy to mix up with the "page 1 = first page" convention people usually think in — worth double-checking the index before you run this. The deletion is also irreversible, so back up the original file first.
If you need to delete multiple pages at once, delete from the highest index to the lowest. Say you want to remove pages 2, 4, and 6: if you iterate forward and delete as you go, once page 2 is gone, the old page 4 shifts into page 3's slot, and continuing with the original indices ends up deleting the wrong pages.
int[] pagesToDelete = {1, 3, 5}; // corresponds to pages 2, 4, 6
Arrays.sort(pagesToDelete);
for (int i = pagesToDelete.length - 1; i >= 0; i--) {
pdf.getPages().removeAt(pagesToDelete[i]);
}
2. Reordering Pages
When page order is scrambled, use PdfDocument.getPages().reArrange() to fix it in one shot. It takes an int[] array where each element is the original page index, and the array's order becomes the new page order.
import com.spire.pdf.PdfDocument;
public class RearrangePages {
public static void main(String[] args) {
// Create a PdfDocument instance
PdfDocument doc = new PdfDocument();
// Load the PDF document
doc.loadFromFile("input.pdf");
// Reorder pages: original page 1, 3, 2, 4
doc.getPages().reArrange(new int[]{0, 2, 1, 3});
// Save the result
doc.saveToFile("output/rearranged.pdf");
doc.close();
}
}
3. Rotating Pages
Scanned PDFs frequently end up with the wrong orientation. Rotation works in 90-degree increments — 0°, 90°, 180°, or 270° — set via PdfPageBase.setRotation().
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.PdfPageRotateAngle;
public class RotatePdfPage {
public static void main(String[] args) {
// Create a PdfDocument instance
PdfDocument pdf = new PdfDocument();
// Load the PDF document
pdf.loadFromFile("sample.pdf");
// Get the first page
PdfPageBase page = pdf.getPages().get(0);
// Get the current rotation angle
int rotation = page.getRotation().getValue();
// Rotate 180 degrees on top of the existing angle
rotation += PdfPageRotateAngle.Rotate_Angle_180.getValue();
page.setRotation(PdfPageRotateAngle.fromValue(rotation));
// Save the result
pdf.saveToFile("output/rotated.pdf");
pdf.close();
}
}
Note that this adds to the existing rotation angle rather than overwriting it. Scanned files often already carry a rotation value of their own (PDFs generated from phone photos default to 270 degrees quite often), so if you skip reading the original angle and just assign a new one directly, the displayed result won't match what you expect.
To rotate every page, just loop through the pdf.getPages() collection and apply the same logic to each one:
for (int i = 0; i < pdf.getPages().getCount(); i++) {
PdfPageBase page = pdf.getPages().get(i);
int rotation = page.getRotation().getValue();
rotation += PdfPageRotateAngle.Rotate_Angle_90.getValue();
page.setRotation(PdfPageRotateAngle.fromValue(rotation));
}
4. Cropping Pages
Cropping works by modifying the page's CropBox, which defines the visible area of the page — anything outside it simply won't render. Use PdfPageBase.setCropBox(Rectangle2D rect) to set it.
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import java.awt.geom.Rectangle2D;
public class CropPdfPage {
public static void main(String[] args) {
// Create a PdfDocument instance
PdfDocument pdf = new PdfDocument();
// Load the PDF document
pdf.loadFromFile("example.pdf");
// Get the first page
PdfPageBase page = pdf.getPages().get(0);
// Define the crop area: x, y, width, height
Rectangle2D rect = new Rectangle2D.Float(0, 0, 550, 822);
// Apply the crop box
page.setCropBox(rect);
// Save the result
pdf.saveToFile("output/cropped.pdf");
pdf.close();
}
}
All four Rectangle2D.Float parameters are in points. There's one gotcha worth calling out on its own: Spire.PDF's coordinate system is not the same as the native PDF spec. The PDF spec places the origin at the bottom-left of the page with the y-axis pointing up. Spire.PDF, to make top-down positioning more intuitive for programmers, remaps that to an origin at the top-left with the y-axis pointing down. setCropBox follows this same remapped system: x and y are the offset of the crop area's top-left corner from the page's top-left corner, and width/height extend right and downward from there.
So to crop out a black margin at the top of the page, you just set y to the margin height directly — no need to work backward from the total page height. For a 20pt margin at the top, that's new Rectangle2D.Float(0, 20, width, height - 20) — starting 20pt down from the top and extending down to the bottom of the page skips right past that margin. Assuming the origin is bottom-left, the way the raw PDF spec defines it, gets the direction backwards — you'll typically end up with either the margin still sitting there or a chunk of your content cut off.
One more thing worth noting: setCropBox only changes the visible region — the original content is still fully intact in the file, just not rendered outside the crop box. That means it's not a real deletion. If you're trying to redact sensitive information from a page, cropping isn't the right tool for that.
Summary
This article showed how to remove, reorder, rotate and crop pages in PDF. Use removeAt() for deleting pages, reArrange() for reordering, setRotation() for rotating, and setCropBox() for cropping. A few things worth keeping in mind: delete pages from the end backward when removing multiple at once; rotation angles accumulate rather than get overwritten; and the crop coordinate system is Spire.PDF's own remapped one — origin at the top-left, y-axis pointing down — which is the opposite of what the native PDF spec defines, even though it happens to be what you'd normally expect from a graphics API. Keeping these in mind up front saves a fair bit of debugging time later.
Comments
Post a Comment