Merge pull request #891 from blikblum/fix-grayscale-png

Fix transparent grayscale png
This commit is contained in:
Luiz Américo 2018-12-23 21:19:56 -03:00 committed by GitHub
commit 2955161da7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 175 additions and 7 deletions

View File

@ -49,10 +49,10 @@ class PNGImage {
// For PNG color types 0, 2 and 3, the transparency data is stored in
// a dedicated PNG chunk.
if (this.image.transparency.grayscale) {
if (this.image.transparency.grayscale != null) {
// Use Color Key Masking (spec section 4.8.5)
// An array with N elements, where N is two times the number of color components.
const val = this.image.transparency.greyscale;
const val = this.image.transparency.grayscale;
return this.obj.data['Mask'] = [val, val];
} else if (this.image.transparency.rgb) {
@ -109,7 +109,8 @@ class PNGImage {
splitAlphaChannel() {
return this.image.decodePixels(pixels => {
let a, p;
const colorByteSize = (this.image.colors * this.image.bits) / 8;
const colorCount = this.image.colors;
const colorByteSize = (colorCount * this.image.bits) / 8;
const pixelCount = this.width * this.height;
const imgData = new Buffer(pixelCount * colorByteSize);
const alphaChannel = new Buffer(pixelCount);
@ -117,9 +118,9 @@ class PNGImage {
let i = p = a = 0;
const len = pixels.length;
while (i < len) {
imgData[p++] = pixels[i++];
imgData[p++] = pixels[i++];
imgData[p++] = pixels[i++];
for (let colorIndex = 0; colorIndex < colorCount; colorIndex++) {
imgData[p++] = pixels[i++];
}
alphaChannel[a++] = pixels[i++];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -10,7 +10,7 @@ describe("PNGImage", () => {
const img = new PNGImage(fs.readFileSync(fileName), "I1");
// noop data manipulation methods
img.loadIndexedAlphaChannel = () => {
if (img.image.hasAlphaChannel) {
if (img.image.transparency.indexed) {
img.alphaChannel = {};
}
};
@ -59,6 +59,38 @@ describe("PNGImage", () => {
});
});
test("RGB white transparent", () => {
// ImageWidth = 32
// ImageHeight = 32
// BitDepth = 16
// ColorType = 2
// Compression = 0
// Filter = 0
// Interlace = 0
const img = createImage("./tests/images/pngsuite-rgb-transparent-white.png");
expect(img.obj.data).toMatchObject({
BitsPerComponent: 16,
ColorSpace: "DeviceRGB",
Filter: "FlateDecode",
Height: 32,
Length: 1932,
Subtype: "Image",
Type: "XObject",
Width: 32,
Mask: [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255],
DecodeParms: expect.any(PDFReference)
});
expect(img.obj.data.DecodeParms.data).toMatchObject({
BitsPerComponent: 16,
Colors: 3,
Columns: 32,
Predictor: 15
});
});
test("RGB with Alpha", () => {
// ImageWidth = 409
// ImageHeight = 400
@ -129,6 +161,141 @@ describe("PNGImage", () => {
});
});
test("Pallete indexed transparency", () => {
// ImageWidth = 32
// ImageHeight = 32
// BitDepth = 8
// ColorType = 3
// Compression = 0
// Filter = 0
// Interlace = 0
const img = createImage("./tests/images/pngsuite-palette-transparent-white.png");
expect(img.obj.data).toMatchObject({
BitsPerComponent: 8,
ColorSpace: ["Indexed", "DeviceRGB", 244, expect.any(PDFReference)],
Filter: "FlateDecode",
Height: 32,
Length: 650,
Subtype: "Image",
Type: "XObject",
Width: 32,
DecodeParms: expect.any(PDFReference),
SMask: expect.any(PDFReference),
});
expect(img.obj.data.DecodeParms.data).toMatchObject({
BitsPerComponent: 8,
Colors: 1,
Columns: 32,
Predictor: 15
});
expect(img.obj.data.SMask.data).toMatchObject({
BitsPerComponent: 8,
ColorSpace: "DeviceGray",
Decode: [
0,
1
],
Filter: "FlateDecode",
Height: 32,
Length: 16,
Subtype: "Image",
Type: "XObject",
Width: 32,
});
});
test("Grayscale", () => {
// ImageWidth = 428
// ImageHeight = 320
// BitDepth = 8
// ColorType = 0
// Compression = 0
// Filter = 0
// Interlace = 0
const img = createImage("./tests/images/glassware-noisy.png");
expect(img.obj.data).toMatchObject({
BitsPerComponent: 8,
ColorSpace: "DeviceGray",
Filter: "FlateDecode",
Height: 428,
Length: 82633,
Subtype: "Image",
Type: "XObject",
Width: 320,
DecodeParms: expect.any(PDFReference),
});
});
test("Grayscale black transparent", () => {
// ImageWidth = 32
// ImageHeight = 32
// BitDepth = 4
// ColorType = 0
// Compression = 0
// Filter = 0
// Interlace = 0
const img = createImage("./tests/images/pngsuite-gray-transparent-black.png");
expect(img.obj.data).toMatchObject({
BitsPerComponent: 4,
ColorSpace: "DeviceGray",
Filter: "FlateDecode",
Height: 32,
Length: 328,
Subtype: "Image",
Type: "XObject",
Width: 32,
Mask: [0, 0],
DecodeParms: expect.any(PDFReference),
});
expect(img.obj.data.DecodeParms.data).toMatchObject({
BitsPerComponent: 4,
Colors: 1,
Columns: 32,
Predictor: 15
});
});
test("Grayscale white transparent", () => {
// ImageWidth = 32
// ImageHeight = 32
// BitDepth = 16
// ColorType = 0
// Compression = 0
// Filter = 0
// Interlace = 0
const img = createImage("./tests/images/pngsuite-gray-transparent-white.png");
expect(img.obj.data).toMatchObject({
BitsPerComponent: 16,
ColorSpace: "DeviceGray",
Filter: "FlateDecode",
Height: 32,
Length: 1212,
Subtype: "Image",
Type: "XObject",
Width: 32,
Mask: [255, 255],
DecodeParms: expect.any(PDFReference),
});
expect(img.obj.data.DecodeParms.data).toMatchObject({
BitsPerComponent: 16,
Colors: 1,
Columns: 32,
Predictor: 15
});
});
test("Grayscale with Alpha", () => {
// ImageWidth = 112
// ImageHeight = 112