From 93e44c60e7fb0a8bcc80d25e496e5b31358877e6 Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Tue, 28 Feb 2017 14:38:34 +0100 Subject: [PATCH] Generalized to combine RGB channels Somehow related to https://github.com/KhronosGroup/glTF/issues/857 --- .../MetallicRoughnessCreator.html | 67 +++++--- .../scripts/MetallicRoughnessCreator.js | 160 +++++++++++------- MetallicRoughnessCreator/style.css | 13 +- 3 files changed, 150 insertions(+), 90 deletions(-) diff --git a/MetallicRoughnessCreator/MetallicRoughnessCreator.html b/MetallicRoughnessCreator/MetallicRoughnessCreator.html index e92c5c4..b8ead2f 100644 --- a/MetallicRoughnessCreator/MetallicRoughnessCreator.html +++ b/MetallicRoughnessCreator/MetallicRoughnessCreator.html @@ -13,23 +13,30 @@

- - + -
-
- Drop metallic file here
-
-
+
+
+ Drop file for the RED channel here
+
+
-
- Drop roughness file here
-
-
+
+
+ Drop file for GREEN channel here
+
+
+
+
+
+ Drop file for BLUE channel here
+
+
+
Result
Flip vertically
@@ -50,23 +57,33 @@ diff --git a/MetallicRoughnessCreator/scripts/MetallicRoughnessCreator.js b/MetallicRoughnessCreator/scripts/MetallicRoughnessCreator.js index cca544f..0358a1a 100644 --- a/MetallicRoughnessCreator/scripts/MetallicRoughnessCreator.js +++ b/MetallicRoughnessCreator/scripts/MetallicRoughnessCreator.js @@ -1,100 +1,134 @@ -var inputImageDatas = [undefined, undefined]; +var inputImageDatas = [undefined, undefined, undefined]; var outputImageData; +function isUndefined(object) +{ + return (typeof object == "undefined"); +} + +function isDefined(object) +{ + return !isUndefined(object); +} -function combine(metallicImageData, roughnessImageData, outputImageData, flip) +function combine(outputImageData, flip) { - var metallicPixelData = metallicImageData.data; - var roughnessPixelData = roughnessImageData.data; var outputPixelData = outputImageData.data; - var w = outputImageData.width; var h = outputImageData.height; - for (var y = 0; y < h; y++) + + for (var i = 0; i < 3; i++) { - var metallicOffset = y * metallicImageData.width; - var roughnessOffset = y * roughnessImageData.width; - var outputOffset = y * outputImageData.width; - if (flip) + var inputImageData = inputImageDatas[i]; + if (isUndefined(inputImageData)) { - outputOffset = (outputImageData.height - 1 - y) * outputImageData.width + continue; } - for (var x = 0; x < w; x++) + var inputPixelData = inputImageData.data; + for (var y = 0; y < h; y++) { - var metallicIndex = x + metallicOffset; - var red = metallicPixelData[metallicIndex << 2]; - - var roughnessIndex = x + roughnessOffset; - var green = roughnessPixelData[roughnessIndex << 2]; - - var outputIndex = x + outputOffset; - - outputPixelData[(outputIndex << 2) + 0] = red; - outputPixelData[(outputIndex << 2) + 1] = green; - outputPixelData[(outputIndex << 2) + 2] = 0; - outputPixelData[(outputIndex << 2) + 3] = 255; + var inputOffset = y * inputImageData.width; + var outputOffset = y * outputImageData.width; + if (flip) + { + outputOffset = (outputImageData.height - 1 - y) * outputImageData.width + } + for (var x = 0; x < w; x++) + { + var inputIndex = x + inputOffset; + var value = inputPixelData[inputIndex << 2]; + var outputIndex = x + outputOffset; + outputPixelData[(outputIndex << 2) + i] = value; + outputPixelData[(outputIndex << 2) + 3] = 255; + } } } } - -function updateOutput() +function haveEqualSize(imageDataA, imageDataB) { - if (inputImageDatas[0] === undefined) + if (isUndefined(imageDataA)) { - return; + return true; } - if (inputImageDatas[1] === undefined) + if (isUndefined(imageDataB)) { - return; + return true; } - - var infoElement = document.getElementById("outputImageInfo"); - - var metallicImageData = inputImageDatas[0]; - var roughnessImageData = inputImageDatas[1]; - - if (metallicImageData.width != roughnessImageData.width) + return imageDataA.width == imageDataB.width && imageDataA.height == imageDataB.height; +} + + +function checkEqualWidths(nameA, imageDataA, nameB, imageDataB, infoElement) +{ + if (!haveEqualSize(imageDataA, imageDataB)) { - infoElement.innerHTML += - "Warning: Different widths: " + metallicImageData.width + - " and "+ roughnessImageData.width + "
"; + infoElement.innerHTML += + "Warning: Different size: " + + nameA + " is " + imageDataA.width + "x" + imageDataA.height + " and " + + nameB + " is " + imageDataB.width + "x" + imageDataB.height + "
"; } - if (metallicImageData.height != roughnessImageData.height) +} + + +function updateOutput() +{ + var infoElement = document.getElementById("outputImageInfo"); + + infoElement.innerHTML = "" + + var rImageData = inputImageDatas[0]; + var gImageData = inputImageDatas[1]; + var bImageData = inputImageDatas[2]; + + if (isUndefined(rImageData) && + isUndefined(gImageData) && + isUndefined(bImageData)) { - infoElement.innerHTML += - "Warning: Different heights: " + metallicImageData.height + - " and "+ roughnessImageData.height + "
"; + infoElement.innerHTML += + "No input images" + "
"; + return; } - - var width = Math.min(metallicImageData.width, roughnessImageData.width); - var height = Math.min(metallicImageData.height, roughnessImageData.height); - + + checkEqualWidths("r", rImageData, "g", gImageData, infoElement); + checkEqualWidths("g", gImageData, "b", bImageData, infoElement); + checkEqualWidths("r", rImageData, "b", bImageData, infoElement); + + + var width = (1<<16); + if (isDefined(rImageData)) width = Math.min(width, rImageData.width); + if (isDefined(gImageData)) width = Math.min(width, gImageData.width); + if (isDefined(bImageData)) width = Math.min(width, bImageData.width); + + var height = (1<<16); + if (isDefined(rImageData)) height = Math.min(height, rImageData.height); + if (isDefined(gImageData)) height = Math.min(height, gImageData.height); + if (isDefined(bImageData)) height = Math.min(height, bImageData.height); + var canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; var context = canvas.getContext('2d'); outputImageData = context.createImageData(width, height); - + var flip = document.getElementById("flipVerticallyCheckBox").checked; - combine(metallicImageData, roughnessImageData, outputImageData, flip); - - context.putImageData(outputImageData, 0, 0); + combine(outputImageData, flip); + context.putImageData(outputImageData, 0, 0); var typeForm = document.getElementById("typeForm"); - if (typeForm.elements[0].checked) + if (typeForm.elements[0].checked) { var outputImage = document.getElementById("outputImage"); outputImage.src = canvas.toDataURL("image/png"); } - if (typeForm.elements[1].checked) + if (typeForm.elements[1].checked) { var outputImage = document.getElementById("outputImage"); outputImage.src = canvas.toDataURL("image/jpeg", 0.9); } - if (typeForm.elements[2].checked) + if (typeForm.elements[2].checked) { var outputImage = document.getElementById("outputImage"); outputImage.src = canvas.toDataURL("image/jpeg", 0.7); @@ -113,12 +147,12 @@ function imageFileLoaded(event, index, image, infoElement) //updateOutput(); }; fullImage.src = event.target.result; - + image.src = event.target.result; } -function obtainImageData(image) +function obtainImageData(image) { var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); @@ -131,7 +165,7 @@ function obtainImageData(image) }; -function handleFileSelect(event, index, image, infoElement) +function handleFileSelect(event, index, image, infoElement) { event.stopPropagation(); event.preventDefault(); @@ -142,24 +176,24 @@ function handleFileSelect(event, index, image, infoElement) infoElement.innerHTML = "Only a single file is allowed. Dropped "+fileList.length+" files"; return; } - + var file = fileList[0]; - if (!file.type.match('image.*')) + if (!file.type.match('image.*')) { infoElement.innerHTML = "Expected image file, but found "+file.type; return; } var reader = new FileReader(); - reader.onload = function(e) + reader.onload = function(e) { imageFileLoaded(e, index, image, infoElement); }; reader.readAsDataURL(file); - + } -function handleDragOver(event) +function handleDragOver(event) { event.stopPropagation(); event.preventDefault(); diff --git a/MetallicRoughnessCreator/style.css b/MetallicRoughnessCreator/style.css index e2c09f1..a3a6917 100644 --- a/MetallicRoughnessCreator/style.css +++ b/MetallicRoughnessCreator/style.css @@ -3,7 +3,7 @@ html { background-color: white; } -div#metallicDropArea { +div#rDropArea { font-size: 1.5em; width: 100%; min-height: 300px; @@ -12,7 +12,16 @@ div#metallicDropArea { text-align: center; } -div#roughnessDropArea { +div#gDropArea { + font-size: 1.5em; + width: 100%; + min-height: 300px; + border-style: solid; + border-width: 3px; + text-align: center; +} + +div#bDropArea { font-size: 1.5em; width: 100%; min-height: 300px;