Skip to content
This repository has been archived by the owner on Jul 15, 2019. It is now read-only.

Commit

Permalink
Fix various issues with different color formats
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelerz committed May 16, 2015
1 parent d93dd2a commit 4264848
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 104 deletions.
73 changes: 36 additions & 37 deletions lib/png/chunks/IHDR.js
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,8 @@ module.exports = {
* @return {int}
*/
getBytesPerPixel: function () {
var bitDepth = Math.max(8, this.getBitDepth()); // Lower than 8 will be rounded up
return (bitDepth / 8) * this.getSamples();
var bitDepth = this.getBitDepth();
return (bitDepth / 8) * this.getUnprocessedSamples();
},

/**
Expand All @@ -251,6 +251,16 @@ module.exports = {
return this.hasIndexedColor() ? 3 : (this.isColor() ? 3 : 1) + (this.hasAlphaChannel() ? 1 : 0);
},

/**
* Gets the number of samples for the color-type (unprocessed - palette not applied yet)
*
* @method getUnprocessedSamples
* @return {int}
*/
getUnprocessedSamples: function () {
return this.hasIndexedColor() ? 1 : this.getSamples();
},

/**
* Gets the sample-depth for the color-type
*
Expand Down Expand Up @@ -439,53 +449,42 @@ module.exports = {
*/
postDecode: function (image, strict) {

var imageStream, scaledStream, spreadedStream, injectedStream;

if (this.isColorTypeIndexedColor()) {
// We expect the PLTE chunk to have already done the work
return image;
}
var imageStream, scaledStream,
bytesNeeded,
isColor, hasAlpha, isIndexed;

imageStream = new BufferedStream(image, false);

isColor = this.isColor();
hasAlpha = this.hasAlphaChannel();
isIndexed = this.isColorTypeIndexedColor();

// Do some scaling
if (this.getBitDepth() === 1) {
scaledStream = new BufferedStream(null, null, image.length * 8);
scale.scale1to8bit(imageStream, scaledStream);
if ((this.getBitDepth() === 8) && isColor && hasAlpha) {
scaledStream = imageStream; // Nothing to do

} else if (this.getBitDepth() === 2) {
scaledStream = new BufferedStream(null, null, image.length * 4);
scale.scale2to8bit(imageStream, scaledStream);
} else {
bytesNeeded = this.getWidth() * this.getHeight() * this.getImageBytesPerPixel();
scaledStream = new BufferedStream(null, null, bytesNeeded);

} else if (this.getBitDepth() === 4) {
scaledStream = new BufferedStream(null, null, image.length * 2);
scale.scale4to8bit(imageStream, scaledStream);
if (this.getBitDepth() === 1) {
scale.scale1to8bit(imageStream, scaledStream, isColor, hasAlpha, isIndexed);

} else if (this.getBitDepth() === 16) {
scaledStream = new BufferedStream(null, null, image.length * 0.5);
scale.scale16to8bit(imageStream, scaledStream);
} else if (this.getBitDepth() === 2) {
scale.scale2to8bit(imageStream, scaledStream, isColor, hasAlpha, isIndexed);

} else {
scaledStream = imageStream; // Nothing to do
}
} else if (this.getBitDepth() === 4) {
scale.scale4to8bit(imageStream, scaledStream, isColor, hasAlpha, isIndexed);

// Channel spreading - Grayscale to color
if (!this.isColor()) {
spreadedStream = new BufferedStream(null, null, scaledStream.length * 3);
scale.duplicate(scaledStream, spreadedStream, 3);
} else {
spreadedStream = scaledStream; // Nothing to do
}
} else if (this.getBitDepth() === 8) {
scale.scale8to8bit(imageStream, scaledStream, isColor, hasAlpha, isIndexed);

// Add alpha channel if needed
if (!this.hasAlphaChannel()) {
injectedStream = new BufferedStream(null, null, spreadedStream.length * 4/3);
scale.inject(spreadedStream, injectedStream, 3, 255);
} else {
injectedStream = spreadedStream; // Nothing to do
} else { // if (this.getBitDepth() === 16) {
scale.scale16to8bit(imageStream, scaledStream, isColor, hasAlpha, isIndexed);
}
}

return injectedStream.toBuffer(true);
return scaledStream.toBuffer(true);
},

/**
Expand Down
20 changes: 10 additions & 10 deletions lib/png/chunks/PLTE.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,16 @@ module.exports = {


/**
* Decoding of chunk data before scaling
* Decoding of chunk data after scaling
*
* Phase 2
* Phase 3
*
* @method decode
* @method postDecode
* @param {Buffer} image
* @param {boolean} strict Should parsing be strict?
* @return {Buffer}
*/
decode: function (image, strict) {
postDecode: function (image, strict) {

var i, len, index,
color, colors, colorsLength,
Expand All @@ -140,20 +140,22 @@ module.exports = {

// Check if image requires a palette or if the colors are suggested
if (!headerChunk.hasIndexedColor()) {
//TODO: May be give an option for using these suggested colors?
return image; // Ignore these since they are not needed
}

colors = this._colors;
colorsLength = colors.length;
imageStream = new BufferedStream(image, false);
outputStream = new BufferedStream(null, null, image.length * 4);

outputStream = new BufferedStream(image, false); // use same buffer
outputStream.writeOffset = 0;

// Convert an index color image to true-color image
for (i = 0, len = image.length; i < len; i++) {
for (i = 0, len = image.length; i < len; i += 4) {

// Get index from input
index = imageStream.readUInt8();
imageStream.skip(3); // Skip the next three bytes
if (index >= colorsLength) {

if (strict) {
Expand All @@ -173,13 +175,11 @@ module.exports = {
color = colors[index];
}

color.alpha = color.alpha || 255; // Opaque by default

// Write to image
outputStream.writeUInt8(color.red);
outputStream.writeUInt8(color.green);
outputStream.writeUInt8(color.blue);
outputStream.writeUInt8(color.alpha);
outputStream.writeUInt8(255);
}

return outputStream.toBuffer(true);
Expand Down
10 changes: 10 additions & 0 deletions lib/png/utils/bufferedStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ BufferedStream.prototype._readCheck = function (size) {
}
};

/**
* Skips a number of bytes
*
* @param {int} count Number of bytes to skip
*/
BufferedStream.prototype.skip = function (count) {
this.readOffset += count;
this.readCounter += count;
};

/**
* @method readUInt8
* @param {boolean} [noAssert=false]
Expand Down

0 comments on commit 4264848

Please sign in to comment.