When extracting monochrome scanned documents or faxes from a PDF using iText, you might encounter a bizarre issue: the extracted image looks diagonally skewed, distorted, or horizontally shifted. Interestingly, switching the same PDF to Apache PDFBox extracts the exact same image cleanly without any artifacts.

The Root Cause: Scanline Bit Alignment and Stride

This issue occurs specifically with 1-bit monochrome images compressed using CCITTFaxDecode (Group 3 or Group 4 fax compression) when the image width in pixels is not an exact multiple of 8.

Consider an image with a width of 1205 pixels:

  • 1205 bits / 8 bits per byte = 150 bytes with a remainder of 5 bits.
  • In standard bitmap raster representations (such as Java's MultiPixelPackedSampleModel or Windows BMP / TIFF specifications), each scanline (row) must be padded to the nearest full byte boundary (requiring 151 bytes per row, where the last 3 bits are padding).
  • If the CCITT decoder treats the decoded bitstream as a continuous stream of bits across row boundaries without padding each row to the byte boundary, or if the raster stride is miscalculated, every new line begins 3 bits too early.

Over a height of 1706 lines, this cumulative shift results in the familiar slanted, sheared appearance.

Why PDFBox Handles It Better

Apache PDFBox features a dedicated, battle-tested CCITTFaxDecoderStream that correctly handles the /EncodedByteAlign and /Columns parameters specified in the PDF dictionary, ensuring rows are correctly aligned and padded before transferring pixel data into a BufferedImage.

Workarounds and Solutions

1. Using TwelveMonkeys ImageIO as an External CCITT Decoder

If you must remain in an iText-centric pipeline, you can bypass iText's built-in getBufferedImage() decoding by reading the raw CCITT stream and routing it through TwelveMonkeys ImageIO (which supports CCITT T.4/T.6 decoding cleanly):

<!-- Add to pom.xml -->
<dependency>
    <groupId>com.twelvemonkeys.imageio</groupId>
    <artifactId>imageio-tiff</artifactId>
    <version>3.10.1</version>
</dependency>

Wrap the raw bytes into a TIFF header containing the proper CCITT tags, then decode using ImageIO.read().

2. Leveraging PDFBox as a Fallback Extractor

Until iText addresses this scanline padding bug in PdfImageXObject, the most robust workaround for extraction is using PDFBox specifically for CCITT images:

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import java.awt.image.BufferedImage;
import java.io.File;

public class ImageExtractionHelper {
    public static BufferedImage extractCorrectCCITTImage(File pdfFile, String objectKey) throws Exception {
        try (PDDocument document = PDDocument.load(pdfFile)) {
            // Locate your PDImageXObject
            PDImageXObject image = ...; 
            // PDFBox correctly handles scanline padding for non-byte-aligned widths
            return image.getImage();
        }
    }
}

3. Fixing the Problem in pdfSweep (Redaction Pipelines)

If you are encountering this problem during redaction workflows with pdfSweep, the distortion happens because pdfSweep decodes the image, applies vector-based blackouts to the bitmap, and re-encodes it. Because the decode phase produces a skewed raster, the redacted image is saved in its skewed state.

To work around this in redaction pipelines:

  • Pre-normalize the PDF: Run a preprocessing step using PDFBox or ghostscript to rewrite non-aligned CCITT streams (e.g., re-encoding them to FlateDecode/PNG or padding the image canvas to a multiple of 8 pixels) before feeding the document into iText's pdfSweep.
  • File a bug with iText: Provide the image dictionary (with /Columns 1205 and /BitsPerComponent 1). The fix on their end requires updating the internal scanline unpacker to enforce byte-aligned line strides when creating the Raster for BufferedImage.

Summary

The distortion happens because iText's CCITT decoding logic currently misses byte-boundary row padding when width % 8 != 0. For image extraction, use PDFBox or TwelveMonkeys as an immediate fix; for redaction, normalize or pad the source images to a byte-aligned width before processing.