Skip to content

Commit

Permalink
Fix embedded CMYK image (#415)
Browse files Browse the repository at this point in the history
* Fix embedded CMYK image rendering blank

* Fix embedded CMYK image rendering inverted

* Add test for CMYK embedding
  • Loading branch information
zwaldowski authored Apr 26, 2020
1 parent 350c54b commit 594fc6a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 3 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 21 additions & 3 deletions src/core/embedders/JpegEmbedder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ const MARKERS = [
enum ColorSpace {
DeviceGray = 'DeviceGray',
DeviceRGB = 'DeviceRGB',
DeviceCYMK = 'DeviceCYMK',
DeviceCMYK = 'DeviceCMYK',
}

const ChannelToColorSpace: { [idx: number]: ColorSpace | undefined } = {
1: ColorSpace.DeviceGray,
3: ColorSpace.DeviceRGB,
4: ColorSpace.DeviceCYMK,
4: ColorSpace.DeviceCMYK,
};

/**
* A note of thanks to the developers of https://github.com/foliojs/pdfkit, as
* this class borrows from:
* https://github.com/devongovett/pdfkit/blob/e71edab0dd4657b5a767804ba86c94c58d01fbca/lib/image/jpeg.coffee
* https://github.com/foliojs/pdfkit/blob/a6af76467ce06bd6a2af4aa7271ccac9ff152a7d/lib/image/jpeg.js
*/
class JpegEmbedder {
static async for(imageData: Uint8Array) {
Expand Down Expand Up @@ -100,6 +100,24 @@ class JpegEmbedder {
Height: this.height,
ColorSpace: this.colorSpace,
Filter: 'DCTDecode',
// CMYK JPEG streams in PDF are typically stored complemented,
// with 1 as 'off' and 0 as 'on' (PDF 32000-1:2008, 8.6.4.4).
//
// Standalone CMYK JPEG (usually exported by Photoshop) are
// stored inverse, with 0 as 'off' and 1 as 'on', like RGB.
//
// Applying a swap here as a hedge that most bytes passing
// through this method will benefit from it.
Decode: this.colorSpace === ColorSpace.DeviceCMYK && [
1,
0,
1,
0,
1,
0,
1,
0,
],
});

if (ref) {
Expand Down
10 changes: 10 additions & 0 deletions tests/core/embedders/JpegEmbedder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { JpegEmbedder, PDFContext, PDFRawStream, PDFRef } from 'src/core';

const catUnicornJpg = fs.readFileSync('./assets/images/cat_riding_unicorn.jpg');
const minionsLaughing = fs.readFileSync('./assets/images/minions_laughing.jpg');
const cmykJpg = fs.readFileSync('./assets/images/Channel_digital_image_CMYK_color.jpg');

describe(`JpegEmbedder`, () => {
it(`can be constructed with JpegEmbedder.for(...)`, async () => {
Expand Down Expand Up @@ -49,4 +50,13 @@ describe(`JpegEmbedder`, () => {
expect(embedder.width).toBe(630);
expect(embedder.colorSpace).toBe('DeviceRGB');
});

it(`can extract properties of JPEG images (3)`, async () => {
const embedder = await JpegEmbedder.for(cmykJpg);

expect(embedder.bitsPerComponent).toBe(8);
expect(embedder.height).toBe(333);
expect(embedder.width).toBe(500);
expect(embedder.colorSpace).toBe('DeviceCMYK');
});
});

0 comments on commit 594fc6a

Please sign in to comment.