Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3202)

Unified Diff: chrome/test/data/third_party/kraken/hosted/explanations/darkroom.js

Issue 10070009: Add a copy of the Kraken Benchmark for performance testing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moved to third_party, correct licenses Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/test/data/third_party/kraken/hosted/explanations/darkroom.js
diff --git a/chrome/test/data/third_party/kraken/hosted/explanations/darkroom.js b/chrome/test/data/third_party/kraken/hosted/explanations/darkroom.js
new file mode 100644
index 0000000000000000000000000000000000000000..001c0544bfda573bcdf1bc5eff81dabee0cdc411
--- /dev/null
+++ b/chrome/test/data/third_party/kraken/hosted/explanations/darkroom.js
@@ -0,0 +1,571 @@
+/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40; -*- */
+
+// The if (0) block of function definitions here tries to use
+// faster math primitives, based on being able to reinterpret
+// floats as ints and vice versa. We do that using the
+// WebGL arrays.
+
+if (0) {
+
+var gConversionBuffer = new ArrayBuffer(4);
+var gFloatConversion = new WebGLFloatArray(gConversionBuffer);
+var gIntConversion = new WebGLIntArray(gConversionBuffer);
+
+function AsFloat(i) {
+ gIntConversion[0] = i;
+ return gFloatConversion[0];
+}
+
+function AsInt(f) {
+ gFloatConversion[0] = f;
+ return gIntConversion[0];
+}
+
+// magic constants used for various floating point manipulations
+var kMagicFloatToInt = (1 << 23);
+var kOneAsInt = 0x3F800000;
+var kScaleUp = AsFloat(0x00800000);
+var kScaleDown = 1.0 / kScaleUp;
+
+function ToInt(f) {
+ // force integer part into lower bits of mantissa
+ var i = ReinterpretFloatAsInt(f + kMagicFloatToInt);
+ // return lower bits of mantissa
+ return i & 0x3FFFFF;
+}
+
+function FastLog2(x) {
+ return (AsInt(x) - kOneAsInt) * kScaleDown;
+}
+
+function FastPower(x, p) {
+ return AsFloat(p * AsInt(x) + (1.0 - p) * kOneAsInt);
+}
+
+var LOG2_HALF = FastLog2(0.5);
+
+function FastBias(b, x) {
+ return FastPower(x, FastLog2(b) / LOG2_HALF);
+}
+
+} else {
+
+function FastLog2(x) {
+ return Math.log(x) / Math.LN2;
+}
+
+var LOG2_HALF = FastLog2(0.5);
+
+function FastBias(b, x) {
+ return Math.pow(x, FastLog2(b) / LOG2_HALF);
+}
+
+}
+
+function FastGain(g, x) {
+ return (x < 0.5) ?
+ FastBias(1.0 - g, 2.0 * x) * 0.5 :
+ 1.0 - FastBias(1.0 - g, 2.0 - 2.0 * x) * 0.5;
+}
+
+function Clamp(x) {
+ return (x < 0.0) ? 0.0 : ((x > 1.0) ? 1.0 : x);
+}
+
+function ProcessImageData(imageData, params) {
+ var saturation = params.saturation;
+ var contrast = params.contrast;
+ var brightness = params.brightness;
+ var blackPoint = params.blackPoint;
+ var fill = params.fill;
+ var temperature = params.temperature;
+ var shadowsHue = params.shadowsHue;
+ var shadowsSaturation = params.shadowsSaturation;
+ var highlightsHue = params.highlightsHue;
+ var highlightsSaturation = params.highlightsSaturation;
+ var splitPoint = params.splitPoint;
+
+ var brightness_a, brightness_b;
+ var oo255 = 1.0 / 255.0;
+
+ // do some adjustments
+ fill *= 0.2;
+ brightness = (brightness - 1.0) * 0.75 + 1.0;
+ if (brightness < 1.0) {
+ brightness_a = brightness;
+ brightness_b = 0.0;
+ } else {
+ brightness_b = brightness - 1.0;
+ brightness_a = 1.0 - brightness_b;
+ }
+ contrast = contrast * 0.5;
+ contrast = (contrast - 0.5) * 0.75 + 0.5;
+ temperature = (temperature / 2000.0) * 0.1;
+ if (temperature > 0.0) temperature *= 2.0;
+ splitPoint = ((splitPoint + 1.0) * 0.5);
+
+ // apply to pixels
+ var sz = imageData.width * imageData.height;
+ var data = imageData.data;
+ for (var j = 0; j < sz; j++) {
+ var r = data[j*4+0] * oo255;
+ var g = data[j*4+1] * oo255;
+ var b = data[j*4+2] * oo255;
+ // convert RGB to YIQ
+ // this is a less than ideal colorspace;
+ // HSL would probably be better, but more expensive
+ var y = 0.299 * r + 0.587 * g + 0.114 * b;
+ var i = 0.596 * r - 0.275 * g - 0.321 * b;
+ var q = 0.212 * r - 0.523 * g + 0.311 * b;
+ i = i + temperature;
+ q = q - temperature;
+ i = i * saturation;
+ q = q * saturation;
+ y = (1.0 + blackPoint) * y - blackPoint;
+ y = y + fill;
+ y = y * brightness_a + brightness_b;
+ y = FastGain(contrast, Clamp(y));
+
+ if (y < splitPoint) {
+ q = q + (shadowsHue * shadowsSaturation) * (splitPoint - y);
+ } else {
+ i = i + (highlightsHue * highlightsSaturation) * (y - splitPoint);
+ }
+
+ // convert back to RGB for display
+ r = y + 0.956 * i + 0.621 * q;
+ g = y - 0.272 * i - 0.647 * q;
+ b = y - 1.105 * i + 1.702 * q;
+
+ // clamping is "free" as part of the ImageData object
+ data[j*4+0] = r * 255.0;
+ data[j*4+1] = g * 255.0;
+ data[j*4+2] = b * 255.0;
+ }
+}
+
+//
+// UI code
+//
+
+var gFullCanvas = null;
+var gFullContext = null;
+var gFullImage = null;
+var gDisplayCanvas = null;
+var gDisplayContext = null;
+var gZoomPoint = null;
+var gDisplaySize = null;
+var gZoomSize = [600, 600];
+var gMouseStart = null;
+var gMouseOrig = [0, 0];
+var gDirty = true;
+
+// If true, apply image correction to the original
+// source image before scaling down; if false,
+// scale down first.
+var gCorrectBefore = false;
+
+var gParams = null;
+var gIgnoreChanges = true;
+
+function OnSliderChanged() {
+ if (gIgnoreChanges)
+ return;
+
+ gDirty = true;
+
+ gParams = {};
+
+ // The values will come in as 0.0 .. 1.0; some params want
+ // a different range.
+ var ranges = {
+ "saturation": [0, 2],
+ "contrast": [0, 2],
+ "brightness": [0, 2],
+ "temperature": [-2000, 2000],
+ "splitPoint": [-1, 1]
+ };
+
+ $(".slider").each(function(index, e) {
+ var val = Math.floor($(e).slider("value")) / 1000.0;
+ var id = e.getAttribute("id");
+ if (id in ranges)
+ val = val * (ranges[id][1] - ranges[id][0]) + ranges[id][0];
+ gParams[id] = val;
+ });
+
+ Redisplay();
+}
+
+function ClampZoomPointToTranslation() {
+ var tx = gZoomPoint[0] - gZoomSize[0]/2;
+ var ty = gZoomPoint[1] - gZoomSize[1]/2;
+ tx = Math.max(0, tx);
+ ty = Math.max(0, ty);
+
+ if (tx + gZoomSize[0] > gFullImage.width)
+ tx = gFullImage.width - gZoomSize[0];
+ if (ty + gZoomSize[1] > gFullImage.height)
+ ty = gFullImage.height - gZoomSize[1];
+ return [tx, ty];
+}
+
+function Redisplay() {
+ if (!gParams)
+ return;
+
+ var angle =
+ (gParams.angle*2.0 - 1.0) * 90.0 +
+ (gParams.fineangle*2.0 - 1.0) * 2.0;
+
+ angle = Math.max(-90, Math.min(90, angle));
+ angle = (angle * Math.PI) / 180.0;
+
+ var processTime;
+ var processWidth, processHeight;
+
+ var t0 = (new Date()).getTime();
+
+ // Render the image with rotation; we only need to render
+ // if we're either correcting just the portion that's visible,
+ // or if we're correcting the full thing and the sliders have been
+ // changed. Otherwise, what's in the full canvas is already corrected
+ // and correct.
+ if ((gCorrectBefore && gDirty) ||
+ !gCorrectBefore)
+ {
+ gFullContext.save();
+ gFullContext.translate(Math.floor(gFullImage.width / 2), Math.floor(gFullImage.height / 2));
+ gFullContext.rotate(angle);
+ gFullContext.globalCompositeOperation = "copy";
+ gFullContext.drawImage(gFullImage,
+ -Math.floor(gFullImage.width / 2),
+ -Math.floor(gFullImage.height / 2));
+ gFullContext.restore();
+ }
+
+ function FullToDisplay() {
+ gDisplayContext.save();
+ if (gZoomPoint) {
+ var pt = ClampZoomPointToTranslation();
+
+ gDisplayContext.translate(-pt[0], -pt[1]);
+ } else {
+ gDisplayContext.translate(0, 0);
+ var ratio = gDisplaySize[0] / gFullCanvas.width;
+ gDisplayContext.scale(ratio, ratio);
+ }
+
+ gDisplayContext.globalCompositeOperation = "copy";
+ gDisplayContext.drawImage(gFullCanvas, 0, 0);
+ gDisplayContext.restore();
+ }
+
+ function ProcessCanvas(cx, canvas) {
+ var ts = (new Date()).getTime();
+
+ var data = cx.getImageData(0, 0, canvas.width, canvas.height);
+ ProcessImageData(data, gParams);
+ cx.putImageData(data, 0, 0);
+
+ processWidth = canvas.width;
+ processHeight = canvas.height;
+
+ processTime = (new Date()).getTime() - ts;
+ }
+
+ if (gCorrectBefore) {
+ if (gDirty) {
+ ProcessCanvas(gFullContext, gFullCanvas);
+ } else {
+ processTime = -1;
+ }
+ gDirty = false;
+ FullToDisplay();
+ } else {
+ FullToDisplay();
+ ProcessCanvas(gDisplayContext, gDisplayCanvas);
+ }
+
+ var t3 = (new Date()).getTime();
+
+ if (processTime != -1) {
+ $("#log")[0].innerHTML = "<p>" +
+ "Size: " + processWidth + "x" + processHeight + " (" + (processWidth*processHeight) + " pixels)<br>" +
+ "Process: " + processTime + "ms" + " Total: " + (t3-t0) + "ms<br>" +
+ "Throughput: " + Math.floor((processWidth*processHeight) / (processTime / 1000.0)) + " pixels per second<br>" +
+ "FPS: " + (Math.floor((1000.0 / (t3-t0)) * 100) / 100) + "<br>" +
+ "</p>";
+ } else {
+ $("#log")[0].innerHTML = "<p>(No stats when zoomed and no processing done)</p>";
+ }
+}
+
+function ZoomToPoint(x, y) {
+ if (gZoomSize[0] > gFullImage.width ||
+ gZoomSize[1] > gFullImage.height)
+ return;
+
+ var r = gDisplaySize[0] / gFullCanvas.width;
+
+ gDisplayCanvas.width = gZoomSize[0];
+ gDisplayCanvas.height = gZoomSize[1];
+ gZoomPoint = [x/r, y/r];
+ $("#canvas").removeClass("canzoomin").addClass("cangrab");
+ Redisplay();
+}
+
+function ZoomReset() {
+ gDisplayCanvas.width = gDisplaySize[0];
+ gDisplayCanvas.height = gDisplaySize[1];
+ gZoomPoint = null;
+ $("#canvas").removeClass("canzoomout cangrab isgrabbing").addClass("canzoomin");
+ Redisplay();
+}
+
+function LoadImage(url) {
+ if (!gFullCanvas)
+ gFullCanvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+ if (!gDisplayCanvas)
+ gDisplayCanvas = $("#canvas")[0];
+
+ var img = new Image();
+ img.onload = function() {
+ var w = img.width;
+ var h = img.height;
+
+ gFullImage = img;
+
+ gFullCanvas.width = w;
+ gFullCanvas.height = h;
+ gFullContext = gFullCanvas.getContext("2d");
+
+ // XXX use the actual size of the visible region, so that
+ // we rescale along with the window
+ var dim = 600;
+ if (Math.max(w,h) > dim) {
+ var scale = dim / Math.max(w,h);
+ w *= scale;
+ h *= scale;
+ }
+
+ gDisplayCanvas.width = Math.floor(w);
+ gDisplayCanvas.height = Math.floor(h);
+ gDisplaySize = [ Math.floor(w), Math.floor(h) ];
+ gDisplayContext = gDisplayCanvas.getContext("2d");
+
+ $("#canvas").removeClass("canzoomin canzoomout cangrab isgrabbing");
+
+ if (gZoomSize[0] <= gFullImage.width &&
+ gZoomSize[1] <= gFullImage.height)
+ {
+ $("#canvas").addClass("canzoomin");
+ }
+
+ OnSliderChanged();
+ };
+ //img.src = "foo.jpg";
+ //img.src = "Nina6.jpg";
+ img.src = url ? url : "sunspots.jpg";
+}
+
+function SetupDnD() {
+ $("#imagedisplay").bind({
+ dragenter: function(e) {
+ $("#imagedisplay").addClass("indrag");
+ return false;
+ },
+
+ dragover: function(e) {
+ return false;
+ },
+
+ dragleave: function(e) {
+ $("#imagedisplay").removeClass("indrag");
+ return false;
+ },
+
+ drop: function(e) {
+ e = e.originalEvent;
+ var dt = e.dataTransfer;
+ var files = dt.files;
+
+ if (files.length > 0) {
+ var file = files[0];
+ var reader = new FileReader();
+ reader.onload = function(e) { LoadImage(e.target.result); };
+ reader.readAsDataURL(file);
+ }
+
+ $("#imagedisplay").removeClass("indrag");
+ return false;
+ }
+ });
+}
+
+function SetupZoomClick() {
+ $("#canvas").bind({
+ click: function(e) {
+ if (gZoomPoint)
+ return true;
+
+ var bounds = $("#canvas")[0].getBoundingClientRect();
+ var x = e.clientX - bounds.left;
+ var y = e.clientY - bounds.top;
+
+ ZoomToPoint(x, y);
+ return false;
+ },
+
+ mousedown: function(e) {
+ if (!gZoomPoint)
+ return true;
+
+ $("#canvas").addClass("isgrabbing");
+
+ gMouseOrig[0] = gZoomPoint[0];
+ gMouseOrig[1] = gZoomPoint[1];
+ gMouseStart = [ e.clientX, e.clientY ];
+
+ return false;
+ },
+
+ mouseup: function(e) {
+ if (!gZoomPoint || !gMouseStart)
+ return true;
+ $("#canvas").removeClass("isgrabbing");
+
+ gZoomPoint = ClampZoomPointToTranslation();
+
+ gZoomPoint[0] += gZoomSize[0]/2;
+ gZoomPoint[1] += gZoomSize[1]/2;
+
+ gMouseStart = null;
+ return false;
+ },
+
+ mousemove: function(e) {
+ if (!gZoomPoint || !gMouseStart)
+ return true;
+
+ gZoomPoint[0] = gMouseOrig[0] + (gMouseStart[0] - e.clientX);
+ gZoomPoint[1] = gMouseOrig[1] + (gMouseStart[1] - e.clientY);
+ Redisplay();
+
+ return false;
+ }
+ });
+
+}
+
+function CheckboxToggled(skipRedisplay) {
+ gCorrectBefore = $("#correct_before")[0].checked ? true : false;
+
+ if (!skipRedisplay)
+ Redisplay();
+}
+
+function ResetSliders() {
+ gIgnoreChanges = true;
+
+ $(".slider").each(function(index, e) { $(e).slider("value", 500); });
+ $("#blackPoint").slider("value", 0);
+ $("#fill").slider("value", 0);
+ $("#shadowsSaturation").slider("value", 0);
+ $("#highlightsSaturation").slider("value", 0);
+
+ gIgnoreChanges = false;
+}
+
+function DoReset() {
+ ResetSliders();
+ ZoomReset();
+ OnSliderChanged();
+}
+
+function DoRedisplay() {
+ Redisplay();
+}
+
+// Speed test: run 10 processings, report in thousands-of-pixels-per-second
+function Benchmark() {
+ var times = [];
+
+ var width = gFullCanvas.width;
+ var height = gFullCanvas.height;
+
+ $("#benchmark-status")[0].innerHTML = "Resetting...";
+
+ ResetSliders();
+
+ setTimeout(RunOneTiming, 0);
+
+ function RunOneTiming() {
+
+ $("#benchmark-status")[0].innerHTML = "Running... " + (times.length + 1);
+
+ // reset to original image
+ gFullContext.save();
+ gFullContext.translate(Math.floor(gFullImage.width / 2), Math.floor(gFullImage.height / 2));
+ gFullContext.globalCompositeOperation = "copy";
+ gFullContext.drawImage(gFullImage,
+ -Math.floor(gFullImage.width / 2),
+ -Math.floor(gFullImage.height / 2));
+ gFullContext.restore();
+
+ // time the processing
+ var start = (new Date()).getTime();
+ var data = gFullContext.getImageData(0, 0, width, height);
+ ProcessImageData(data, gParams);
+ gFullContext.putImageData(data, 0, 0);
+ var end = (new Date()).getTime();
+ times.push(end - start);
+
+ if (times.length < 5) {
+ setTimeout(RunOneTiming, 0);
+ } else {
+ displayResults();
+ }
+
+ }
+
+ function displayResults() {
+ var totalTime = times.reduce(function(p, c) { return p + c; });
+ var totalPixels = height * width * times.length;
+ var MPixelsPerSec = totalPixels / totalTime / 1000;
+ $("#benchmark-status")[0].innerHTML = "Complete: " + MPixelsPerSec.toFixed(2) + " megapixels/sec";
+ $("#benchmark-ua")[0].innerHTML = navigator.userAgent;
+ }
+}
+
+function SetBackground(n) {
+ $("body").removeClass("blackbg whitebg graybg");
+
+ switch (n) {
+ case 0: // black
+ $("body").addClass("blackbg");
+ break;
+ case 1: // gray
+ $("body").addClass("graybg");
+ break;
+ case 2: // white
+ $("body").addClass("whitebg");
+ break;
+ }
+}
+
+$(function() {
+ $(".slider").slider({
+ orientation: 'horizontal',
+ range: "min",
+ max: 1000,
+ value: 500,
+ slide: OnSliderChanged,
+ change: OnSliderChanged
+ });
+ ResetSliders();
+ SetupDnD();
+ SetupZoomClick();
+ CheckboxToggled(true);
+ LoadImage();
+ });

Powered by Google App Engine
This is Rietveld 408576698