0

I'm using nodejs and I'm processing PDFs. One thing I'd like to do is to outline all the fonts of the PDF (so that they are not selectable with the mouse cursor afterwards).

I tried the pdftk's flatten command (using a node wrapper), but I did not get what I wanted.

I may have a track in using inkscape (command line), but I'm not even sure about how to do it. I really am looking for the easiest way to do that using nodejs.

There might also be a track using ghostscript: https://stackoverflow.com/a/28798374/11348232. One notable thing to notice is that I don't use files on disk, but Buffer objects, so it'd be painful to save the PDF locally then use the gs command.

Thanks a lot.

Contestosis
  • 369
  • 1
  • 4
  • 19
  • 2
    Ghostscript is perfectly capable of accepting the PDF piped into stdin. It will then of course buffer the PDF to disk, but at least **you** don't have to save the PDF content. There is no JavaScript interface though, so you'd have to send the content from your buffer to stdin of a separate process. I rather suspect that saving the content to a local file might actually be easier. Using -dNoOutputFonts with the pdfwrite device will then produce a PDF file where all the 'text' is in fact simply linework. The resulting PDF will of course be a file on disk. – KenS Feb 23 '22 at 13:10
  • @KenS the output pdf has some defects: some borders around font characters have disappeared. Do you know an option to fix that? – Contestosis Mar 21 '22 at 13:27
  • @KenS I have a follow-up question there: https://stackoverflow.com/q/71558819/11348232 – Contestosis Mar 21 '22 at 13:56

1 Answers1

0

I finally followed @KenS way:

import util from 'util';
import childProcess from 'child_process';
import fs from 'fs';
import os from 'os';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';

const exec = util.promisify(childProcess.exec);

const unlinkCallback = (err) => {
  if (err) {
    console.error(err);
  }
};

const deleteFile = (path: fs.PathLike) => {
  if (fs.existsSync(path)) {
    fs.unlink(path, unlinkCallback);
  }
};

const createTempPathPDF = () => path.join(os.tmpdir(), `${uuidv4()}.pdf`);

const convertFontsToOutlines = async (buffer: Buffer): Promise<Buffer> => {
  const inputPath = createTempPathPDF();
  const outputPath = createTempPathPDF();
  let bufferWithOutlines: Buffer;

  fs.createWriteStream(inputPath).write(buffer);

  try {
    // ! ghostscript package MUST be installed on system
    await exec(`gs -o ${outputPath} -dNoOutputFonts -sDEVICE=pdfwrite ${inputPath}`);

    bufferWithOutlines = fs.readFileSync(outputPath);
  } catch (e) {
    console.error(e);

    bufferWithOutlines = buffer;
  }

  deleteFile(inputPath);
  deleteFile(outputPath);

  return bufferWithOutlines;
};
Contestosis
  • 369
  • 1
  • 4
  • 19