Render document in night mode

Q:How can I render a document in night mode?

A: Night mode is not supported yet in PSPDFKit for Web, but you could emulate it using PSPDFKit.Configuration#renderPageCallback, like in this example where we convert every pixel to HSV, invert the luminance value and convert the pixel back to RGB to be rendered:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
PSPDFKit.load({
  ...defaultConfiguration,
  renderPageCallback(ctx, pageIndex, pageSize) {
    const imageData = ctx.getImageData(0, 0, pageSize.width, pageSize.height);
    for (let y = 0; y < pageSize.height; y++) {
      for (let x = 0; x < pageSize.width; x++) {
        const pR = imageData.data[y * pageSize.width * 4 + x * 4];
        const pG = imageData.data[y * pageSize.width * 4 + x * 4 + 1];
        const pB = imageData.data[y * pageSize.width * 4 + x * 4 + 2];
        const [h, s, v] = rgb2hsv(pR / 255, pG / 255, pB / 255);
        const [nR, nG, nB] = hsv2rgb(h, s, 1 - v);
        imageData.data[y * pageSize.width * 4 + x * 4] = nR * 255;
        imageData.data[y * pageSize.width * 4 + x * 4 + 1] = nG * 255;
        imageData.data[y * pageSize.width * 4 + x * 4 + 2] = nB * 255;
      }
    }
    ctx.putImageData(imageData, 0, 0);
  }
});

// https://stackoverflow.com/a/54070620/1934001
// input: r,g,b in [0,1], out: h in [0,360) and s,v in [0,1]
function rgb2hsv(r, g, b) {
  let v = Math.max(r, g, b),
    n = v - Math.min(r, g, b);
  let h =
    n && (v == r ? (g - b) / n : v == g ? 2 + (b - r) / n : 4 + (r - g) / n);
  return [60 * (h < 0 ? h + 6 : h), v && n / v, v];
}

// https://stackoverflow.com/a/54024653/1934001
// input: h in [0,360] and s,v in [0,1] - output: r,g,b in [0,1]
function hsv2rgb(h, s, v) {
  let f = (n, k = (n + h / 60) % 6) =>
    v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
  return [f(5), f(3), f(1)];
}

Unfortunately, using this operation to render each page is quite resource expensive so we don't recommend implementing it. Instead, you could use a compromise between color fidelity and performance where you just let the browser invert every pixel color, so not only white gets rendered as black, but all the other colors get inverted too.

Copy
1
2
3
4
5
6
7
8
PSPDFKit.load({ 
  ...defaultConfiguration,
  renderPageCallback(ctx, pageIndex, pageSize) {
    ctx.globalCompositeOperation = "difference";
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, pageSize.width, pageSize.height);
  }
});

This has been tested with PSPDFKit for Web 2019.4.1