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

Side by Side Diff: chrome/browser/resources/file_manager/js/image_editor/image_util.js

Issue 8769031: More reliable image loading in Photo Editor (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Whitespace Created 9 years 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 5
6 // Namespace object for the utilities. 6 // Namespace object for the utilities.
7 function ImageUtil() {} 7 function ImageUtil() {}
8 8
9 // Performance trace. 9 // Performance trace.
10 ImageUtil.trace = (function() { 10 ImageUtil.trace = (function() {
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 /* 323 /*
324 * ImageLoader loads an image from a given URL into a canvas in two steps: 324 * ImageLoader loads an image from a given URL into a canvas in two steps:
325 * 1. Loads the image into an HTMLImageElement. 325 * 1. Loads the image into an HTMLImageElement.
326 * 2. Copies pixels from HTMLImageElement to HTMLCanvasElement. This is done 326 * 2. Copies pixels from HTMLImageElement to HTMLCanvasElement. This is done
327 * stripe-by-stripe to avoid freezing up the UI. The transform is taken into 327 * stripe-by-stripe to avoid freezing up the UI. The transform is taken into
328 * account. 328 * account.
329 */ 329 */
330 330
331 ImageUtil.ImageLoader = function(document) { 331 ImageUtil.ImageLoader = function(document) {
332 this.document_ = document; 332 this.document_ = document;
333 this.image_ = new Image(); 333 this.image_ = null;
334 }; 334 };
335 335
336 /** 336 /**
337 * @param {string} url 337 * @param {string} url
338 * @param {{scaleX: number, scaleY: number, rotate90: number}} transform 338 * @param {{scaleX: number, scaleY: number, rotate90: number}} transform
339 * @param {function(HTMLCanvasElement} callback 339 * @param {function(HTMLCanvasElement} callback
340 * @param {number} opt_delay Load delay in milliseconds, useful to let the 340 * @param {number} opt_delay Load delay in milliseconds, useful to let the
341 * animations play out before the computation heavy image loading starts. 341 * animations play out before the computation heavy image loading starts.
342 */ 342 */
343 ImageUtil.ImageLoader.prototype.load = function( 343 ImageUtil.ImageLoader.prototype.load = function(
344 url, transform, callback, opt_delay) { 344 url, transform, callback, opt_delay) {
345 this.cancel(); 345 this.cancel();
346 346
347 this.url_ = url; 347 this.url_ = url;
348 this.transform_ = transform || { scaleX: 1, scaleY: 1, rotate90: 0}; 348 this.transform_ = transform || { scaleX: 1, scaleY: 1, rotate90: 0};
349 this.callback_ = callback; 349 this.callback_ = callback;
350 350
351 var self = this; 351 var self = this;
352 function startLoad() { 352 function startLoad() {
353 self.timeout_ = null; 353 self.timeout_ = null;
354 self.image_.onload = self.convertImage_.bind(self); 354 // The clients of this class sometimes request the same url repeatedly.
355 // The onload fires only if the src is different from the previous value.
356 // To work around that we create a new Image every time.
357 self.image_ = new Image();
358 self.image_.onload = function(e) {
359 self.image_ = null;
360 self.convertImage_(e.target);
361 };
355 self.image_.src = url; 362 self.image_.src = url;
356 } 363 }
357 if (opt_delay) { 364 if (opt_delay) {
358 this.timeout_ = setTimeout(startLoad, opt_delay); 365 this.timeout_ = setTimeout(startLoad, opt_delay);
359 } else { 366 } else {
360 startLoad(); 367 startLoad();
361 } 368 }
362 }; 369 };
363 370
364 ImageUtil.ImageLoader.prototype.isBusy = function() { 371 ImageUtil.ImageLoader.prototype.isBusy = function() {
365 return !!this.callback_; 372 return !!this.callback_;
366 }; 373 };
367 374
368 ImageUtil.ImageLoader.prototype.isLoading = function(url) { 375 ImageUtil.ImageLoader.prototype.isLoading = function(url) {
369 return this.isBusy() && (this.url_ == url); 376 return this.isBusy() && (this.url_ == url);
370 }; 377 };
371 378
372 ImageUtil.ImageLoader.prototype.setCallback = function(callback) { 379 ImageUtil.ImageLoader.prototype.setCallback = function(callback) {
373 this.callback_ = callback; 380 this.callback_ = callback;
374 }; 381 };
375 382
376 ImageUtil.ImageLoader.prototype.cancel = function() { 383 ImageUtil.ImageLoader.prototype.cancel = function() {
377 if (!this.callback_) return; 384 if (!this.callback_) return;
378 this.callback_ = null; 385 this.callback_ = null;
379 if (this.timeout_) { 386 if (this.timeout_) {
380 clearTimeout(this.timeout_); 387 clearTimeout(this.timeout_);
381 this.timeout_ = null; 388 this.timeout_ = null;
382 } 389 }
383 this.image_.onload = function(){}; 390 if (this.image_) {
391 this.image_.onload = function(){};
392 this.image_ = null;
393 }
384 }; 394 };
385 395
386 ImageUtil.ImageLoader.prototype.convertImage_ = function() { 396 ImageUtil.ImageLoader.prototype.convertImage_ = function(image) {
387 var canvas = this.document_.createElement('canvas'); 397 var canvas = this.document_.createElement('canvas');
388 398
389 if (this.transform_.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions. 399 if (this.transform_.rotate90 & 1) { // Rotated +/-90deg, swap the dimensions.
390 canvas.width = this.image_.height; 400 canvas.width = image.height;
391 canvas.height = this.image_.width; 401 canvas.height = image.width;
392 } else { 402 } else {
393 canvas.width = this.image_.width; 403 canvas.width = image.width;
394 canvas.height = this.image_.height; 404 canvas.height = image.height;
395 } 405 }
396 406
397 ImageUtil.trace.resetTimer('load-convert'); 407 ImageUtil.trace.resetTimer('load-convert');
398 408
399 var context = canvas.getContext('2d'); 409 var context = canvas.getContext('2d');
400 context.save(); 410 context.save();
401 context.translate(canvas.width / 2, canvas.height / 2); 411 context.translate(canvas.width / 2, canvas.height / 2);
402 context.rotate(this.transform_.rotate90 * Math.PI/2); 412 context.rotate(this.transform_.rotate90 * Math.PI/2);
403 context.scale(this.transform_.scaleX, this.transform_.scaleY); 413 context.scale(this.transform_.scaleX, this.transform_.scaleY);
404 414
405 var stripCount = 415 var stripCount = Math.ceil(image.width * image.height / ( 1 << 21));
406 Math.ceil (this.image_.width * this.image_.height / ( 1 << 21)); 416 var step = Math.max(16, Math.ceil(image.height / stripCount)) & 0xFFFFF0;
407 var step =
408 Math.max(16, Math.ceil(this.image_.height / stripCount)) & 0xFFFFF0;
409 417
410 this.copyStrip_(context, 0, step); 418 this.copyStrip_(context, image, 0, step);
411 }; 419 };
412 420
413 ImageUtil.ImageLoader.prototype.copyStrip_ = function( 421 ImageUtil.ImageLoader.prototype.copyStrip_ = function(
414 context, firstRow, rowCount) { 422 context, image, firstRow, rowCount) {
415 var lastRow = Math.min (firstRow + rowCount, this.image_.height); 423 var lastRow = Math.min (firstRow + rowCount, image.height);
416 424
417 context.drawImage( 425 context.drawImage(
418 this.image_, 0, firstRow, this.image_.width, lastRow - firstRow, 426 image, 0, firstRow, image.width, lastRow - firstRow,
419 -this.image_.width / 2, firstRow - this.image_.height / 2, 427 -image.width / 2, firstRow - image.height / 2,
420 this.image_.width, lastRow - firstRow); 428 image.width, lastRow - firstRow);
421 429
422 if (lastRow == this.image_.height) { 430 if (lastRow == image.height) {
423 context.restore(); 431 context.restore();
424 ImageUtil.trace.reportTimer('load-convert'); 432 ImageUtil.trace.reportTimer('load-convert');
425 var callback = this.callback_; 433 var callback = this.callback_;
426 this.callback_ = null; 434 this.callback_ = null;
427 callback(context.canvas); 435 callback(context.canvas);
428 } else { 436 } else {
429 var self = this; 437 var self = this;
430 this.timeout_ = setTimeout( 438 this.timeout_ = setTimeout(
431 function() { 439 function() {
432 self.timeout_ = null; 440 self.timeout_ = null;
433 self.copyStrip_(context, lastRow, rowCount); 441 self.copyStrip_(context, image, lastRow, rowCount);
434 }, 0); 442 }, 0);
435 } 443 }
436 }; 444 };
437 445
438 ImageUtil.removeChildren = function(element) { 446 ImageUtil.removeChildren = function(element) {
439 element.textContent = ''; 447 element.textContent = '';
440 }; 448 };
441 449
442 ImageUtil.getFullNameFromUrl = function(url) { 450 ImageUtil.getFullNameFromUrl = function(url) {
443 if (url.indexOf('/') != -1) 451 if (url.indexOf('/') != -1)
(...skipping 14 matching lines...) Expand all
458 return ImageUtil.getFileNameFromFullName(ImageUtil.getFullNameFromUrl(url)); 466 return ImageUtil.getFileNameFromFullName(ImageUtil.getFullNameFromUrl(url));
459 }; 467 };
460 468
461 ImageUtil.replaceFileNameInFullName = function(fullName, name) { 469 ImageUtil.replaceFileNameInFullName = function(fullName, name) {
462 var index = fullName.lastIndexOf('.'); 470 var index = fullName.lastIndexOf('.');
463 if (index != -1) 471 if (index != -1)
464 return name + fullName.substr(index); 472 return name + fullName.substr(index);
465 else 473 else
466 return name; 474 return name;
467 }; 475 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698