Claude Code × Medical Application

[Claude Code] Turning Visual Checks into Automated Checks, Part 1: Detecting Page Breaks — Measuring White Space by Greyscale Intensity

日本語 / English

1. Introduction — a broken page shows up as white space

As we saw on the reference page, pages with broken page breaks share a common shape.

  • Only one or two rows are left at the end of the page, with a large empty area below
  • Columns are pushed onto the next page, leaving a large empty area on the right
  • The page holds only a title and footnotes, with almost no content

The numbers are correct, so numeric checks do not catch these. People find them by paging through the PDF one page at a time. Put the other way round: if you measure how much white there is along the bottom and right edges of each page, you can narrow down the pages that need a human eye.

This post goes through that measurement step by step.

  1. Where the method comes from
  2. What we wrote before handing the work to Claude Code
  3. Turning the page into a greyscale image and measuring the white ratio
  4. Flagging pages — the threshold and the “near threshold” label
  5. Why page 1 is skipped, and the range to check
  6. What changes when you move the threshold
  7. What this method cannot find
  • 31pagesthe dummy TLF used throughout the series (30 pages checked, pages 2–31)
  • 8pagesflagged CHECK; the same 8 pages we deliberately broke
  • 0.98threshold for the bottom edge and right edge white ratios
  • ≈30mscomputation time per page (in the browser)

2. Where the method comes from

The method is based on the PharmaSUG 2026 paper “Detecting Abnormal Page Breaks Using Grayscale Pixel-Density Analysis in R Shiny” (Yi Guo, Paper AP-233). The same method was also presented at an R/Pharma 2026 workshop.

The idea in the paper is simple. Turn the page into a greyscale image and count the proportion of white pixels. A normal page packed with tables and text has a moderate white ratio; a broken page is almost pure white towards the edges. The method captures that difference as a number.

In TLF Visual QC, we reimplemented the method to run in the browser, following the steps and default values described in the paper. The reason is that the PDF is never sent to a server; everything is computed only on the user’s own computer (this design is covered in Part 4).

3. What we wrote before handing the work to Claude Code

3-1. The instructions

We left the implementation to Claude Code, but before starting, we wrote down in an instruction document what to build and what to protect. Its contents were as follows.

Item What we wrote
Purpose Find pages with unnatural page breaks in a TLF PDF
Steps and defaults Follow the paper’s steps. Use the paper’s defaults as they are for resolution, downscaling ratio, cropped bands, white cut-off and thresholds
What to protect Never send the user’s PDF anywhere. Add no outbound communication (including analytics or advertising tags). Use no real drug names, study numbers or company names
How to verify Build a dummy TLF with deliberately broken pages mixed in, and fix the correct page numbers in advance. It passes if the CHECK pages match the answer
Where to stop Once page-break detection is implemented, write a report and stop. Colour checks and screen finishing come in the next stage

3-2. What people decided

The most important point in the instructions was deciding that we would not tweak the steps or defaults ourselves.

Each value in the paper has a reason behind it. If you start adjusting things because “this might work better,” you can no longer compare against the paper’s results, and you lose track of what is actually having an effect. We set the order: confirm it works exactly as in the paper first, and only then make changes.

The other point was preparing the answer first. With a dummy TLF that records which pages were broken, pass or fail comes down to one question: “Are the 8 pages flagged CHECK the same 8 pages we broke?” This leaves no room to look at the results and then judge them “roughly right” (verification is covered in detail in Part 2).

4. Turning the page into a greyscale image and measuring the white ratio

There are six steps.

Animation showing the six steps in order: PDF page → render to image → convert to greyscale → downscale → crop edge bands → measure white ratio
The six steps of page-break detection (a broken dummy page)

4-1. Render the page as an image (120 dpi)

Each PDF page is rendered as a 120 dpi image. In the browser, the PDF viewer component (PDF.js) draws the page, and the pixels are then read back.

4-2. Convert to greyscale

The colour image is converted to a greyscale image that holds brightness only. Pixel values run from 0 (black) to 255 (white).

4-3. Downscale (25%)

The image is shrunk to 25% in each direction. The shapes of small characters are lost, but all we want to know here is “where is it white,” so that does not matter. With one sixteenth of the pixels to compute, it runs faster.

4-4. Crop the edge bands (6% top and bottom, 8% left and right)

The top and bottom 6% and the left and right 8% of the page are cut away, and only the central area is examined.

Diagram cropping 6% bands at top and bottom and 8% bands at left and right, then splitting the remaining area into a bottom half and a right half
The cropped bands and the areas where the white ratio is measured. The bottom edge is the bottom half of the remaining area; the right edge is the right half

Paper margins, and the page numbers and headers that appear identically on every page, are present on all pages, so they do not help tell pages apart. Removing them first makes differences in what we actually care about, the layout of the content, show up more clearly in the numbers.

4-5. Count as white (pixels brighter than 245)

A pixel with a value greater than 245 is counted as “white.” This includes not only pure white (255) but also light greys close to the paper background. Table rules and light shading are not counted as white.

4-6. Three white ratios

For the remaining area, three white-pixel ratios are calculated.

Metric Area Role
Bottom edge white ratio Bottom half of the remaining area Find pages with only a few rows left at the end (primary)
Right edge white ratio Right half of the remaining area Find pages where columns were pushed over, leaving the right empty (primary)
Overall white ratio The whole remaining area Find nearly blank pages (supporting)
Bar chart comparing the bottom edge, right edge and overall white ratios for a page empty at the bottom, a page empty on the right and a normal page
The three white ratios (dummy). On a broken page, the bottom or right ratio approaches 1

5. Flagging pages — the threshold and the “near threshold” label

5-1. The CHECK conditions

A page that meets any one of the following is flagged CHECK. All other pages are OK.

  • The bottom edge white ratio is greater than 0.98
  • The right edge white ratio is greater than 0.98
  • The overall white ratio is greater than 0.95

If 98% or more of the bottom half is white, there is almost no text in the bottom half. On a normal table page, the table runs right down to the last row, so this does not happen.

Chart of the bottom edge and right edge white ratios for the 30 pages of the dummy TLF, with CHECK marks on pages that cross the 0.98 line
Bottom edge and right edge white ratios for the dummy TLF. Pages where either exceeds 0.98 are flagged CHECK
The tool’s results table, listing the three white ratios and the verdict for each page
The tool's results table (dummy)

In the dummy TLF, 8 pages were flagged CHECK: 5, 8, 10, 15, 18, 21, 24 and 29. These are the same 8 pages we deliberately broke.

5-2. Mean and standard deviation are not used for the verdict

The paper also calculates the mean and standard deviation of the page’s pixels, but these are only displayed as reference values and are not used for the verdict. The mean and standard deviation capture changes in how white the page is as a whole, but they cannot tell where the white area is. Whether a page is broken depends on whether the white is concentrated towards an edge, so the verdict uses the three ratios, which carry position.

We also do not use robust measures such as the median. Almost all pixels on a page are close to white, so the median is nearly the same on every page and shows no difference.

5-3. The “near threshold” label

If you draw the line exactly at the threshold, 0.979 and 0.981 get different verdicts. So in TLF Visual QC we decided to add a discreet “near threshold” label to pages whose white ratio is within ±0.01 of the threshold. This is a display added in the tool; it is not in the paper. It does not change the verdict itself.

The tool’s screen showing a “near threshold” label on page 31
Page 31 is OK, but its bottom edge white ratio is 0.977, so it gets the label (dummy)

In the dummy TLF, the label appears on 4 pages, 10, 15, 21 and 24 (all CHECK), and on page 31 (OK). Page 31 is a short table followed by two lines of footnotes, with a bottom edge white ratio of 0.977. It is not flagged CHECK, but it is picked up as a page you may want to check by eye just in case, even though it is OK.

6. Why page 1 is skipped, and the range to check

In the paper, checking starts from page 2. Page 1 is a cover or table of contents, centred on a logo and title, and has a different shape from the body of the TLF. Breaks on page 1 are rare, and if one does occur, an ordinary review spots it at once.

TLF Visual QC also starts from page 2 by default. Some PDFs have no cover, however (the table starts right on page 1), so we made the range to check configurable.

The range setting, with Custom selected and an arbitrary range specified
The range setting. The default (Full) runs from page 2 to the last page; Custom lets you specify a range

7. What changes when you move the threshold

The value 0.98 is the paper’s default, and it is not necessarily optimal for every TLF. Lowering the threshold adds flags; raising it removes them.

Line chart of the number of CHECK pages in the dummy TLF as the threshold moves from 0.90 to 0.99
Threshold and number of CHECK pages (dummy). Lowering the bottom edge and right edge threshold adds page 31 at 0.97 and page 7 at 0.94

In the dummy TLF, the 8 deliberately broken pages have bottom edge or right edge white ratios close to 1.000, so even raising the threshold to 0.99 left them at 8 pages. Lowering it adds page 31 (the short table with footnotes) at 0.97 and page 7 (a normal page whose table ends two thirds of the way down) at 0.94, for 10 pages. Lowering the overall threshold (0.95) to 0.91 or below also adds page 31.

Set the threshold too low and normal pages get flagged too, adding to the pages you must check by eye. Set it too high and you miss pages with smaller breaks. The right value depends on the company and on how its TLFs are produced. The paper itself notes that the thresholds are fixed rules and need adjusting to each company’s layout.

8. What this method cannot find

Because this method measures “white space concentrated towards an edge,” it does not help in the following cases.

Case What happens
Tables that are short by design A summary table that ends after a few rows has a white bottom even when nothing is broken, so it is flagged CHECK
Footnotes or footers in the bottom half If footnotes or footers sit above the cropped band (the bottom 6%), within the bottom half of the measured area, their text lowers the white ratio. Even with a large empty area below the table, the page may fall short of 0.98 and stay OK
Breaks that are not white space A table header not repeated on the next page, or a row cut off midway, does not show up as white space

A flag on a short table can be dismissed as “not a break” in a few seconds by eye. Misses caused by footnotes or footers, on the other hand, produce no flag and are therefore harder to notice, so take care with TLFs that have many footnotes. The tool’s About section also carries this caution. Part 2 shows how this kind of miss appeared in a real submission-format TLF.

9. Summary

  • A broken page break shows up as unnatural white space along the bottom or right edge of a page
  • Render each page as a 120 dpi image, convert to greyscale, downscale to 25%, crop 6% at top and bottom and 8% at left and right, then measure the ratio of white (pixels brighter than 245) in the bottom half, the right half and overall
  • Flag CHECK if the bottom or right exceeds 0.98, or overall exceeds 0.95. The tool also adds a “near threshold” label within ±0.01 of the threshold
  • We decided in advance to follow the paper’s steps and defaults, and to verify with an answer-keyed dummy before changing anything
  • Short tables get flagged, and footnotes or footers in the bottom half can cause misses. Use it to narrow down visual checks, not to replace them

Finding broken pages is less tiring with numbers than with your eyes. But knowing what the numbers actually measure is the surest way to avoid misses.

Next steps

Part 2 covers how we verified that this computation works correctly: comparing the image processing pixel by pixel against another tool, how we built the deliberately broken dummy TLF and its answer key, and the results of trying it on a submission-format TLF published by the R Consortium.

Sources

  • Yi Guo. Detecting Abnormal Page Breaks Using Grayscale Pixel-Density Analysis in R Shiny. PharmaSUG 2026, Paper AP-233. https://pharmasug.org/proceedings/2026/AP/PharmaSUG-2026-AP-233.pdf (the method was also presented at an R/Pharma 2026 workshop)
  • The TLF images and figures on this page come from a dummy TLF (31 pages) built from fictitious data. It is not related to any real study, drug or company