|
|
@ -24,15 +24,52 @@ var ColorSpace = (function ColorSpaceClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ColorSpace.prototype = { |
|
|
|
ColorSpace.prototype = { |
|
|
|
// Input: array of size numComps representing color component values
|
|
|
|
/** |
|
|
|
// Output: array of rgb values, each value ranging from [0.1]
|
|
|
|
* Converts src array items representing color components values starting |
|
|
|
getRgb: function ColorSpace_getRgb(color) { |
|
|
|
* from srcOffset to RGB color. Returns the array of the rgb components |
|
|
|
error('Should not call ColorSpace.getRgb: ' + color); |
|
|
|
* items, each value ranging from [0,255]. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
getRgb: function ColorSpace_getRgb(src, srcOffset) { |
|
|
|
|
|
|
|
error('Should not call ColorSpace.getRgb'); |
|
|
|
}, |
|
|
|
}, |
|
|
|
// Input: Uint8Array of component values, each value scaled to [0,255]
|
|
|
|
/** |
|
|
|
// Output: Uint8Array of rgb values, each value scaled to [0,255]
|
|
|
|
* Converts src array items representing color components values starting |
|
|
|
getRgbBuffer: function ColorSpace_getRgbBuffer(input) { |
|
|
|
* from srcOffset to RGB colors. The src is Uint8Array with the items that |
|
|
|
error('Should not call ColorSpace.getRgbBuffer: ' + input); |
|
|
|
* represent color components values, each value scaled to [0, 2^bits). |
|
|
|
|
|
|
|
* Only count amount of values with be converted and placed into dest array |
|
|
|
|
|
|
|
* starting from destOffset offset, each value scaled to [0,255]. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
getRgbBuffer: function ColorSpace_getRgbBuffer(src, srcOffset, count, |
|
|
|
|
|
|
|
dest, destOffset, bits) { |
|
|
|
|
|
|
|
error('Should not call ColorSpace.getRgbBuffer'); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Determines amount of the bytes is required to store the reslut of the |
|
|
|
|
|
|
|
* conversion that done by the getRgbBuffer method. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
getOutputLength: function ColorSpace_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
error('Should not call ColorSpace.getOutputLength'); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns true if source data will be equal the result/output data. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
isPassthrough: function ColorSpace_isPassthrough(bits) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Converts src array items representing color components values starting |
|
|
|
|
|
|
|
* from srcOffset to RGB colors similar to the getRgbBuffer. Returns |
|
|
|
|
|
|
|
* the created buffer. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
createRgbBuffer: function ColorSpace_createRgbBuffer(src, srcOffset, |
|
|
|
|
|
|
|
count, bits) { |
|
|
|
|
|
|
|
if (this.isPassthrough(bits)) { |
|
|
|
|
|
|
|
return src.subarray(srcOffset); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var destLength = this.getOutputLength(count * this.numComps); |
|
|
|
|
|
|
|
var dest = new Uint8Array(destLength); |
|
|
|
|
|
|
|
this.getRgbBuffer(src, srcOffset, count, dest, 0, bits); |
|
|
|
|
|
|
|
return dest; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -216,39 +253,54 @@ var AlternateCS = (function AlternateCSClosure() { |
|
|
|
function AlternateCS(numComps, base, tintFn) { |
|
|
|
function AlternateCS(numComps, base, tintFn) { |
|
|
|
this.name = 'Alternate'; |
|
|
|
this.name = 'Alternate'; |
|
|
|
this.numComps = numComps; |
|
|
|
this.numComps = numComps; |
|
|
|
this.defaultColor = []; |
|
|
|
this.defaultColor = new Float32Array(numComps); |
|
|
|
for (var i = 0; i < numComps; ++i) |
|
|
|
for (var i = 0; i < numComps; ++i) { |
|
|
|
this.defaultColor.push(1); |
|
|
|
this.defaultColor[i] = 1; |
|
|
|
|
|
|
|
} |
|
|
|
this.base = base; |
|
|
|
this.base = base; |
|
|
|
this.tintFn = tintFn; |
|
|
|
this.tintFn = tintFn; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
AlternateCS.prototype = { |
|
|
|
AlternateCS.prototype = { |
|
|
|
getRgb: function AlternateCS_getRgb(color) { |
|
|
|
getRgb: function AlternateCS_getRgb(src, srcOffset) { |
|
|
|
var tinted = this.tintFn(color); |
|
|
|
var baseNumComps = this.base.numComps; |
|
|
|
return this.base.getRgb(tinted); |
|
|
|
var input = 'subarray' in src ? |
|
|
|
|
|
|
|
src.subarray(srcOffset, srcOffset + this.numComps) : |
|
|
|
|
|
|
|
Array.prototype.slice.call(src, srcOffset, srcOffset + this.numComps); |
|
|
|
|
|
|
|
var tinted = this.tintFn(input); |
|
|
|
|
|
|
|
return this.base.getRgb(tinted, 0); |
|
|
|
}, |
|
|
|
}, |
|
|
|
getRgbBuffer: function AlternateCS_getRgbBuffer(input, bits) { |
|
|
|
getRgbBuffer: function AlternateCS_getRgbBuffer(src, srcOffset, count, |
|
|
|
|
|
|
|
dest, destOffset, bits) { |
|
|
|
var tintFn = this.tintFn; |
|
|
|
var tintFn = this.tintFn; |
|
|
|
var base = this.base; |
|
|
|
var base = this.base; |
|
|
|
var scale = 1 / ((1 << bits) - 1); |
|
|
|
var scale = 1 / ((1 << bits) - 1); |
|
|
|
var length = input.length; |
|
|
|
|
|
|
|
var pos = 0; |
|
|
|
|
|
|
|
var baseNumComps = base.numComps; |
|
|
|
var baseNumComps = base.numComps; |
|
|
|
var baseBuf = new Uint8Array(baseNumComps * length); |
|
|
|
var isPassthrough = base.isPassthrough(8); |
|
|
|
|
|
|
|
var pos = isPassthrough ? destOffset : 0; |
|
|
|
|
|
|
|
var baseBuf = isPassthrough ? dest : new Uint8Array(baseNumComps * count); |
|
|
|
var numComps = this.numComps; |
|
|
|
var numComps = this.numComps; |
|
|
|
var scaled = []; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < length; i += numComps) { |
|
|
|
|
|
|
|
for (var z = 0; z < numComps; ++z) |
|
|
|
|
|
|
|
scaled[z] = input[i + z] * scale; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var scaled = new Float32Array(numComps); |
|
|
|
|
|
|
|
for (var i = 0; i < count; i++) { |
|
|
|
|
|
|
|
for (var j = 0; j < numComps; j++) { |
|
|
|
|
|
|
|
scaled[j] = src[srcOffset++] * scale; |
|
|
|
|
|
|
|
} |
|
|
|
var tinted = tintFn(scaled); |
|
|
|
var tinted = tintFn(scaled); |
|
|
|
for (var j = 0; j < baseNumComps; ++j) |
|
|
|
for (var j = 0; j < baseNumComps; j++) { |
|
|
|
baseBuf[pos++] = 255 * tinted[j]; |
|
|
|
baseBuf[pos++] = tinted[j] * 255; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!isPassthrough) { |
|
|
|
|
|
|
|
base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8); |
|
|
|
} |
|
|
|
} |
|
|
|
return base.getRgbBuffer(baseBuf, 8); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getOutputLength: function AlternateCS_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
return this.base.getOutputLength(inputLength * |
|
|
|
|
|
|
|
this.base.numComps / this.numComps); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
isPassthrough: ColorSpace.prototype.isPassthrough, |
|
|
|
|
|
|
|
createRgbBuffer: ColorSpace.prototype.createRgbBuffer, |
|
|
|
isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { |
|
|
|
isDefaultDecode: function AlternateCS_isDefaultDecode(decodeMap) { |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
} |
|
|
|
} |
|
|
@ -271,7 +323,7 @@ var IndexedCS = (function IndexedCSClosure() { |
|
|
|
function IndexedCS(base, highVal, lookup) { |
|
|
|
function IndexedCS(base, highVal, lookup) { |
|
|
|
this.name = 'Indexed'; |
|
|
|
this.name = 'Indexed'; |
|
|
|
this.numComps = 1; |
|
|
|
this.numComps = 1; |
|
|
|
this.defaultColor = [0]; |
|
|
|
this.defaultColor = new Uint8Array([0]); |
|
|
|
this.base = base; |
|
|
|
this.base = base; |
|
|
|
this.highVal = highVal; |
|
|
|
this.highVal = highVal; |
|
|
|
|
|
|
|
|
|
|
@ -296,33 +348,29 @@ var IndexedCS = (function IndexedCSClosure() { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
IndexedCS.prototype = { |
|
|
|
IndexedCS.prototype = { |
|
|
|
getRgb: function IndexedCS_getRgb(color) { |
|
|
|
getRgb: function IndexedCS_getRgb(src, srcOffset) { |
|
|
|
var numComps = this.base.numComps; |
|
|
|
var numComps = this.base.numComps; |
|
|
|
var start = color[0] * numComps; |
|
|
|
var start = src[srcOffset] * numComps; |
|
|
|
var c = []; |
|
|
|
return this.base.getRgb(this.lookup, start); |
|
|
|
|
|
|
|
|
|
|
|
for (var i = start, ii = start + numComps; i < ii; ++i) |
|
|
|
|
|
|
|
c.push(this.lookup[i]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return this.base.getRgb(c); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
getRgbBuffer: function IndexedCS_getRgbBuffer(input) { |
|
|
|
getRgbBuffer: function IndexedCS_getRgbBuffer(src, srcOffset, count, |
|
|
|
|
|
|
|
dest, destOffset) { |
|
|
|
var base = this.base; |
|
|
|
var base = this.base; |
|
|
|
var numComps = base.numComps; |
|
|
|
var numComps = base.numComps; |
|
|
|
|
|
|
|
var outputDelta = base.getOutputLength(numComps); |
|
|
|
var lookup = this.lookup; |
|
|
|
var lookup = this.lookup; |
|
|
|
var length = input.length; |
|
|
|
|
|
|
|
var baseBuf = new Uint8Array(length * numComps); |
|
|
|
|
|
|
|
var baseBufPos = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < length; ++i) { |
|
|
|
for (var i = 0; i < count; ++i) { |
|
|
|
var lookupPos = input[i] * numComps; |
|
|
|
var lookupPos = src[srcOffset++] * numComps; |
|
|
|
for (var j = 0; j < numComps; ++j) { |
|
|
|
base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8); |
|
|
|
baseBuf[baseBufPos++] = lookup[lookupPos + j]; |
|
|
|
destOffset += outputDelta; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return base.getRgbBuffer(baseBuf, 8); |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getOutputLength: function IndexedCS_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
return this.base.getOutputLength(inputLength * this.base.numComps); |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
isPassthrough: ColorSpace.prototype.isPassthrough, |
|
|
|
|
|
|
|
createRgbBuffer: ColorSpace.prototype.createRgbBuffer, |
|
|
|
isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { |
|
|
|
isDefaultDecode: function IndexedCS_isDefaultDecode(decodeMap) { |
|
|
|
// indexed color maps shouldn't be changed
|
|
|
|
// indexed color maps shouldn't be changed
|
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -335,26 +383,31 @@ var DeviceGrayCS = (function DeviceGrayCSClosure() { |
|
|
|
function DeviceGrayCS() { |
|
|
|
function DeviceGrayCS() { |
|
|
|
this.name = 'DeviceGray'; |
|
|
|
this.name = 'DeviceGray'; |
|
|
|
this.numComps = 1; |
|
|
|
this.numComps = 1; |
|
|
|
this.defaultColor = [0]; |
|
|
|
this.defaultColor = new Float32Array([0]); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
DeviceGrayCS.prototype = { |
|
|
|
DeviceGrayCS.prototype = { |
|
|
|
getRgb: function DeviceGrayCS_getRgb(color) { |
|
|
|
getRgb: function DeviceGrayCS_getRgb(src, srcOffset) { |
|
|
|
var c = color[0]; |
|
|
|
var c = (src[srcOffset] * 255) | 0; |
|
|
|
return [c, c, c]; |
|
|
|
c = c < 0 ? 0 : c > 255 ? 255 : c; |
|
|
|
|
|
|
|
return new Uint8Array([c, c, c]); |
|
|
|
}, |
|
|
|
}, |
|
|
|
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(input, bits) { |
|
|
|
getRgbBuffer: function DeviceGrayCS_getRgbBuffer(src, srcOffset, count, |
|
|
|
|
|
|
|
dest, destOffset, bits) { |
|
|
|
var scale = 255 / ((1 << bits) - 1); |
|
|
|
var scale = 255 / ((1 << bits) - 1); |
|
|
|
var length = input.length; |
|
|
|
var j = srcOffset, q = destOffset; |
|
|
|
var rgbBuf = new Uint8Array(length * 3); |
|
|
|
for (var i = 0; i < count; ++i) { |
|
|
|
for (var i = 0, j = 0; i < length; ++i) { |
|
|
|
var c = (scale * src[j++]) | 0; |
|
|
|
var c = (scale * input[i]) | 0; |
|
|
|
dest[q++] = c; |
|
|
|
rgbBuf[j++] = c; |
|
|
|
dest[q++] = c; |
|
|
|
rgbBuf[j++] = c; |
|
|
|
dest[q++] = c; |
|
|
|
rgbBuf[j++] = c; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return rgbBuf; |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getOutputLength: function DeviceGrayCS_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
return inputLength * 3; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
isPassthrough: ColorSpace.prototype.isPassthrough, |
|
|
|
|
|
|
|
createRgbBuffer: ColorSpace.prototype.createRgbBuffer, |
|
|
|
isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { |
|
|
|
isDefaultDecode: function DeviceGrayCS_isDefaultDecode(decodeMap) { |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
} |
|
|
|
} |
|
|
@ -366,22 +419,39 @@ var DeviceRgbCS = (function DeviceRgbCSClosure() { |
|
|
|
function DeviceRgbCS() { |
|
|
|
function DeviceRgbCS() { |
|
|
|
this.name = 'DeviceRGB'; |
|
|
|
this.name = 'DeviceRGB'; |
|
|
|
this.numComps = 3; |
|
|
|
this.numComps = 3; |
|
|
|
this.defaultColor = [0, 0, 0]; |
|
|
|
this.defaultColor = new Float32Array([0, 0, 0]); |
|
|
|
} |
|
|
|
} |
|
|
|
DeviceRgbCS.prototype = { |
|
|
|
DeviceRgbCS.prototype = { |
|
|
|
getRgb: function DeviceRgbCS_getRgb(color) { |
|
|
|
getRgb: function DeviceRgbCS_getRgb(src, srcOffset) { |
|
|
|
return color; |
|
|
|
var r = src[srcOffset] * 255; |
|
|
|
|
|
|
|
var g = src[srcOffset + 1] * 255; |
|
|
|
|
|
|
|
var b = src[srcOffset + 2] * 255; |
|
|
|
|
|
|
|
var rgb = new Uint8Array(3); |
|
|
|
|
|
|
|
rgb[0] = r < 0 ? 0 : r > 255 ? 255 : r; |
|
|
|
|
|
|
|
rgb[1] = g < 0 ? 0 : g > 255 ? 255 : g; |
|
|
|
|
|
|
|
rgb[2] = b < 0 ? 0 : b > 255 ? 255 : b; |
|
|
|
|
|
|
|
return rgb; |
|
|
|
}, |
|
|
|
}, |
|
|
|
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(input, bits) { |
|
|
|
getRgbBuffer: function DeviceRgbCS_getRgbBuffer(src, srcOffset, count, |
|
|
|
if (bits == 8) |
|
|
|
dest, destOffset, bits) { |
|
|
|
return input; |
|
|
|
var length = count * 3; |
|
|
|
|
|
|
|
if (bits == 8) { |
|
|
|
|
|
|
|
dest.set(src.subarray(srcOffset, srcOffset + length), destOffset); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
var scale = 255 / ((1 << bits) - 1); |
|
|
|
var scale = 255 / ((1 << bits) - 1); |
|
|
|
var i, length = input.length; |
|
|
|
var j = srcOffset, q = destOffset; |
|
|
|
var rgbBuf = new Uint8Array(length); |
|
|
|
for (var i = 0; i < length; ++i) { |
|
|
|
for (i = 0; i < length; ++i) |
|
|
|
dest[q++] = (scale * input[j++]) | 0; |
|
|
|
rgbBuf[i] = (scale * input[i]) | 0; |
|
|
|
} |
|
|
|
return rgbBuf; |
|
|
|
}, |
|
|
|
|
|
|
|
getOutputLength: function DeviceRgbCS_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
return inputLength; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
isPassthrough: function DeviceRgbCS_isPassthrough(bits) { |
|
|
|
|
|
|
|
return bits == 8; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
createRgbBuffer: ColorSpace.prototype.createRgbBuffer, |
|
|
|
isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { |
|
|
|
isDefaultDecode: function DeviceRgbCS_isDefaultDecode(decodeMap) { |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
} |
|
|
|
} |
|
|
@ -1059,72 +1129,74 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() { |
|
|
|
15, 13, 26, 2, 1, 11, 0, 0, 0, 0, 0, 0, 54, 54, 57, 47, 44, 47, 39, 35, 39, |
|
|
|
15, 13, 26, 2, 1, 11, 0, 0, 0, 0, 0, 0, 54, 54, 57, 47, 44, 47, 39, 35, 39, |
|
|
|
28, 25, 29, 17, 13, 17, 4, 1, 3, 0, 0, 0, 0, 0, 0]); |
|
|
|
28, 25, 29, 17, 13, 17, 4, 1, 3, 0, 0, 0, 0, 0, 0]); |
|
|
|
|
|
|
|
|
|
|
|
function DeviceCmykCS() { |
|
|
|
function convertToRgb(src, srcOffset, srcScale, dest, destOffset) { |
|
|
|
this.name = 'DeviceCMYK'; |
|
|
|
// using lut as in spline interpolation (see function.js)
|
|
|
|
this.numComps = 4; |
|
|
|
var cubeVertices = 16; // 1 << number of colors
|
|
|
|
this.defaultColor = [0, 0, 0, 1]; |
|
|
|
var cubeN = new Float32Array(cubeVertices); |
|
|
|
} |
|
|
|
var cubeVertex = new Uint32Array(cubeVertices); |
|
|
|
DeviceCmykCS.prototype = { |
|
|
|
for (var j = 0; j < cubeVertices; j++) |
|
|
|
getRgb: function DeviceCmykCS_getRgb(color) { |
|
|
|
cubeN[j] = 1; |
|
|
|
// using lut as in spline interpolation (see function.js)
|
|
|
|
|
|
|
|
var cubeVertices = 16; // 1 << number of colors
|
|
|
|
|
|
|
|
var cubeN = new Float32Array(cubeVertices); |
|
|
|
|
|
|
|
var cubeVertex = new Uint32Array(cubeVertices); |
|
|
|
|
|
|
|
for (var j = 0; j < cubeVertices; j++) |
|
|
|
|
|
|
|
cubeN[j] = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var k = 3, pos = 1; |
|
|
|
var k = 3, pos = 1; |
|
|
|
var lutDomain = 7, lutStep = 8; |
|
|
|
var lutDomain = 7, lutStep = 8; |
|
|
|
for (var i = 3; i >= 0; i--) { |
|
|
|
for (var i = 3; i >= 0; i--) { |
|
|
|
var e = color[i] * lutDomain; |
|
|
|
var e = src[srcOffset + i] * srcScale * lutDomain; |
|
|
|
|
|
|
|
|
|
|
|
var e0 = e < lutDomain ? Math.floor(e) : e - 1; // e1 = e0 + 1;
|
|
|
|
var e0 = e < lutDomain ? Math.floor(e) : e - 1; // e1 = e0 + 1;
|
|
|
|
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
|
|
|
|
var n0 = e0 + 1 - e; // (e1 - e) / (e1 - e0);
|
|
|
|
var n1 = e - e0; // (e - e0) / (e1 - e0);
|
|
|
|
var n1 = e - e0; // (e - e0) / (e1 - e0);
|
|
|
|
var offset0 = e0 * k; |
|
|
|
var offset0 = e0 * k; |
|
|
|
var offset1 = offset0 + k; // e1 * k
|
|
|
|
var offset1 = offset0 + k; // e1 * k
|
|
|
|
for (var j = 0; j < cubeVertices; j++) { |
|
|
|
for (var j = 0; j < cubeVertices; j++) { |
|
|
|
if (j & pos) { |
|
|
|
if (j & pos) { |
|
|
|
cubeN[j] *= n1; |
|
|
|
cubeN[j] *= n1; |
|
|
|
cubeVertex[j] += offset1; |
|
|
|
cubeVertex[j] += offset1; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
cubeN[j] *= n0; |
|
|
|
cubeN[j] *= n0; |
|
|
|
cubeVertex[j] += offset0; |
|
|
|
cubeVertex[j] += offset0; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
k *= lutStep; |
|
|
|
|
|
|
|
pos <<= 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var y = new Float32Array(3); |
|
|
|
|
|
|
|
for (var j = 0; j < 3; ++j) { |
|
|
|
|
|
|
|
var rj = 0; |
|
|
|
|
|
|
|
for (var i = 0; i < cubeVertices; i++) |
|
|
|
|
|
|
|
rj += lut[cubeVertex[i] + j] * cubeN[i]; |
|
|
|
|
|
|
|
y[j] = rj; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return [y[0] / 255, y[1] / 255, y[2] / 255]; |
|
|
|
k *= lutStep; |
|
|
|
|
|
|
|
pos <<= 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
var y0 = 0, y1 = 0, y2 = 0; |
|
|
|
|
|
|
|
for (var i = 0; i < cubeVertices; i++) |
|
|
|
|
|
|
|
y0 += lut[cubeVertex[i]] * cubeN[i]; |
|
|
|
|
|
|
|
for (var i = 0; i < cubeVertices; i++) |
|
|
|
|
|
|
|
y1 += lut[cubeVertex[i] + 1] * cubeN[i]; |
|
|
|
|
|
|
|
for (var i = 0; i < cubeVertices; i++) |
|
|
|
|
|
|
|
y2 += lut[cubeVertex[i] + 2] * cubeN[i]; |
|
|
|
|
|
|
|
dest[destOffset] = y0 > 255 ? 255 : y0; |
|
|
|
|
|
|
|
dest[destOffset + 1] = y1 > 255 ? 255 : y1; |
|
|
|
|
|
|
|
dest[destOffset + 2] = y2 > 255 ? 255 : y2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function DeviceCmykCS() { |
|
|
|
|
|
|
|
this.name = 'DeviceCMYK'; |
|
|
|
|
|
|
|
this.numComps = 4; |
|
|
|
|
|
|
|
this.defaultColor = new Float32Array([0, 0, 0, 1]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
DeviceCmykCS.prototype = { |
|
|
|
|
|
|
|
getRgb: function DeviceCmykCS_getRgb(src, srcOffset) { |
|
|
|
|
|
|
|
var rgb = new Uint8Array(3); |
|
|
|
|
|
|
|
convertToRgb(src, srcOffset, 1, rgb, 0); |
|
|
|
|
|
|
|
return rgb; |
|
|
|
}, |
|
|
|
}, |
|
|
|
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(colorBuf, bits) { |
|
|
|
getRgbBuffer: function DeviceCmykCS_getRgbBuffer(src, srcOffset, count, |
|
|
|
|
|
|
|
dest, destOffset, bits) { |
|
|
|
var scale = 1 / ((1 << bits) - 1); |
|
|
|
var scale = 1 / ((1 << bits) - 1); |
|
|
|
var length = colorBuf.length / 4; |
|
|
|
for (var i = 0; i < count; i++) { |
|
|
|
var rgbBuf = new Uint8Array(length * 3); |
|
|
|
convertToRgb(src, srcOffset, scale, dest, destOffset); |
|
|
|
var rgbBufPos = 0; |
|
|
|
srcOffset += 4; |
|
|
|
var colorBufPos = 0; |
|
|
|
destOffset += 3; |
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < length; i++) { |
|
|
|
|
|
|
|
var cmyk = []; |
|
|
|
|
|
|
|
for (var j = 0; j < 4; ++j) |
|
|
|
|
|
|
|
cmyk.push(scale * colorBuf[colorBufPos++]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var rgb = this.getRgb(cmyk); |
|
|
|
|
|
|
|
for (var j = 0; j < 3; ++j) |
|
|
|
|
|
|
|
rgbBuf[rgbBufPos++] = Math.round(rgb[j] * 255); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rgbBuf; |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getOutputLength: function DeviceCmykCS_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
return (inputLength >> 2) * 3; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
isPassthrough: ColorSpace.prototype.isPassthrough, |
|
|
|
|
|
|
|
createRgbBuffer: ColorSpace.prototype.createRgbBuffer, |
|
|
|
isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { |
|
|
|
isDefaultDecode: function DeviceCmykCS_isDefaultDecode(decodeMap) { |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
return ColorSpace.isDefaultDecode(decodeMap, this.numComps); |
|
|
|
} |
|
|
|
} |
|
|
@ -1140,7 +1212,7 @@ var LabCS = (function LabCSClosure() { |
|
|
|
function LabCS(whitePoint, blackPoint, range) { |
|
|
|
function LabCS(whitePoint, blackPoint, range) { |
|
|
|
this.name = 'Lab'; |
|
|
|
this.name = 'Lab'; |
|
|
|
this.numComps = 3; |
|
|
|
this.numComps = 3; |
|
|
|
this.defaultColor = [0, 0, 0]; |
|
|
|
this.defaultColor = new Float32Array([0, 0, 0]); |
|
|
|
|
|
|
|
|
|
|
|
if (!whitePoint) |
|
|
|
if (!whitePoint) |
|
|
|
error('WhitePoint missing - required for color space Lab'); |
|
|
|
error('WhitePoint missing - required for color space Lab'); |
|
|
@ -1188,51 +1260,61 @@ var LabCS = (function LabCSClosure() { |
|
|
|
return (108 / 841) * (x - 4 / 29); |
|
|
|
return (108 / 841) * (x - 4 / 29); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
LabCS.prototype = { |
|
|
|
function convertToRgb(cs, src, srcOffset, dest, destOffset) { |
|
|
|
getRgb: function LabCS_getRgb(color) { |
|
|
|
// Ls,as,bs <---> L*,a*,b* in the spec
|
|
|
|
// Ls,as,bs <---> L*,a*,b* in the spec
|
|
|
|
var Ls = src[srcOffset]; |
|
|
|
var Ls = color[0], as = color[1], bs = color[2]; |
|
|
|
var as = src[srcOffset + 1]; |
|
|
|
|
|
|
|
var bs = src[srcOffset + 2]; |
|
|
|
|
|
|
|
|
|
|
|
// Adjust limits of 'as' and 'bs'
|
|
|
|
// Adjust limits of 'as' and 'bs'
|
|
|
|
as = as > this.amax ? this.amax : as; |
|
|
|
as = as > cs.amax ? cs.amax : as; |
|
|
|
as = as < this.amin ? this.amin : as; |
|
|
|
as = as < cs.amin ? cs.amin : as; |
|
|
|
bs = bs > this.bmax ? this.bmax : bs; |
|
|
|
bs = bs > cs.bmax ? cs.bmax : bs; |
|
|
|
bs = bs < this.bmin ? this.bmin : 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 = this.XW * g(L); |
|
|
|
var X = cs.XW * g(L); |
|
|
|
var Y = this.YW * g(M); |
|
|
|
var Y = cs.YW * g(M); |
|
|
|
var Z = this.ZW * g(N); |
|
|
|
var Z = cs.ZW * g(N); |
|
|
|
|
|
|
|
|
|
|
|
// XYZ to RGB 3x3 matrix, from:
|
|
|
|
// XYZ to RGB 3x3 matrix, from:
|
|
|
|
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
|
|
|
|
// http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC18
|
|
|
|
var XYZtoRGB = [3.240479, -1.537150, -0.498535, |
|
|
|
var XYZtoRGB = [3.240479, -1.537150, -0.498535, |
|
|
|
-0.969256, 1.875992, 0.041556, |
|
|
|
-0.969256, 1.875992, 0.041556, |
|
|
|
0.055648, -0.204043, 1.057311]; |
|
|
|
0.055648, -0.204043, 1.057311]; |
|
|
|
|
|
|
|
|
|
|
|
return Util.apply3dTransform(XYZtoRGB, [X, Y, Z]); |
|
|
|
var rgb = Util.apply3dTransform(XYZtoRGB, [X, Y, Z]); |
|
|
|
}, |
|
|
|
|
|
|
|
getRgbBuffer: function LabCS_getRgbBuffer(input, bits) { |
|
|
|
// clamp color values to [0,255] range
|
|
|
|
if (bits == 8) |
|
|
|
dest[destOffset] = rgb[0] < 0 ? 0 : rgb[0] > 1 ? 255 : rgb[0] * 255; |
|
|
|
return input; |
|
|
|
dest[destOffset + 1] = rgb[1] < 0 ? 0 : rgb[1] > 1 ? 255 : rgb[1] * 255; |
|
|
|
var scale = 255 / ((1 << bits) - 1); |
|
|
|
dest[destOffset + 2] = rgb[2] < 0 ? 0 : rgb[2] > 1 ? 255 : rgb[2] * 255; |
|
|
|
var i, length = input.length / 3; |
|
|
|
} |
|
|
|
var rgbBuf = new Uint8Array(length); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var j = 0; |
|
|
|
LabCS.prototype = { |
|
|
|
for (i = 0; i < length; ++i) { |
|
|
|
getRgb: function LabCS_getRgb(src, srcOffset) { |
|
|
|
// Convert L*, a*, s* into RGB
|
|
|
|
var rgb = new Uint8Array(3); |
|
|
|
var rgb = this.getRgb([input[i], input[i + 1], input[i + 2]]); |
|
|
|
convertToRgb(this, src, srcOffset, rgb, 0); |
|
|
|
rgbBuf[j++] = rgb[0]; |
|
|
|
return rgb; |
|
|
|
rgbBuf[j++] = rgb[1]; |
|
|
|
}, |
|
|
|
rgbBuf[j++] = rgb[2]; |
|
|
|
getRgbBuffer: function LabCS_getRgbBuffer(src, srcOffset, count, |
|
|
|
|
|
|
|
dest, destOffset) { |
|
|
|
|
|
|
|
for (var i = 0; i < count; ++i) { |
|
|
|
|
|
|
|
convertToRgb(this, src, srcOffset, dest, destOffset); |
|
|
|
|
|
|
|
srcOffset += 3; |
|
|
|
|
|
|
|
destOffset += 3; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rgbBuf; |
|
|
|
return rgbBuf; |
|
|
|
}, |
|
|
|
}, |
|
|
|
|
|
|
|
getOutputLength: function LabCS_getOutputLength(inputLength) { |
|
|
|
|
|
|
|
return inputLength; |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
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
|
|
|
|