image_util.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. var natives = requireNative('setIcon');
  5. var inServiceWorker = natives.IsInServiceWorker();
  6. // Compute a scaling factor for the image based on the supplied
  7. // image specification.
  8. function computeScaleFactor(imageSpec, img) {
  9. var scaleFactor = 1;
  10. if (imageSpec.width && imageSpec.width < img.width)
  11. scaleFactor = imageSpec.width / img.width;
  12. if (imageSpec.height && imageSpec.height < img.height) {
  13. var heightScale = imageSpec.height / img.height;
  14. if (heightScale < scaleFactor)
  15. scaleFactor = heightScale;
  16. }
  17. return scaleFactor;
  18. }
  19. function loadImageDataForServiceWorker(imageSpec, callbacks) {
  20. var path = imageSpec.path;
  21. let fetchPromise = fetch(path);
  22. let blobPromise = $Promise.then(fetchPromise, (response) => {
  23. if (!response.ok)
  24. throw $Error.self({ problem: 'could_not_load', path: path });
  25. return response.blob();
  26. });
  27. let imagePromise = $Promise.then(blobPromise, (blob) => {
  28. return createImageBitmap(blob);
  29. });
  30. let imageDataPromise = $Promise.then(imagePromise, (image) => {
  31. if (image.width <= 0 || image.height <= 0)
  32. throw $Error.self({ problem: 'image_size_invalid', path: path});
  33. var scaleFactor = computeScaleFactor(imageSpec, image);
  34. var canvas = new OffscreenCanvas(image.width * scaleFactor,
  35. image.height * scaleFactor);
  36. var canvasContext = canvas.getContext('2d');
  37. canvasContext.clearRect(0, 0, canvas.width, canvas.height);
  38. canvasContext.drawImage(image, 0, 0, canvas.width, canvas.height);
  39. try {
  40. var imageData = canvasContext.getImageData(
  41. 0, 0, canvas.width, canvas.height);
  42. if (typeof callbacks.oncomplete === 'function') {
  43. callbacks.oncomplete(
  44. imageData.width, imageData.height, imageData.data.buffer);
  45. }
  46. } catch (e) {
  47. throw $Error.self({ problem: 'data_url_unavailable', path: path });
  48. }
  49. });
  50. $Promise.catch(imageDataPromise, function(error) {
  51. if (typeof callbacks.onerror === 'function')
  52. callbacks.onerror(error);
  53. });
  54. }
  55. // This function takes an object |imageSpec| with the key |path| -
  56. // corresponding to the internet URL to be translated - and optionally
  57. // |width| and |height| which are the maximum dimensions to be used when
  58. // converting the image.
  59. function loadImageDataForNonServiceWorker(imageSpec, callbacks) {
  60. var path = imageSpec.path;
  61. var img = new Image();
  62. if (typeof callbacks.onerror === 'function') {
  63. img.onerror = function() {
  64. callbacks.onerror({ problem: 'could_not_load', path: path });
  65. };
  66. }
  67. img.onload = function() {
  68. var canvas = document.createElement('canvas');
  69. if (img.width <= 0 || img.height <= 0) {
  70. callbacks.onerror({ problem: 'image_size_invalid', path: path});
  71. return;
  72. }
  73. var scaleFactor = computeScaleFactor(imageSpec, img);
  74. canvas.width = img.width * scaleFactor;
  75. canvas.height = img.height * scaleFactor;
  76. var canvas_context = canvas.getContext('2d');
  77. canvas_context.clearRect(0, 0, canvas.width, canvas.height);
  78. canvas_context.drawImage(img, 0, 0, canvas.width, canvas.height);
  79. try {
  80. var imageData = canvas_context.getImageData(
  81. 0, 0, canvas.width, canvas.height);
  82. if (typeof callbacks.oncomplete === 'function') {
  83. callbacks.oncomplete(
  84. imageData.width, imageData.height, imageData.data.buffer);
  85. }
  86. } catch (e) {
  87. if (typeof callbacks.onerror === 'function') {
  88. callbacks.onerror({ problem: 'data_url_unavailable', path: path });
  89. }
  90. }
  91. }
  92. img.src = path;
  93. }
  94. function loadImageData(imageSpec, callbacks) {
  95. if (inServiceWorker) {
  96. loadImageDataForServiceWorker(imageSpec, callbacks);
  97. } else {
  98. loadImageDataForNonServiceWorker(imageSpec, callbacks);
  99. }
  100. }
  101. function on_complete_index(index, err, loading, finished, callbacks) {
  102. return function(width, height, imageData) {
  103. delete loading[index];
  104. finished[index] = { width: width, height: height, data: imageData };
  105. if (err)
  106. callbacks.onerror(index);
  107. if ($Object.keys(loading).length == 0)
  108. callbacks.oncomplete(finished);
  109. }
  110. }
  111. function loadAllImages(imageSpecs, callbacks) {
  112. var loading = {}, finished = [],
  113. index, pathname;
  114. for (var index = 0; index < imageSpecs.length; index++) {
  115. loading[index] = imageSpecs[index];
  116. loadImageData(imageSpecs[index], {
  117. oncomplete: on_complete_index(index, false, loading, finished, callbacks),
  118. onerror: on_complete_index(index, true, loading, finished, callbacks)
  119. });
  120. }
  121. }
  122. exports.$set('loadImageData', loadImageData);
  123. exports.$set('loadAllImages', loadAllImages);