Refactors Lab CS; uses different conversion for D50 and D65; adds getRgbItem

This commit is contained in:
Yury Delendik 2012-11-30 09:07:39 -06:00
parent 223ad0c117
commit 0dc137a0df
3 changed files with 93 additions and 48 deletions

View File

@ -25,19 +25,26 @@ var ColorSpace = (function ColorSpaceClosure() {
ColorSpace.prototype = { ColorSpace.prototype = {
/** /**
* Converts src array items representing color components values starting * Converts the color value to the RGB color. The color components are
* from srcOffset to RGB color. Returns the array of the rgb components * located in the src array starting from the srcOffset. Returns the array
* items, each value ranging from [0,255]. * of the rgb components, each value ranging from [0,255].
*/ */
getRgb: function ColorSpace_getRgb(src, srcOffset) { getRgb: function ColorSpace_getRgb(src, srcOffset) {
error('Should not call ColorSpace.getRgb'); error('Should not call ColorSpace.getRgb');
}, },
/** /**
* Converts src array items representing color components values starting * Converts the color value to the RGB color, similar to the getRgb method.
* from srcOffset to RGB colors. The src is Uint8Array with the items that * The result placed into the dest array starting from the destOffset.
* represent color components values, each value scaled to [0, 2^bits). */
* Only count amount of values with be converted and placed into dest array getRgbItem: function ColorSpace_getRgb(src, srcOffset, dest, destOffset) {
* starting from destOffset offset, each value scaled to [0,255]. error('Should not call ColorSpace.getRgbItem');
},
/**
* Converts the specified number of the color values to the RGB colors.
* The colors are located in the src array starting from the srcOffset.
* The result is placed into the dest array starting from the destOffset.
* The src array items shall be in [0,2^bits) range, the dest array items
* will be in [0,255] range.
*/ */
getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) { dest, destOffset, bits) {
@ -57,9 +64,8 @@ var ColorSpace = (function ColorSpaceClosure() {
return false; return false;
}, },
/** /**
* Converts src array items representing color components values starting * Creates the output buffer and converts the specified number of the color
* from srcOffset to RGB colors similar to the getRgbBuffer. Returns * values to the RGB colors, similar to the getRgbBuffer.
* the created buffer.
*/ */
createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset, createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset,
count, bits) { count, bits) {
@ -263,12 +269,18 @@ var AlternateCS = (function AlternateCSClosure() {
AlternateCS.prototype = { AlternateCS.prototype = {
getRgb: function AlternateCS_getRgb(src, srcOffset) { getRgb: function AlternateCS_getRgb(src, srcOffset) {
var rgb = new Uint8Array(3);
this.getRgbItem(src, srcOffset, rgb, 0);
return rgb;
},
getRgbItem: function AlternateCS_getRgbItem(src, srcOffset,
dest, destOffset) {
var baseNumComps = this.base.numComps; var baseNumComps = this.base.numComps;
var input = 'subarray' in src ? var input = 'subarray' in src ?
src.subarray(srcOffset, srcOffset + this.numComps) : src.subarray(srcOffset, srcOffset + this.numComps) :
Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps); Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps);
var tinted = this.tintFn(input); var tinted = this.tintFn(input);
return this.base.getRgb(tinted, 0); this.base.getRgbItem(tinted, 0, dest, destOffset);
}, },
getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) { dest, destOffset, bits) {
@ -276,7 +288,8 @@ var AlternateCS = (function AlternateCSClosure() {
var base = this.base; var base = this.base;
var scale = 1 / ((1 << bits) - 1); var scale = 1 / ((1 << bits) - 1);
var baseNumComps = base.numComps; var baseNumComps = base.numComps;
var isPassthrough = base.isPassthrough(8); var isGetRgbBufferSupported = 'getRgbBuffer' in base;
var isPassthrough = base.isPassthrough(8) || !isGetRgbBufferSupported;
var pos = isPassthrough ? destOffset : 0; var pos = isPassthrough ? destOffset : 0;
var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count);
var numComps = this.numComps; var numComps = this.numComps;
@ -287,8 +300,13 @@ var AlternateCS = (function AlternateCSClosure() {
scaled[j] = src[srcOffset++] * scale; scaled[j] = src[srcOffset++] * scale;
} }
var tinted = tintFn(scaled); var tinted = tintFn(scaled);
for (var j = 0; j < baseNumComps; j++) { if (isGetRgbBufferSupported) {
baseBuf[pos++] = tinted[j] * 255; for (var j = 0; j < baseNumComps; j++) {
baseBuf[pos++] = tinted[j] * 255;
}
} else {
base.getRgbItem(tinted, 0, baseBuf, pos);
pos += baseNumComps;
} }
} }
if (!isPassthrough) { if (!isPassthrough) {
@ -353,6 +371,12 @@ var IndexedCS = (function IndexedCSClosure() {
var start = src[srcOffset] * numComps; var start = src[srcOffset] * numComps;
return this.base.getRgb(this.lookup, start); return this.base.getRgb(this.lookup, start);
}, },
getRgbItem: function IndexedCS_getRgbItem(src, srcOffset,
dest, destOffset) {
var numComps = this.base.numComps;
var start = src[srcOffset] * numComps;
this.base.getRgbItem(this.lookup, start, dest, destOffset);
},
getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset) { dest, destOffset) {
var base = this.base; var base = this.base;
@ -388,9 +412,15 @@ var DeviceGrayCS = (function DeviceGrayCSClosure() {
DeviceGrayCS.prototype = { DeviceGrayCS.prototype = {
getRgb: function DeviceGrayCS_getRgb(src, srcOffset) { getRgb: function DeviceGrayCS_getRgb(src, srcOffset) {
var rgb = new Uint8Array(3);
this.getRgbItem(src, srcOffset, rgb, 0);
return rgb;
},
getRgbItem: function DeviceGrayCS_getRgbItem(src, srcOffset,
dest, destOffset) {
var c = (src[srcOffset] * 255) | 0; var c = (src[srcOffset] * 255) | 0;
c = c < 0 ? 0 : c > 255 ? 255 : c; c = c < 0 ? 0 : c > 255 ? 255 : c;
return new Uint8Array([c, c, c]); dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
}, },
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) { dest, destOffset, bits) {
@ -423,14 +453,18 @@ var DeviceRgbCS = (function DeviceRgbCSClosure() {
} }
DeviceRgbCS.prototype = { DeviceRgbCS.prototype = {
getRgb: function DeviceRgbCS_getRgb(src, srcOffset) { getRgb: function DeviceRgbCS_getRgb(src, srcOffset) {
var rgb = new Uint8Array(3);
this.getRgbItem(src, srcOffset, rgb, 0);
return rgb;
},
getRgbItem: function DeviceRgbCS_getRgbItem(src, srcOffset,
dest, destOffset) {
var r = src[srcOffset] * 255; var r = src[srcOffset] * 255;
var g = src[srcOffset + 1] * 255; var g = src[srcOffset + 1] * 255;
var b = src[srcOffset + 2] * 255; var b = src[srcOffset + 2] * 255;
var rgb = new Uint8Array(3); dest[destOffset] = r < 0 ? 0 : r > 255 ? 255 : r;
rgb[0] = r < 0 ? 0 : r > 255 ? 255 : r; dest[destOffset + 1] = g < 0 ? 0 : g > 255 ? 255 : g;
rgb[1] = g < 0 ? 0 : g > 255 ? 255 : g; dest[destOffset + 2] = b < 0 ? 0 : b > 255 ? 255 : b;
rgb[2] = b < 0 ? 0 : b > 255 ? 255 : b;
return rgb;
}, },
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) { dest, destOffset, bits) {
@ -1183,6 +1217,10 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
convertToRgb(src, srcOffset, 1, rgb, 0); convertToRgb(src, srcOffset, 1, rgb, 0);
return rgb; return rgb;
}, },
getRgbItem: function DeviceCmykCS_getRgbItem(src, srcOffset,
dest, destOffset) {
convertToRgb(src, srcOffset, 1, dest, destOffset);
},
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count,
dest, destOffset, bits) { dest, destOffset, bits) {
var scale = 1 / ((1 << bits) - 1); var scale = 1 / ((1 << bits) - 1);
@ -1253,7 +1291,7 @@ var LabCS = (function LabCSClosure() {
}; };
// Function g(x) from spec // Function g(x) from spec
function g(x) { function fn_g(x) {
if (x >= 6 / 29) if (x >= 6 / 29)
return x * x * x; return x * x * x;
else else
@ -1267,31 +1305,37 @@ var LabCS = (function LabCSClosure() {
var bs = src[srcOffset + 2]; var bs = src[srcOffset + 2];
// Adjust limits of 'as' and 'bs' // Adjust limits of 'as' and 'bs'
as = as > cs.amax ? cs.amax : as; as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
as = as < cs.amin ? cs.amin : as; bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
bs = bs > cs.bmax ? cs.bmax : bs;
bs = bs < cs.bmin ? cs.bmin : bs;
// Computes intermediate variables X,Y,Z as per spec // Computes intermediate variables X,Y,Z as per spec
var M = (Ls + 16) / 116; var M = (Ls + 16) / 116;
var L = M + (as / 500); var L = M + (as / 500);
var N = M - (bs / 200); var N = M - (bs / 200);
var X = cs.XW * g(L);
var Y = cs.YW * g(M);
var Z = cs.ZW * g(N);
// XYZ to RGB 3x3 matrix, from: var X = cs.XW * fn_g(L);
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18 var Y = cs.YW * fn_g(M);
var XYZtoRGB = [3.240479, -1.537150, -0.498535, var Z = cs.ZW * fn_g(N);
-0.969256, 1.875992, 0.041556,
0.055648, -0.204043, 1.057311];
var rgb = Util.apply3dTransform(XYZtoRGB, [X, Y, Z]); var r, g, b;
// Using different conversions for D50 and D65 white points,
// per http://www.color.org/srgb.pdf
if (cs.ZW < 1) {
// Assuming D50 (X=0.9642, Y=1.00, Z=0.8249)
r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
} else {
// Assuming D65 (X=0.9505, Y=1.00, Z=1.0888)
r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
}
// clamp color values to [0,255] range // clamp color values to [0,255] range
dest[destOffset] = rgb[0] < 0 ? 0 : rgb[0] > 1 ? 255 : rgb[0] * 255; dest[destOffset] = r < 0 ? 0 : r > 1 ? 255 : r * 255;
dest[destOffset + 1] = rgb[1] < 0 ? 0 : rgb[1] > 1 ? 255 : rgb[1] * 255; dest[destOffset + 1] = g < 0 ? 0 : g > 1 ? 255 : g * 255;
dest[destOffset + 2] = rgb[2] < 0 ? 0 : rgb[2] > 1 ? 255 : rgb[2] * 255; dest[destOffset + 2] = b < 0 ? 0 : b > 1 ? 255 : b * 255;
} }
LabCS.prototype = { LabCS.prototype = {
@ -1300,21 +1344,13 @@ var LabCS = (function LabCSClosure() {
convertToRgb(this, src, srcOffset, rgb, 0); convertToRgb(this, src, srcOffset, rgb, 0);
return rgb; return rgb;
}, },
getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, getRgbItem: function LabCS_getRgbItem(src, srcOffset, dest, destOffset) {
dest, destOffset) { convertToRgb(this, src, srcOffset, dest, destOffset);
for (var i = 0; i < count; ++i) {
convertToRgb(this, src, srcOffset, dest, destOffset);
srcOffset += 3;
destOffset += 3;
}
return rgbBuf;
}, },
getOutputLength: function LabCS_getOutputLength(inputLength) { getOutputLength: function LabCS_getOutputLength(inputLength) {
return inputLength; return inputLength;
}, },
isPassthrough: ColorSpace.prototype.isPassthrough, isPassthrough: ColorSpace.prototype.isPassthrough,
createRgbBuffer: ColorSpace.prototype.createRgbBuffer,
isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) { isDefaultDecode: function LabCS_isDefaultDecode(decodeMap) {
// From Table 90 in Adobe's: // From Table 90 in Adobe's:
// "Document management - Portable document format", 1st ed, 2008 // "Document management - Portable document format", 1st ed, 2008

View File

@ -0,0 +1 @@
http://www.uctc.net/access/30/Access%2030%20-%2002%20-%20Horse%20Power.pdf

View File

@ -735,6 +735,14 @@
"rounds": 1, "rounds": 1,
"type": "load" "type": "load"
}, },
{ "id": "issue1998",
"file": "pdfs/issue1998.pdf",
"md5": "586e0213be2f461360ec26770b5a4e48",
"rounds": 1,
"pageLimit": 2,
"link": true,
"type": "load"
},
{ "id": "issue1878", { "id": "issue1878",
"file": "pdfs/issue1878.pdf", "file": "pdfs/issue1878.pdf",
"md5": "b4fb0ce7c19368e7104dce3d0d34bcb3", "md5": "b4fb0ce7c19368e7104dce3d0d34bcb3",