OCR-READY DOCUMENT CLEANUP

Bitonal TIFF, before the upload.

One call turns a scan, an image or PDF in any common format, into a clean 1-bpp black & white TIFF, the format OCR engines expect. It runs in the browser on the user's own device, so the document is already prepared before you decide whether to send it anywhere.

On-device, no upload 1-bpp BW TIFF output Works offline Main thread or worker pool
WHAT IT DOES

One method. One bitonal TIFF.

Feed ocrbw() a scan in any common format, JPEG, PNG, TIFF or PDF, and you get back a 1-bpp black & white TIFF, every pixel either black or white, one bit each. That is the shape most OCR engines want to be handed, and computing it on the client means the raw scan does not have to travel first.

  • ✓ Input: one image or PDF, JPEG, PNG, TIFF and other common formats, as a Uint8Array
  • ✓ Output: DATA, a 1-bpp BW TIFF as a Uint8Array
  • ✓ Runs entirely in WebAssembly on the user's device
  • ✓ Same method name in both run modes
  • ✓ Returns { STATUS, DESCRIPTION, DATA }, never throws
  • ✓ No server round-trip, so it works offline
cleanup.js
// Everything below runs on this device.
const helper = new ImageWizHelper();
await helper.ready;
await helper.initialize(LICENSE_BLOB);

const file = input.files[0];
const buf  = new Uint8Array(await file.arrayBuffer());

const res = await helper.ocrbw(buf);

if (res.STATUS) {
  // res.DATA → Uint8Array, a 1-bpp BW TIFF
  const blob = new Blob([res.DATA], { type: 'image/tiff' });
  body.append('file', blob, 'clean.tiff');   // → your OCR
} else {
  console.error(res.DESCRIPTION);             // no throw
}
PIPELINE FIT

Where cleanup belongs

Cleanup is the step between capture and recognition. Doing it in the browser means the bytes you eventually send are bitonal, and the bytes you don't send never left.

1
Capture or select
A camera capture, a scanner output, or a file the user picks. Read it as a Uint8Array.
2
Inspect (optional)
Call readImageInformation() for page count, dimensions, DPI and colour type before you commit.
3
Clean in the browser
ocrbw() returns the 1-bpp BW TIFF. No upload has happened yet.
4
Send to OCR
Post the bitonal TIFF to your own OCR engine, or to the hosted OCR Full Text API.

The privacy line moves

The SDK is WebAssembly running in the page. A document is only ever transmitted if your own code chooses to transmit it after cleanup, the cleanup step itself has no network dependency, which is also why it keeps working with no connection at all.

WHY CLIENT-SIDE

Three practical consequences

The scan stays put

Cleanup happens on the user's device. Nothing is uploaded to produce the bitonal TIFF, so the original never crosses your network boundary unless you send it deliberately.

One bit per pixel

The output is a 1-bpp black & white TIFF: each pixel carries a single bit rather than a colour value. It is the representation OCR engines are built to consume.

Two run modes

Load the main-thread build for the simplest path, or the worker-pool build to keep the UI responsive and fan a batch out in parallel. Identical method names either way.

BULK

A batch, off the main thread

The worker-pool build spreads one task per file across the pool, so a folder of scans cleans up without freezing the page.

bulk.js
const helper = new ImageWizHelper();  // worker pool
await helper.ready;
await helper.initialize(LICENSE_BLOB);

const buffers = await Promise.all(
  [...input.files].map(async f =>
    new Uint8Array(await f.arrayBuffer()))
);

// one task per file, fanned out across the pool
const results = await Promise.all(
  buffers.map(b => helper.ocrbw(b))
);

results.forEach((r, i) => {
  if (r.STATUS) save(`clean_${i}.tiff`, r.DATA);
  else console.warn(i, r.DESCRIPTION);
});
verify.js
// Confirm what you're about to send.
const info = await helper.readImageInformation(r.DATA);

if (info.STATUS) {
  console.log(info.DATA.TOTAL_PAGES);  // page count
  console.log(info.DATA.FILESIZE);     // KB

  info.DATA.INFORMATION.forEach(p => {
    console.log(
      p.PAGE_NO,
      p.WIDTH, p.HEIGHT,
      p.DPI,
      p.COLOR_TYPE      // "BW"
    );
  });
}

One gotcha worth knowing

The worker facade transfers input ArrayBuffers into the worker, which detaches them on the caller's side. If you need the original bytes again after the call, re-read the file.

FAQ

Questions, answered plainly

What exactly does ocrbw() return?
The same object every method in the SDK returns: { STATUS, DESCRIPTION, DATA }. On success STATUS is true, DESCRIPTION is "SUCCESS", and DATA is a Uint8Array holding a 1-bpp black & white TIFF. Failures come back through STATUS and DESCRIPTION, the API does not throw.
Does it deskew, remove noise, or improve OCR accuracy?
We don't claim any of that. What the SDK documents for this method is a single, specific thing: a 1-bpp BW TIFF out. If your pipeline needs deskew and orientation correction as well, the hosted OCR Full Text API performs those server-side as part of recognition.
Does the document leave the browser?
Not for the cleanup step. The SDK is WebAssembly executing in the page on the user's own device, with no server round-trip, which is also why it works offline. Anything that travels afterwards travels because your code sent it.
How is this different from setting the black & white filter and compressing?
Two different tools. SetFilter(200) followed by compressToTiff(buffers) applies a black-and-white filter per page and takes an array of inputs, producing one multi-page TIFF. ocrbw(buffer) takes a single image or PDF and is the method documented to return a 1-bpp BW TIFF.
Main thread or worker pool, which build?
Both expose the same method names and the same response contract, so the choice is about where the work runs. The main-thread build is the simplest path and is fine for one document at a time; the worker-pool build keeps the UI unblocked and processes a batch in parallel.
What happens without a licence key?
initialize() is non-fatal. With a missing or rejected licence blob the SDK still initializes and every operation still works, the output is simply watermarked while it runs in demo state. That makes it straightforward to evaluate before you talk to us about licensing.
How do I confirm the output really is bitonal?
Pass the result to readImageInformation(). It returns FILESIZE in KB, TOTAL_PAGES, and a per-page INFORMATION array carrying WIDTH, HEIGHT, DPI and COLOR_TYPE, the last of which reads "BW", "GREYSCALE" or "COLOR".
Any hosting requirements?
Serve the SDK over HTTP or HTTPS, a file:// page will not load the .wasm. Keep the distributed files together in one directory, since the loader resolves its siblings relative to its own script URL. After that, no connection is needed for cleanup itself.

Clean the scan where it was captured

Get a key and wire ocrbw() into your pipeline today.