| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 cr.define('options', function() { | 5 cr.define('options', function() { |
| 6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; | 6 /** @const */ var ArrayDataModel = cr.ui.ArrayDataModel; |
| 7 /** @const */ var Grid = cr.ui.Grid; | 7 /** @const */ var Grid = cr.ui.Grid; |
| 8 /** @const */ var GridItem = cr.ui.GridItem; | 8 /** @const */ var GridItem = cr.ui.GridItem; |
| 9 /** @const */ var GridSelectionController = cr.ui.GridSelectionController; | 9 /** @const */ var GridSelectionController = cr.ui.GridSelectionController; |
| 10 /** @const */ var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; | 10 /** @const */ var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; |
| 11 | 11 |
| 12 /** | |
| 13 * Number of frames recorded by takeVideo(). | |
| 14 * @const | |
| 15 */ | |
| 16 var RECORD_FRAMES = 48; | |
| 17 | |
| 18 /** | |
| 19 * FPS at which camera stream is recorded. | |
| 20 * @const | |
| 21 */ | |
| 22 var RECORD_FPS = 16; | |
| 23 | |
| 24 /** | 12 /** |
| 25 * Dimensions for camera capture. | 13 * Dimensions for camera capture. |
| 26 * @const | 14 * @const |
| 27 */ | 15 */ |
| 28 var CAPTURE_SIZE = { | 16 var CAPTURE_SIZE = { |
| 29 height: 480, | 17 height: 480, |
| 30 width: 480 | 18 width: 480 |
| 31 }; | 19 }; |
| 32 | 20 |
| 33 /** | 21 /** |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 previewClassList[value == 'default' ? 'add' : 'remove']('default-image'); | 297 previewClassList[value == 'default' ? 'add' : 'remove']('default-image'); |
| 310 previewClassList[value == 'profile' ? 'add' : 'remove']('profile-image'); | 298 previewClassList[value == 'profile' ? 'add' : 'remove']('profile-image'); |
| 311 previewClassList[value == 'camera' ? 'add' : 'remove']('camera'); | 299 previewClassList[value == 'camera' ? 'add' : 'remove']('camera'); |
| 312 | 300 |
| 313 var setFocusIfLost = function() { | 301 var setFocusIfLost = function() { |
| 314 // Set focus to the grid, if focus is not on UI. | 302 // Set focus to the grid, if focus is not on UI. |
| 315 if (!document.activeElement || | 303 if (!document.activeElement || |
| 316 document.activeElement.tagName == 'BODY') { | 304 document.activeElement.tagName == 'BODY') { |
| 317 $('user-image-grid').focus(); | 305 $('user-image-grid').focus(); |
| 318 } | 306 } |
| 319 } | 307 }; |
| 320 // Timeout guarantees processing AFTER style changes display attribute. | 308 // Timeout guarantees processing AFTER style changes display attribute. |
| 321 setTimeout(setFocusIfLost, 0); | 309 setTimeout(setFocusIfLost, 0); |
| 322 }, | 310 }, |
| 323 | 311 |
| 324 /** | 312 /** |
| 325 * Current image captured from camera as data URL. Setting to null will | 313 * Current image captured from camera as data URL. Setting to null will |
| 326 * return to the live camera stream. | 314 * return to the live camera stream. |
| 327 * @type {string=} | 315 * @type {string=} |
| 328 */ | 316 */ |
| 329 get cameraImage() { | 317 get cameraImage() { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 this.cameraImage = previewImg.src; | 472 this.cameraImage = previewImg.src; |
| 485 }.bind(this)); | 473 }.bind(this)); |
| 486 previewImg.src = canvas.toDataURL('image/png'); | 474 previewImg.src = canvas.toDataURL('image/png'); |
| 487 var e = new Event('phototaken'); | 475 var e = new Event('phototaken'); |
| 488 e.dataURL = this.flipPhoto ? this.flipFrame_(canvas) : previewImg.src; | 476 e.dataURL = this.flipPhoto ? this.flipFrame_(canvas) : previewImg.src; |
| 489 this.dispatchEvent(e); | 477 this.dispatchEvent(e); |
| 490 return true; | 478 return true; |
| 491 }, | 479 }, |
| 492 | 480 |
| 493 /** | 481 /** |
| 494 * Performs video capture from the live camera stream. | |
| 495 * @param {function=} opt_callback Callback that receives taken video as | |
| 496 * data URL of a vertically stacked PNG sprite. | |
| 497 */ | |
| 498 takeVideo: function(opt_callback) { | |
| 499 var canvas = document.createElement('canvas'); | |
| 500 canvas.width = CAPTURE_SIZE.width; | |
| 501 canvas.height = CAPTURE_SIZE.height * RECORD_FRAMES; | |
| 502 var ctx = canvas.getContext('2d'); | |
| 503 // Force canvas initialization to prevent FPS lag on the first frame. | |
| 504 ctx.fillRect(0, 0, 1, 1); | |
| 505 var captureData = { | |
| 506 callback: opt_callback, | |
| 507 canvas: canvas, | |
| 508 ctx: ctx, | |
| 509 frameNo: 0, | |
| 510 lastTimestamp: new Date().getTime() | |
| 511 }; | |
| 512 captureData.timer = window.setInterval( | |
| 513 this.captureVideoFrame_.bind(this, captureData), 1000 / RECORD_FPS); | |
| 514 }, | |
| 515 | |
| 516 /** | |
| 517 * Discard current photo and return to the live camera stream. | 482 * Discard current photo and return to the live camera stream. |
| 518 */ | 483 */ |
| 519 discardPhoto: function() { | 484 discardPhoto: function() { |
| 520 this.cameraTitle_ = this.placeholderTitle_; | 485 this.cameraTitle_ = this.placeholderTitle_; |
| 521 this.cameraImage = null; | 486 this.cameraImage = null; |
| 522 }, | 487 }, |
| 523 | 488 |
| 524 /** | 489 /** |
| 525 * Capture a single still frame from a <video> element, placing it at the | 490 * Capture a single still frame from a <video> element, placing it at the |
| 526 * current drawing origin of a canvas context. | 491 * current drawing origin of a canvas context. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 canvas.width = CAPTURE_SIZE.width; | 528 canvas.width = CAPTURE_SIZE.width; |
| 564 canvas.height = CAPTURE_SIZE.height; | 529 canvas.height = CAPTURE_SIZE.height; |
| 565 var ctx = canvas.getContext('2d'); | 530 var ctx = canvas.getContext('2d'); |
| 566 ctx.translate(CAPTURE_SIZE.width, 0); | 531 ctx.translate(CAPTURE_SIZE.width, 0); |
| 567 ctx.scale(-1.0, 1.0); | 532 ctx.scale(-1.0, 1.0); |
| 568 ctx.drawImage(source, 0, 0); | 533 ctx.drawImage(source, 0, 0); |
| 569 return canvas.toDataURL('image/png'); | 534 return canvas.toDataURL('image/png'); |
| 570 }, | 535 }, |
| 571 | 536 |
| 572 /** | 537 /** |
| 573 * Capture next frame of the video being recorded after a takeVideo() call. | |
| 574 * @param {Object} data Property bag with the recorder details. | |
| 575 * @private | |
| 576 */ | |
| 577 captureVideoFrame_: function(data) { | |
| 578 var lastTimestamp = new Date().getTime(); | |
| 579 var delayMs = lastTimestamp - data.lastTimestamp; | |
| 580 console.error('Delay: ' + delayMs + ' (' + (1000 / delayMs + ' FPS)')); | |
| 581 data.lastTimestamp = lastTimestamp; | |
| 582 | |
| 583 this.captureFrame_(this.cameraVideo_, data.ctx, CAPTURE_SIZE); | |
| 584 data.ctx.translate(0, CAPTURE_SIZE.height); | |
| 585 | |
| 586 if (++data.frameNo == RECORD_FRAMES) { | |
| 587 window.clearTimeout(data.timer); | |
| 588 if (data.callback && typeof data.callback == 'function') | |
| 589 data.callback(data.canvas.toDataURL('image/png')); | |
| 590 } | |
| 591 }, | |
| 592 | |
| 593 /** | |
| 594 * Adds new image to the user image grid. | 538 * Adds new image to the user image grid. |
| 595 * @param {string} src Image URL. | 539 * @param {string} src Image URL. |
| 596 * @param {string=} opt_title Image tooltip. | 540 * @param {string=} opt_title Image tooltip. |
| 597 * @param {function=} opt_clickHandler Image click handler. | 541 * @param {function=} opt_clickHandler Image click handler. |
| 598 * @param {number=} opt_position If given, inserts new image into | 542 * @param {number=} opt_position If given, inserts new image into |
| 599 * that position (0-based) in image list. | 543 * that position (0-based) in image list. |
| 600 * @param {function=} opt_decorateFn Function called with the list element | 544 * @param {function=} opt_decorateFn Function called with the list element |
| 601 * as argument to do any final decoration. | 545 * as argument to do any final decoration. |
| 602 * @return {!Object} Image data inserted into the data model. | 546 * @return {!Object} Image data inserted into the data model. |
| 603 */ | 547 */ |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 UserImagesGrid.ButtonImages = { | 638 UserImagesGrid.ButtonImages = { |
| 695 TAKE_PHOTO: 'chrome://theme/IDR_BUTTON_USER_IMAGE_TAKE_PHOTO', | 639 TAKE_PHOTO: 'chrome://theme/IDR_BUTTON_USER_IMAGE_TAKE_PHOTO', |
| 696 CHOOSE_FILE: 'chrome://theme/IDR_BUTTON_USER_IMAGE_CHOOSE_FILE', | 640 CHOOSE_FILE: 'chrome://theme/IDR_BUTTON_USER_IMAGE_CHOOSE_FILE', |
| 697 PROFILE_PICTURE: 'chrome://theme/IDR_PROFILE_PICTURE_LOADING' | 641 PROFILE_PICTURE: 'chrome://theme/IDR_PROFILE_PICTURE_LOADING' |
| 698 }; | 642 }; |
| 699 | 643 |
| 700 return { | 644 return { |
| 701 UserImagesGrid: UserImagesGrid | 645 UserImagesGrid: UserImagesGrid |
| 702 }; | 646 }; |
| 703 }); | 647 }); |
| OLD | NEW |