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

Side by Side Diff: tools/skpdiff/diff_viewer.js

Issue 29103005: update skpdiff visualization (image magnification with alpha mask) (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/skpdiff/SkImageDiffer.h ('k') | tools/skpdiff/skpdiff_main.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 var MAX_SWAP_IMG_SIZE = 400; 1 var MAX_SWAP_IMG_SIZE = 400;
2 var MAGNIFIER_WIDTH = 200;
3 var MAGNIFIER_HEIGHT = 200;
4 var MAGNIFIER_HALF_WIDTH = MAGNIFIER_WIDTH * 0.5;
5 var MAGNIFIER_HALF_HEIGHT = MAGNIFIER_HEIGHT * 0.5;
6 // TODO add support for a magnified scale factor
7 var MAGNIFIER_SCALE_FACTOR = 2.0;
2 8
3 angular.module('diff_viewer', []). 9 angular.module('diff_viewer', []).
4 config(['$routeProvider', function($routeProvider) { 10 directive('imgCompare', function() {
5 // Show the list of differences by default 11 // Custom directive for comparing (3-way) images
6 $routeProvider. 12 return {
7 otherwise({ templateUrl: '/diff_list.html', controller: DiffListController}) ; 13 restrict: 'E', // The directive can be used as an element name
8 }]). 14 replace: true, // The directive replaces itself with the template
9 directive('swapImg', function() { 15 template: '<canvas/>',
10 // Custom directive for showing an image that gets swapped my mouseover. 16 scope: true,
11 return { 17 link: function(scope, elm, attrs, ctrl) {
12 restrict: 'E', // The directive can be used as an element name 18 var image = new Image();
13 replace: true, // The directive replaces itself with the template 19 var canvas = elm[0];
14 template: '<canvas ng-mouseenter="swap()" ng-mouseleave="swap()"></canva s>', 20 var ctx = canvas.getContext('2d');
15 scope: { // The attributes below are bound to the scope
16 leftSrc: '@',
17 rightSrc: '@',
18 side: '@'
19 },
20 link: function(scope, elm, attrs, ctrl) {
21 var leftImage = new Image();
22 var rightImage = new Image();
23 var ctx = elm[0].getContext('2d');
24 21
25 scope.render = function() { 22 var magnifyContent = false;
26 var image;
27 if (scope.side == "left") {
28 image = leftImage;
29 } else {
30 image = rightImage;
31 }
32 23
33 // Make it so the maximum size of an image is MAX_SWAP_IMG_SIZE, and the images are 24 // When the type attribute changes, load the image and then render
34 // scaled down in halves. 25 attrs.$observe('type', function(value) {
35 var divisor = 1; 26 switch(value) {
36 while ((image.width / divisor) > MAX_SWAP_IMG_SIZE) { 27 case "alphaMask":
37 divisor *= 2; 28 image.src = scope.record.differencePath;
38 } 29 break;
30 case "baseline":
31 image.src = scope.record.baselinePath;
32 magnifyContent = true;
33 break;
34 case "test":
35 image.src = scope.record.testPath;
36 magnifyContent = true;
37 break;
38 default:
39 console.log("Unknown type attribute on <img-compare>: " + va lue);
40 return;
41 }
39 42
40 // Set canvas to correct size and draw the image into it 43 image.onload = function() {
41 elm[0].width = image.width / divisor; 44 // compute the scaled image width/height for image and canvas
42 elm[0].height = image.height / divisor; 45 var divisor = 1;
43 ctx.drawImage(image, 0, 0, elm[0].width, elm[0].height); 46 // Make it so the maximum size of an image is MAX_SWAP_IMG_SIZ E,
47 // and the images are scaled down in halves.
48 while ((image.width / divisor) > MAX_SWAP_IMG_SIZE) {
49 divisor *= 2;
50 }
51
52 scope.setImgScaleFactor(1 / divisor);
53
54 // Set canvas to correct size
55 canvas.width = image.width * scope.imgScaleFactor;
56 canvas.height = image.height * scope.imgScaleFactor;
57
58 // render the image onto the canvas
59 scope.renderImage();
60 }
61 });
62
63 // When the magnify attribute changes, render the magnified rect at
64 // the default zoom level.
65 scope.$watch('magnifyCenter', function(magCenter) {
66 if (!magnifyContent) {
67 return;
68 }
69
70 scope.renderImage();
71
72 if (!magCenter) {
73 return;
74 }
75
76 var magX = magCenter.x - MAGNIFIER_HALF_WIDTH;
77 var magY = magCenter.y - MAGNIFIER_HALF_HEIGHT;
78
79 var magMaxX = canvas.width - MAGNIFIER_WIDTH;
80 var magMaxY = canvas.height - MAGNIFIER_HEIGHT;
81
82 var magRect = { x: Math.max(0, Math.min(magX, magMaxX)),
83 y: Math.max(0, Math.min(magY, magMaxY)),
84 width: MAGNIFIER_WIDTH,
85 height: MAGNIFIER_HEIGHT
86 };
87
88 var imgRect = { x: (magCenter.x / scope.imgScaleFactor) - MAGNIFIE R_HALF_WIDTH,
89 y: (magCenter.y / scope.imgScaleFactor) - MAGNIFI ER_HALF_HEIGHT,
90 width: MAGNIFIER_WIDTH,
91 height: MAGNIFIER_HEIGHT
92 };
93
94 // draw the magnified image
95 ctx.clearRect(magRect.x, magRect.y, magRect.width, magRect.height) ;
96 ctx.drawImage(image, imgRect.x, imgRect.y, imgRect.width, imgRect. height,
97 magRect.x, magRect.y, magRect.width, magRect.height) ;
98
99 // draw the outline rect
100 ctx.beginPath();
101 ctx.rect(magRect.x, magRect.y, magRect.width, magRect.height);
102 ctx.lineWidth = 2;
103 ctx.strokeStyle = 'red';
104 ctx.stroke();
105
106 });
107
108 // render the image to the canvas. This is often done every frame prio r
109 // to any special effects (i.e. magnification).
110 scope.renderImage = function() {
111 ctx.clearRect(0, 0, canvas.width, canvas.height);
112 ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
113 };
114
115 // compute a rect (x,y,width,height) that represents the bounding box for
116 // the magnification effect
117 scope.computeMagnifierOutline = function(event) {
118 var scaledWidth = MAGNIFIER_WIDTH * scope.imgScaleFactor;
119 var scaledHeight = MAGNIFIER_HEIGHT * scope.imgScaleFactor;
120 return {
121 x: event.offsetX - (scaledWidth * 0.5),
122 y: event.offsetY - (scaledHeight * 0.5),
123 width: scaledWidth,
124 height: scaledHeight
44 }; 125 };
126 };
45 127
46 // When the leftSrc attribute changes, load the image and then reren der 128 // event handler for mouse events that triggers the magnification
47 attrs.$observe('leftSrc', function(value) { 129 // effect across the 3 images being compared.
48 leftImage.src = value; 130 scope.MagnifyDraw = function(event, startMagnify) {
49 leftImage.onload = function() { 131 if (startMagnify) {
50 if (scope.side == "left") { 132 scope.setMagnifierState(true);
51 scope.render(); 133 } else if (!scope.magnifierOn) {
52 } 134 return;
53 }; 135 }
54 });
55 136
56 // When the rightSrc attribute changes, load the image and then rere nder 137 scope.renderImage();
57 attrs.$observe('rightSrc', function(value) {
58 rightImage.src = value;
59 rightImage.onload = function() {
60 if (scope.side == "right") {
61 scope.render();
62 }
63 };
64 });
65 138
66 // Swap which side to draw onto the canvas and then rerender 139 // render the magnifier outline rect
67 scope.swap = function() { 140 var rect = scope.computeMagnifierOutline(event);
68 if (scope.side == "left") { 141 ctx.save();
69 scope.side = "right"; 142 ctx.beginPath();
70 } else { 143 ctx.rect(rect.x, rect.y, rect.width, rect.height);
71 scope.side = "left"; 144 ctx.lineWidth = 2;
72 } 145 ctx.strokeStyle = 'red';
73 scope.render(); 146 ctx.stroke();
74 }; 147 ctx.restore();
75 } 148
76 }; 149 // update scope on baseline / test that will cause them to render
150 scope.setMagnifyCenter({x: event.offsetX, y: event.offsetY});
151 };
152
153 // event handler that triggers the end of the magnification effect and
154 // resets all the canvases to their original state.
155 scope.MagnifyEnd = function(event) {
156 scope.renderImage();
157 // update scope on baseline / test that will cause them to render
158 scope.setMagnifierState(false);
159 scope.setMagnifyCenter(undefined);
160 };
161 }
162 };
77 }); 163 });
78 164
165 function ImageController($scope, $http, $location, $timeout, $parse) {
166 $scope.imgScaleFactor = 1.0;
167 $scope.magnifierOn = false;
168 $scope.magnifyCenter = undefined;
169
170 $scope.setImgScaleFactor = function(scaleFactor) {
171 $scope.imgScaleFactor = scaleFactor;
172 }
173
174 $scope.setMagnifierState = function(magnifierOn) {
175 $scope.magnifierOn = magnifierOn;
176 }
177
178 $scope.setMagnifyCenter = function(magnifyCenter) {
179 $scope.magnifyCenter = magnifyCenter;
180 }
181 }
182
79 function DiffListController($scope, $http, $location, $timeout, $parse) { 183 function DiffListController($scope, $http, $location, $timeout, $parse) {
80 // Detect if we are running the web server version of the viewer. If so, we set a flag and 184 // Detect if we are running the web server version of the viewer. If so, we set a flag and
81 // enable some extra functionality of the website for rebaselining. 185 // enable some extra functionality of the website for rebaselining.
82 $scope.isDynamic = ($location.protocol() == "http" || $location.protocol() = = "https"); 186 $scope.isDynamic = ($location.protocol() == "http" || $location.protocol() = = "https");
83 187
84 // Label each kind of differ for the sort buttons. 188 // Label each kind of differ for the sort buttons.
85 $scope.differs = [ 189 $scope.differs = [
86 { 190 {
87 "title": "Different Pixels" 191 "title": "Different Pixels"
88 }, 192 },
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 } 267 }
164 $http.post("/commit_rebaselines", { 268 $http.post("/commit_rebaselines", {
165 "rebaselines": rebaselines 269 "rebaselines": rebaselines
166 }).success(function(data) { 270 }).success(function(data) {
167 $scope.flashStatus(data.success); 271 $scope.flashStatus(data.success);
168 }).error(function() { 272 }).error(function() {
169 $scope.flashStatus(false); 273 $scope.flashStatus(false);
170 }); 274 });
171 }; 275 };
172 } 276 }
OLDNEW
« no previous file with comments | « tools/skpdiff/SkImageDiffer.h ('k') | tools/skpdiff/skpdiff_main.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698