Skip to content

Commit

Permalink
⚾ Replace Buffer with Uint8Array
Browse files Browse the repository at this point in the history
  • Loading branch information
hyzyla committed Aug 10, 2024
1 parent b16bb09 commit f31ef59
Show file tree
Hide file tree
Showing 11 changed files with 40 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ async main() {
});

// Save the PNG image to the output folder
await fs.writeFile(`output/${page.number}.png`, image.data);
await fs.writeFile(`output/${page.number}.png`, Buffer.from(image.data));
}

// Do not forget to destroy the document and the library
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/02-render-pdf.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ console.log(image.data); // Bitmap image data as a buffer

#### render: custom render function

You can also pass a custom render function as the `render` option. It should be a function that accepts a `RenderPageOptions` object and returns a `Promise<Buffer>` object. You can use it to render to any image format:
You can also pass a custom render function as the `render` option. It should be a function that accepts a `RenderPageOptions` object and returns a `Promise<Uint8Array>` object. You can use it to render to any image format:

```typescript
import sharp from 'sharp';
import { type PDFiumPageRenderOptions } from '@hyzyla/pdfium';

const image = await page.render({
scale: 3,
render: async (options: PDFiumPageRenderOptions): Promise<Buffer> => {
render: async (options: PDFiumPageRenderOptions): Promise<Uint8Array> => {
return await sharp(options.data, {
raw: {
width: options.width,
Expand Down Expand Up @@ -170,7 +170,7 @@ async main() {
});

// Save the PNG image to the output folder
await fs.writeFile(`output/${page.number}.png`, image.data);
await fs.writeFile(`output/${page.number}.png`, Buffer.from(image.data));
}

// Do not forget to destroy the document and the library
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/03-extract-images-from-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ for (const page of document.pages()) {
});

// Save the PNG image to the output folder
await fs.writeFile(`output/${index}.png`, image.data);
await fs.writeFile(`output/${index}.png`, Buffer.from(image.data));

index++;
}
Expand All @@ -44,7 +44,7 @@ const page = document.getPage(0);
const object = page.getObject(0);

const image = await object.render({
render: async (options: PDFiumPageRenderOptions): Promise<Buffer> => {
render: async (options: PDFiumPageRenderOptions): Promise<Uint8Array> => {
return await sharp(options.data, {
raw: {
width: options.width,
Expand Down
21 changes: 12 additions & 9 deletions src/objects.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type * as t from "./vendor/pdfium";

import { BYTES_PER_PIXEL, FPDFBitmap, FPDFPageObjectType } from "./constants";
import { convertBitmapToImage } from "./utils";
import { convertBitmapToImage, readUInt16LE } from "./utils";
import type {
PDFiumImageObjectRaw,
PDFiumImageObjectRender,
Expand Down Expand Up @@ -93,7 +93,7 @@ export class PDFiumImageObject extends PDFiumObjectBase {
throw new Error("Failed to get bitmap buffer.");
}

const oData = Buffer.from(this.module.HEAPU8.slice(bufferPtr, bufferPtr + bufferSize));
const oData = this.module.HEAPU8.slice(bufferPtr, bufferPtr + bufferSize);
this.module.wasmExports.free(bufferPtr);

// Width and height of the image in pixels will be written to these pointers as 16-bit integers (2 bytes each):
Expand All @@ -106,12 +106,12 @@ export class PDFiumImageObject extends PDFiumObjectBase {
throw new Error("Failed to get image size.");
}

const widthBuffer = Buffer.from(this.module.HEAPU8.slice(widthPtr, widthPtr + 2));
const heightBuffer = Buffer.from(this.module.HEAPU8.slice(heightPtr, heightPtr + 2));
const widthBuffer = this.module.HEAPU8.slice(widthPtr, widthPtr + 2);
const heightBuffer = this.module.HEAPU8.slice(heightPtr, heightPtr + 2);
this.module.wasmExports.free(sizePtr);

const width = widthBuffer.readUInt16LE();
const height = heightBuffer.readUInt16LE();
const width = readUInt16LE(widthBuffer)
const height = readUInt16LE(heightBuffer)

const filtersCount = this.module._FPDFImageObj_GetImageFilterCount(this.objectIdx);
const filters: string[] = [];
Expand All @@ -121,8 +121,9 @@ export class PDFiumImageObject extends PDFiumObjectBase {
if (!this.module._FPDFImageObj_GetImageFilter(this.objectIdx, i, filterPtr, filterSize)) {
throw new Error("Failed to get image filter.");
}
const filterBuffer = Buffer.from(this.module.HEAPU8.slice(filterPtr, filterPtr + filterSize - 1));
const filter = filterBuffer.toString("utf8").trim();
const filterBuffer = this.module.HEAPU8.slice(filterPtr, filterPtr + filterSize - 1);
const filter = (new TextDecoder().decode(filterBuffer)).trim();

this.module.wasmExports.free(filterPtr);
filters.push(filter);
}
Expand Down Expand Up @@ -178,7 +179,9 @@ export class PDFiumImageObject extends PDFiumObjectBase {
const tBPP = BYTES_PER_PIXEL;

// Create a new buffer for the target image and fill it with white color
const tData = Buffer.alloc(width * height * tBPP, 255);
const tData = new Uint8Array(width * height * tBPP);
// Fill the buffer with transparent white color
tData.fill(255);

// Iterate over the rows of the original and target images
for (let rowIndex = 0; rowIndex < height; rowIndex++) {
Expand Down
4 changes: 2 additions & 2 deletions src/objects.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ export type PDFiumImageObjectRenderParams = {
export type PDFiumImageObjectRender = {
width: number;
height: number;
data: Buffer;
data: Uint8Array;
};

export type PDFiumImageObjectRaw = {
width: number;
height: number;
data: Buffer;
data: Uint8Array;
filters: string[];
};
4 changes: 2 additions & 2 deletions src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class PDFiumPage {
this.module._FPDFBitmap_Destroy(bitmap);
this.module._FPDF_ClosePage(this.pageIdx);

const data = Buffer.from(this.module.HEAPU8.subarray(ptr, ptr + buffSize));
const data = this.module.HEAPU8.subarray(ptr, ptr + buffSize);
this.module.wasmExports.free(ptr);

const image = await this.convertBitmapToImage({
Expand All @@ -112,7 +112,7 @@ export class PDFiumPage {
options: {
render: PDFiumRenderFunction;
} & PDFiumRenderOptions,
): Promise<Buffer> {
): Promise<Uint8Array> {
return await convertBitmapToImage(options);
}

Expand Down
10 changes: 5 additions & 5 deletions src/page.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ import type { PDFiumRenderFunction, PDFiumRenderOptions } from "./types";
export type PDFiumPageRenderFunction = PDFiumRenderFunction;
export type PDFiumPageRenderOptions = PDFiumRenderOptions;

export type PDFiumPageRenderCallback = (options: PDFiumPageRenderOptions) => Promise<Buffer>;
export type PDFiumPageRenderCallback = (options: PDFiumPageRenderOptions) => Promise<Uint8Array>;
export type PDFiumPageRenderParams = {
render: PDFiumPageRenderFunction;
} & (
| {
| {
scale: number;
}
| {
| {
width: number;
height: number;
}
);
);

export type PDFiumPageSize = {
width: number;
Expand All @@ -26,5 +26,5 @@ export type PDFiumPageRender = {
height: number;
originalHeight: number;
originalWidth: number;
data: Buffer;
data: Uint8Array;
};
2 changes: 1 addition & 1 deletion src/renderer/sharp.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PDFiumRenderOptions } from "../types";

export async function renderBySharp(options: PDFiumRenderOptions): Promise<Buffer> {
export async function renderBySharp(options: PDFiumRenderOptions): Promise<Uint8Array> {
const { default: sharp } = await import("sharp");
return await sharp(options.data, {
raw: {
Expand Down
4 changes: 2 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export type PDFiumRenderOptions = {
width: number;
height: number;
data: Buffer;
data: Uint8Array;
};

export type PDFiumRenderCallback = (options: PDFiumRenderOptions) => Promise<Buffer>;
export type PDFiumRenderCallback = (options: PDFiumRenderOptions) => Promise<Uint8Array>;

export type PDFiumRenderFunction = "sharp" | "bitmap" | PDFiumRenderCallback;
7 changes: 6 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export async function convertBitmapToImage(
options: {
render: PDFiumRenderFunction;
} & PDFiumRenderOptions,
): Promise<Buffer> {
): Promise<Uint8Array> {
switch (options.render) {
case "sharp":
return await renderBySharp(options);
Expand All @@ -15,3 +15,8 @@ export async function convertBitmapToImage(
return await options.render(options);
}
}


export function readUInt16LE(buffer: Uint8Array, offset = 0): number {
return buffer[offset] | (buffer[offset + 1] << 8);
}
7 changes: 4 additions & 3 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,14 @@ describe("PDFium", () => {
const result = await document.getPage(0).render({
scale: 1,
render: async (options) => {
expect(options.data).toBeInstanceOf(Buffer);
expect(options.data).toBeInstanceOf(Uint8Array);
expect(options.height).toBe(A4_SIZE.height);
expect(options.width).toBe(A4_SIZE.width);
return Buffer.from("test");
return new TextEncoder().encode("test");
},
});
expect(result).toEqual({
data: Buffer.from("test"),
data: new TextEncoder().encode("test"),
height: A4_SIZE.height,
width: A4_SIZE.width,
originalHeight: A4_SIZE.height,
Expand Down Expand Up @@ -256,6 +256,7 @@ describe("PDFium", () => {
const { data: image } = await imageObj.render({
render: "sharp",
});
expect(image).toBeInstanceOf(Uint8Array);
expect(image).toMatchImageSnapshot();
}
}
Expand Down

0 comments on commit f31ef59

Please sign in to comment.