Skip to content

Commit fbea8ed

Browse files
committed
merging with separate matrices
2 parents 6992169 + d6dba4d commit fbea8ed

File tree

9 files changed

+210
-88
lines changed

9 files changed

+210
-88
lines changed

SeamCarver.js

+80-30
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ class SeamCarver {
2626
// Simple implementation of energy matrix as array of arrays.
2727
// Because we need to remove items, when removing the seam,
2828
// maybe some sort of linked structure is more efficient.
29-
this.energy_matrix = new Array(this.width);
29+
this.energyMatrix = new Array(this.width);
30+
this.minsumMatrix = new Array(this.width);
31+
this.minxMatrix = new Array(this.width);
3032
for (var i = 0; i < this.width; i++) {
31-
this.energy_matrix[i] = new Array(this.height);
33+
this.energyMatrix[i] = new Float32Array(this.height);
34+
this.minsumMatrix[i] = new Float32Array(this.height);
35+
this.minxMatrix[i] = new Uint16Array(this.height);
3236
}
3337

3438
console.time('createEnergyMatrix');
@@ -128,20 +132,20 @@ class SeamCarver {
128132
// last row
129133
if (y >= this.height-1) {
130134
energy_cell.vminsum = energy_cell.energy;
131-
energy_cell.minx = 0;
135+
energy_cell.minx = x;
132136
} else {
133137
var cursum = 0;
134138
var curminx = 0;
135139

136140
// below left
137141
if (x - 1 >= 0) {
138-
energy_cell.vminsum = this.energy_matrix[x - 1][y + 1].vminsum + energy_cell.energy;
142+
energy_cell.vminsum = this.minsumMatrix[x - 1][y + 1] + energy_cell.energy;
139143
energy_cell.minx = x - 1;
140144
}
141145

142146
// below
143147
if (x < this.width) {
144-
cursum = this.energy_matrix[x][y + 1].vminsum + energy_cell.energy;
148+
cursum = this.minsumMatrix[x][y + 1] + energy_cell.energy;
145149
if (cursum < energy_cell.vminsum) {
146150
energy_cell.vminsum = cursum;
147151
energy_cell.minx = x;
@@ -150,7 +154,7 @@ class SeamCarver {
150154

151155
// below right
152156
if (x + 1 < this.width) {
153-
cursum = this.energy_matrix[x + 1][y + 1].vminsum + energy_cell.energy;
157+
cursum = this.minsumMatrix[x + 1][y + 1] + energy_cell.energy;
154158
if (cursum < energy_cell.vminsum) {
155159
energy_cell.vminsum = cursum;
156160
energy_cell.minx = x + 1;
@@ -182,7 +186,9 @@ class SeamCarver {
182186
for (var x = 0; x < this.width; x++) {
183187
var energy = this.recalculate(x,y);
184188
this.maxVminsum = Math.max(energy.vminsum, this.maxVminsum);
185-
this.energy_matrix[x][y] = energy;
189+
this.energyMatrix[x][y] = energy.energy;
190+
this.minsumMatrix[x][y] = energy.vminsum;
191+
this.minxMatrix[x][y] = energy.minx;
186192
}
187193
}
188194
}
@@ -199,8 +205,8 @@ class SeamCarver {
199205

200206
// Find smallest sum on first row
201207
for (var x = 0; x < this.width; x++) {
202-
if (this.energy_matrix[x][0].vminsum < vminsum) {
203-
vminsum = this.energy_matrix[x][0].vminsum;
208+
if (this.minsumMatrix[x][0] < vminsum) {
209+
vminsum = this.minsumMatrix[x][0];
204210
xminsum = x;
205211
}
206212
}
@@ -210,7 +216,7 @@ class SeamCarver {
210216
// Follow down to get array
211217
var y = 0;
212218
while (y < this.height - 1) {
213-
xminsum = this.energy_matrix[xminsum][y].minx
219+
xminsum = this.minxMatrix[xminsum][y]
214220
y++;
215221
vseam[y] = xminsum;
216222
}
@@ -249,13 +255,20 @@ class SeamCarver {
249255
}
250256

251257
// copy across energy_matrix
252-
var val_right = this.energy_matrix[col + 1][row];
253-
val_right.minx--;
254-
this.energy_matrix[col][row] = val_right;
258+
var energy_right = this.energyMatrix[col + 1][row];
259+
var minx_right = this.minxMatrix[col + 1][row];
260+
var minsum_right = this.minsumMatrix[col + 1][row];
261+
minx_right--;
262+
this.energyMatrix[col + 1][row] = energy_right;
263+
this.minxMatrix[col + 1][row] = minx_right;
264+
this.minsumMatrix[col + 1][row] = minsum_right;
255265
}
256266
}
257267

258-
this.energy_matrix.splice(this.width - 1, 1)
268+
// chop off last column
269+
this.energyMatrix.splice(this.width - 1, 1);
270+
this.minxMatrix.splice(this.width - 1, 1);
271+
this.minsumMatrix.splice(this.width - 1, 1);
259272
this.picture = this.imageData.data;
260273
this.width--;
261274
}
@@ -281,9 +294,10 @@ class SeamCarver {
281294
var col = deletedCol + i;
282295

283296
if (this.pixelInRange(col, row)) {
284-
var oldValue = this.energy_matrix[col][row];
285297
var newValue = this.recalculate(col, row);
286-
this.energy_matrix[col][row] = newValue;
298+
this.energyMatrix[col][row] = newValue.energy;
299+
this.minxMatrix[col][row] = newValue.minx;
300+
this.minsumMatrix[col][row] = newValue.vminsum;
287301
// enqueue pixel in range
288302
queue.push(this.pixelToIndex(col, row));
289303
}
@@ -317,23 +331,25 @@ class SeamCarver {
317331

318332
var col = this.indexToX(pixelIndex);
319333
var row = this.indexToY(pixelIndex);
320-
var node = this.energy_matrix[col][row];
321-
var oldVminsum = node.vminsum;
322-
node.vminsum = Number.POSITIVE_INFINITY;
334+
var nodeEnergy = this.energyMatrix[col][row];
335+
var oldVminsum = this.minsumMatrix[col][row];
336+
this.minsumMatrix[col][row] = Number.POSITIVE_INFINITY;
323337

324338
// check three parents in row below
325339
for (var i = Math.max(col - 1, 0); i < Math.min(col + 1, lastCol); i ++) {
326-
var parent = this.energy_matrix[i][row + 1];
327-
var new_vminsum = parent.vminsum + node.energy;
340+
var parentVminsum = this.minsumMatrix[i][row + 1];
341+
var newVminsum = parentVminsum + nodeEnergy;
328342

329343
// TODO: do I always need to update the vminsum for this node?
330-
if (new_vminsum < node.vminsum) {
331-
node.vminsum = new_vminsum;
332-
node.minx = i;
344+
if (newVminsum < this.minsumMatrix[col][row]) {
345+
this.minsumMatrix[col][row] = newVminsum;
346+
// TODO: check i is correct and does not need to be -1, 0, 1
347+
// rather than actual col
348+
this.minxMatrix[col][row] = i;
333349
}
334350
}
335351

336-
if (oldVminsum !== node.vminsum && row > 0) {
352+
if (oldVminsum !== this.minsumMatrix[col][row] && row > 0) {
337353
// TODO: do I need to enqueue all children
338354
// found better path from parent
339355
// so enqueue three affected children from row above
@@ -342,6 +358,17 @@ class SeamCarver {
342358
}
343359
}
344360
}
361+
362+
// now update energy matrix
363+
// for (var row = this.height - 1; row >= 0; row--) {
364+
// for (var col = 0; col < this.width; col++) {
365+
// // TODO recalculate energy only when necessary: pixels adjacent (up, down and both sides) to the removed seam.
366+
// var energy = this.recalculate(col, row);
367+
// this.energyMatrix[col][row] = energy.energy;
368+
// this.minsumMatrix[col][row] = energy.vminsum;
369+
// this.minxMatrix[col][row] = energy.minx;
370+
// }
371+
// }
345372
}
346373

347374
/**
@@ -365,19 +392,32 @@ class SeamCarver {
365392
this.canvas.width = this.imageData.width;
366393
this.canvas.height = this.imageData.height;
367394

395+
this.canvas.style.width = this.imageData.width + 'px';
396+
this.canvas.style.height = this.imageData.height + 'px';
397+
368398
if (field === 'energy' || field === 'vminsum' || (field !== this.imageData.dataField)) {
369399
this.imageData = this.context.createImageData(this.width, this.height);
370400
this.imageData.dataField = field;
371401

372402
for (var row = 0; row < this.height; row ++) {
373403
for (var col = 0; col < this.width; col ++) {
374404
var pos = this.pixelToIndex(col, row);
375-
var val = this.energy_matrix[col][row][field];
376405

377406
if (field === 'energy') {
407+
var val = this.energyMatrix[col][row];
378408
var normalizedVal = Math.min(255, ((val / 255) * 255));
379-
} else if (field === 'vminsum') {
409+
} else if (field === 'minsum') {
410+
var val = this.minsumMatrix[col][row];
380411
var normalizedVal = ((val - 1000) / (this.maxVminsum - 1000)) * 255
412+
} else if (field === 'minx') {
413+
var val = this.minxMatrix[col][row];
414+
var direction = col - val + 1;
415+
for (var i = 0; i < 3; i ++) {
416+
this.imageData.data[pos + i] = 0;
417+
}
418+
if (direction >= 0 && direction <= 2) this.imageData.data[pos + direction] = 255;
419+
this.imageData.data[pos + 3] = 255;
420+
continue;
381421
} else {
382422
// rgb
383423
for (var i = 0; i < 4; i ++) {
@@ -427,12 +467,22 @@ class SeamCarver {
427467
} else {
428468
for (var y = 0; y < this.height; y++) {
429469
for (var x = 0; x < this.width; x++) {
430-
var val = this.energy_matrix[x][y];
431-
if (val && field in val) {
432-
lines += val[field].toFixed(2) + "\t";
470+
var val;
471+
472+
if (field === 'energy') {
473+
val = this.energyMatrix[x][y];
474+
} else if (field === 'minsum') {
475+
val = this.minsumMatrix[x][y];
476+
} else if (field === 'minx') {
477+
val = this.minxMatrix[x][y];
478+
}
479+
480+
if (val) {
481+
lines += val.toFixed(2) + "\t";
433482
} else {
434483
lines += '-----\t';
435484
}
485+
436486
}
437487
lines += '\n';
438488
}

0 commit comments

Comments
 (0)