@eris/image
Advanced tools
Comparing version 0.2.1-alpha.1 to 0.2.1-alpha.2
@@ -581,28 +581,55 @@ "use strict"; | ||
} | ||
const gammaCorrect = (c) => c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); | ||
const dstImageData = Object.assign({}, srcImageData); | ||
const numPixels = srcImageData.width * srcImageData.height; | ||
const rawData = []; | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3; | ||
const rLinear = gammaCorrect(srcImageData.data[offset] / 255); | ||
const gLinear = gammaCorrect(srcImageData.data[offset + 1] / 255); | ||
const bLinear = gammaCorrect(srcImageData.data[offset + 2] / 255); | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
const X = calibrationProfile.xRed * rLinear + | ||
calibrationProfile.xGreen * gLinear + | ||
calibrationProfile.xBlue * bLinear; | ||
const Y = calibrationProfile.yRed * rLinear + | ||
calibrationProfile.yGreen * gLinear + | ||
calibrationProfile.yBlue * bLinear; | ||
const Z = calibrationProfile.zRed * rLinear + | ||
calibrationProfile.zGreen * gLinear + | ||
calibrationProfile.zBlue * bLinear; | ||
rawData[offset + 0] = X; | ||
rawData[offset + 1] = Y; | ||
rawData[offset + 2] = Z; | ||
if (env_1.hasWASM()) { | ||
const { wasmModule } = env_1.getWASM(); | ||
const numberOfElements = numPixels * 3; | ||
const byteSize = numberOfElements * 4; | ||
const pointer = wasmModule.instance.exports.alloc(byteSize); | ||
const rawData = new Float32Array(wasmModule.instance.exports.memory.buffer, pointer, numberOfElements); | ||
for (let i = 0; i < srcImageData.data.length; i++) { | ||
rawData[i] = srcImageData.data[i]; | ||
} | ||
wasmModule.instance.exports.toXYZ(pointer, numPixels, calibrationProfile.xRed, calibrationProfile.xGreen, calibrationProfile.xBlue, calibrationProfile.yRed, calibrationProfile.yGreen, calibrationProfile.yBlue, calibrationProfile.zRed, calibrationProfile.zGreen, calibrationProfile.zBlue); | ||
dstImageData.data = [...rawData]; | ||
wasmModule.instance.exports.dealloc(pointer, byteSize); | ||
} | ||
else { | ||
// While this isn't 100% accurate, it's much, MUCH faster | ||
// See https://www.desmos.com/calculator/scyl4fhjns | ||
// Essentially... | ||
// v <= 0.2 ... y = x * x | ||
// v <= 0.6 ... y = x * x - 0.125 * x + .025 | ||
// v <= 1.0 ... y = x * x + 0.125 * x - .125 | ||
const gammaCorrect = (c) => { | ||
if (c <= 0.2) | ||
return c * c; | ||
if (c <= 0.6) | ||
return c * c - 0.125 * c + 0.025; | ||
return c * c + 0.125 * c - 0.125; | ||
}; | ||
const rawData = []; | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3; | ||
const rLinear = gammaCorrect(srcImageData.data[offset] / 255); | ||
const gLinear = gammaCorrect(srcImageData.data[offset + 1] / 255); | ||
const bLinear = gammaCorrect(srcImageData.data[offset + 2] / 255); | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
const X = calibrationProfile.xRed * rLinear + | ||
calibrationProfile.xGreen * gLinear + | ||
calibrationProfile.xBlue * bLinear; | ||
const Y = calibrationProfile.yRed * rLinear + | ||
calibrationProfile.yGreen * gLinear + | ||
calibrationProfile.yBlue * bLinear; | ||
const Z = calibrationProfile.zRed * rLinear + | ||
calibrationProfile.zGreen * gLinear + | ||
calibrationProfile.zBlue * bLinear; | ||
rawData[offset + 0] = X; | ||
rawData[offset + 1] = Y; | ||
rawData[offset + 2] = Z; | ||
} | ||
dstImageData.data = rawData; | ||
} | ||
dstImageData.colorspace = types_1.Colorspace.XYZ; | ||
dstImageData.channels = 3; | ||
dstImageData.data = rawData; | ||
return dstImageData; | ||
@@ -613,20 +640,49 @@ } | ||
const numPixels = srcImageData.width * srcImageData.height; | ||
const rawData = new Uint8Array(numPixels * 3); | ||
const gammaCorrect = (c) => c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055; | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3; | ||
const x = srcImageData.data[offset]; | ||
const y = srcImageData.data[offset + 1]; | ||
const z = srcImageData.data[offset + 2]; | ||
const rLinear = 3.2406 * x - 1.5372 * y - 0.4986 * z; | ||
const gLinear = -0.9689 * x + 1.8758 * y + 0.0415 * z; | ||
const bLinear = 0.0557 * x - 0.204 * y + 1.057 * z; | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
rawData[offset + 0] = ImageData.clip(gammaCorrect(rLinear) * 255); | ||
rawData[offset + 1] = ImageData.clip(gammaCorrect(gLinear) * 255); | ||
rawData[offset + 2] = ImageData.clip(gammaCorrect(bLinear) * 255); | ||
if (env_1.hasWASM()) { | ||
const { wasmModule } = env_1.getWASM(); | ||
const numberOfElements = numPixels * 3; | ||
const byteSize = numberOfElements * 4; | ||
const pointerIn = wasmModule.instance.exports.alloc(byteSize); | ||
const pointerOut = wasmModule.instance.exports.alloc(numberOfElements); | ||
const rawDataIn = new Float32Array(wasmModule.instance.exports.memory.buffer, pointerIn, numberOfElements); | ||
const rawDataOut = new Uint8Array(wasmModule.instance.exports.memory.buffer, pointerOut, numberOfElements); | ||
for (let i = 0; i < srcImageData.data.length; i++) { | ||
rawDataIn[i] = srcImageData.data[i]; | ||
} | ||
wasmModule.instance.exports.toRGBFromXYZ(pointerIn, pointerOut, numPixels); | ||
dstImageData.data = new Uint8Array(rawDataOut); | ||
wasmModule.instance.exports.dealloc(pointerIn, byteSize); | ||
wasmModule.instance.exports.dealloc(pointerOut, byteSize); | ||
} | ||
else { | ||
const rawData = new Uint8Array(numPixels * 3); | ||
// Reverse our linear combination from before... | ||
// Pluggin in our choke points to reverse the previous functions. | ||
// y <= 0.04 ... y = x * x | ||
// v <= 0.31 ... y = x * x - 0.125 * x + .025 | ||
// v <= 1.00 ... y = x * x + 0.125 * x - .125 | ||
const gammaCorrect = (v) => { | ||
if (v <= 0.04) | ||
return Math.sqrt(v); | ||
if (v <= 0.31) | ||
return (Math.sqrt(6400.0 * v - 135.0) + 5.0) / 80.0; | ||
return (Math.sqrt(256.0 * v + 33.0) - 1.0) / 16.0; | ||
}; | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3; | ||
const x = srcImageData.data[offset]; | ||
const y = srcImageData.data[offset + 1]; | ||
const z = srcImageData.data[offset + 2]; | ||
const rLinear = 3.2406 * x - 1.5372 * y - 0.4986 * z; | ||
const gLinear = -0.9689 * x + 1.8758 * y + 0.0415 * z; | ||
const bLinear = 0.0557 * x - 0.204 * y + 1.057 * z; | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
rawData[offset + 0] = ImageData.clip(gammaCorrect(rLinear) * 255); | ||
rawData[offset + 1] = ImageData.clip(gammaCorrect(gLinear) * 255); | ||
rawData[offset + 2] = ImageData.clip(gammaCorrect(bLinear) * 255); | ||
} | ||
dstImageData.data = rawData; | ||
} | ||
dstImageData.colorspace = types_1.Colorspace.RGB; | ||
dstImageData.channels = 3; | ||
dstImageData.data = rawData; | ||
return dstImageData; | ||
@@ -681,5 +737,6 @@ } | ||
const { wasmModule } = env_1.getWASM(); | ||
const byteSize = numPixels * 3; | ||
const numberOfElements = numPixels * 3; | ||
const byteSize = numberOfElements; | ||
const pointer = wasmModule.instance.exports.alloc(byteSize); | ||
const rawData = new Uint8Array(wasmModule.instance.exports.memory.buffer, pointer, byteSize); | ||
const rawData = new Uint8Array(wasmModule.instance.exports.memory.buffer, pointer, numberOfElements); | ||
for (let i = 0; i < srcImageData.height * srcImageData.width * srcImageData.channels; i++) { | ||
@@ -686,0 +743,0 @@ rawData[i] = srcImageData.data[i]; |
@@ -762,31 +762,77 @@ import { | ||
const gammaCorrect = (c: number) => | ||
c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4) | ||
const dstImageData = {...srcImageData} | ||
const numPixels = srcImageData.width * srcImageData.height | ||
const rawData = [] | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3 | ||
const rLinear = gammaCorrect(srcImageData.data[offset] / 255) | ||
const gLinear = gammaCorrect(srcImageData.data[offset + 1] / 255) | ||
const bLinear = gammaCorrect(srcImageData.data[offset + 2] / 255) | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
const X = | ||
calibrationProfile.xRed * rLinear + | ||
calibrationProfile.xGreen * gLinear + | ||
calibrationProfile.xBlue * bLinear | ||
const Y = | ||
calibrationProfile.yRed * rLinear + | ||
calibrationProfile.yGreen * gLinear + | ||
calibrationProfile.yBlue * bLinear | ||
const Z = | ||
calibrationProfile.zRed * rLinear + | ||
calibrationProfile.zGreen * gLinear + | ||
calibrationProfile.zBlue * bLinear | ||
if (hasWASM()) { | ||
const {wasmModule} = getWASM() | ||
rawData[offset + 0] = X | ||
rawData[offset + 1] = Y | ||
rawData[offset + 2] = Z | ||
const numberOfElements = numPixels * 3 | ||
const byteSize = numberOfElements * 4 | ||
const pointer = wasmModule.instance.exports.alloc(byteSize) | ||
const rawData = new Float32Array( | ||
wasmModule.instance.exports.memory.buffer, | ||
pointer, | ||
numberOfElements, | ||
) | ||
for (let i = 0; i < srcImageData.data.length; i++) { | ||
rawData[i] = srcImageData.data[i] | ||
} | ||
wasmModule.instance.exports.toXYZ( | ||
pointer, | ||
numPixels, | ||
calibrationProfile.xRed, | ||
calibrationProfile.xGreen, | ||
calibrationProfile.xBlue, | ||
calibrationProfile.yRed, | ||
calibrationProfile.yGreen, | ||
calibrationProfile.yBlue, | ||
calibrationProfile.zRed, | ||
calibrationProfile.zGreen, | ||
calibrationProfile.zBlue, | ||
) | ||
dstImageData.data = [...rawData] | ||
wasmModule.instance.exports.dealloc(pointer, byteSize) | ||
} else { | ||
// While this isn't 100% accurate, it's much, MUCH faster | ||
// See https://www.desmos.com/calculator/scyl4fhjns | ||
// Essentially... | ||
// v <= 0.2 ... y = x * x | ||
// v <= 0.6 ... y = x * x - 0.125 * x + .025 | ||
// v <= 1.0 ... y = x * x + 0.125 * x - .125 | ||
const gammaCorrect = (c: number) => { | ||
if (c <= 0.2) return c * c | ||
if (c <= 0.6) return c * c - 0.125 * c + 0.025 | ||
return c * c + 0.125 * c - 0.125 | ||
} | ||
const rawData = [] | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3 | ||
const rLinear = gammaCorrect(srcImageData.data[offset] / 255) | ||
const gLinear = gammaCorrect(srcImageData.data[offset + 1] / 255) | ||
const bLinear = gammaCorrect(srcImageData.data[offset + 2] / 255) | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
const X = | ||
calibrationProfile.xRed * rLinear + | ||
calibrationProfile.xGreen * gLinear + | ||
calibrationProfile.xBlue * bLinear | ||
const Y = | ||
calibrationProfile.yRed * rLinear + | ||
calibrationProfile.yGreen * gLinear + | ||
calibrationProfile.yBlue * bLinear | ||
const Z = | ||
calibrationProfile.zRed * rLinear + | ||
calibrationProfile.zGreen * gLinear + | ||
calibrationProfile.zBlue * bLinear | ||
rawData[offset + 0] = X | ||
rawData[offset + 1] = Y | ||
rawData[offset + 2] = Z | ||
} | ||
dstImageData.data = rawData | ||
} | ||
@@ -796,3 +842,2 @@ | ||
dstImageData.channels = 3 | ||
dstImageData.data = rawData | ||
return dstImageData | ||
@@ -804,20 +849,60 @@ } | ||
const numPixels = srcImageData.width * srcImageData.height | ||
const rawData = new Uint8Array(numPixels * 3) | ||
const gammaCorrect = (c: number) => | ||
c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055 | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3 | ||
const x = srcImageData.data[offset] | ||
const y = srcImageData.data[offset + 1] | ||
const z = srcImageData.data[offset + 2] | ||
if (hasWASM()) { | ||
const {wasmModule} = getWASM() | ||
const rLinear = 3.2406 * x - 1.5372 * y - 0.4986 * z | ||
const gLinear = -0.9689 * x + 1.8758 * y + 0.0415 * z | ||
const bLinear = 0.0557 * x - 0.204 * y + 1.057 * z | ||
const numberOfElements = numPixels * 3 | ||
const byteSize = numberOfElements * 4 | ||
const pointerIn = wasmModule.instance.exports.alloc(byteSize) | ||
const pointerOut = wasmModule.instance.exports.alloc(numberOfElements) | ||
const rawDataIn = new Float32Array( | ||
wasmModule.instance.exports.memory.buffer, | ||
pointerIn, | ||
numberOfElements, | ||
) | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
rawData[offset + 0] = ImageData.clip(gammaCorrect(rLinear) * 255) | ||
rawData[offset + 1] = ImageData.clip(gammaCorrect(gLinear) * 255) | ||
rawData[offset + 2] = ImageData.clip(gammaCorrect(bLinear) * 255) | ||
const rawDataOut = new Uint8Array( | ||
wasmModule.instance.exports.memory.buffer, | ||
pointerOut, | ||
numberOfElements, | ||
) | ||
for (let i = 0; i < srcImageData.data.length; i++) { | ||
rawDataIn[i] = srcImageData.data[i] | ||
} | ||
wasmModule.instance.exports.toRGBFromXYZ(pointerIn, pointerOut, numPixels) | ||
dstImageData.data = new Uint8Array(rawDataOut) | ||
wasmModule.instance.exports.dealloc(pointerIn, byteSize) | ||
wasmModule.instance.exports.dealloc(pointerOut, byteSize) | ||
} else { | ||
const rawData = new Uint8Array(numPixels * 3) | ||
// Reverse our linear combination from before... | ||
// Pluggin in our choke points to reverse the previous functions. | ||
// y <= 0.04 ... y = x * x | ||
// v <= 0.31 ... y = x * x - 0.125 * x + .025 | ||
// v <= 1.00 ... y = x * x + 0.125 * x - .125 | ||
const gammaCorrect = (v: number) => { | ||
if (v <= 0.04) return Math.sqrt(v) | ||
if (v <= 0.31) return (Math.sqrt(6400.0 * v - 135.0) + 5.0) / 80.0 | ||
return (Math.sqrt(256.0 * v + 33.0) - 1.0) / 16.0 | ||
} | ||
for (let i = 0; i < numPixels; i++) { | ||
const offset = i * 3 | ||
const x = srcImageData.data[offset] | ||
const y = srcImageData.data[offset + 1] | ||
const z = srcImageData.data[offset + 2] | ||
const rLinear = 3.2406 * x - 1.5372 * y - 0.4986 * z | ||
const gLinear = -0.9689 * x + 1.8758 * y + 0.0415 * z | ||
const bLinear = 0.0557 * x - 0.204 * y + 1.057 * z | ||
// From https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation | ||
rawData[offset + 0] = ImageData.clip(gammaCorrect(rLinear) * 255) | ||
rawData[offset + 1] = ImageData.clip(gammaCorrect(gLinear) * 255) | ||
rawData[offset + 2] = ImageData.clip(gammaCorrect(bLinear) * 255) | ||
} | ||
dstImageData.data = rawData | ||
} | ||
@@ -827,3 +912,2 @@ | ||
dstImageData.channels = 3 | ||
dstImageData.data = rawData | ||
return dstImageData | ||
@@ -888,5 +972,11 @@ } | ||
const byteSize = numPixels * 3 | ||
const numberOfElements = numPixels * 3 | ||
const byteSize = numberOfElements | ||
const pointer = wasmModule.instance.exports.alloc(byteSize) | ||
const rawData = new Uint8Array(wasmModule.instance.exports.memory.buffer, pointer, byteSize) | ||
const rawData = new Uint8Array( | ||
wasmModule.instance.exports.memory.buffer, | ||
pointer, | ||
numberOfElements, | ||
) | ||
for (let i = 0; i < srcImageData.height * srcImageData.width * srcImageData.channels; i++) { | ||
@@ -893,0 +983,0 @@ rawData[i] = srcImageData.data[i] |
{ | ||
"name": "@eris/image", | ||
"version": "0.2.1-alpha.1", | ||
"version": "0.2.1-alpha.2", | ||
"description": "Collection of image manipulation libraries for node and the browser.", | ||
@@ -38,3 +38,3 @@ "main": "./dist/node-index.js", | ||
"dependencies": { | ||
"@eris/exif": "0.2.1-alpha.1", | ||
"@eris/exif": "0.2.1-alpha.2", | ||
"buffer": "^5.2.0", | ||
@@ -41,0 +41,0 @@ "file-type": "^7.0.1", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1611580
14013
+ Added@eris/exif@0.2.1-alpha.2(transitive)
- Removed@eris/exif@0.2.1-alpha.1(transitive)
Updated@eris/exif@0.2.1-alpha.2