From df16ce481cf1c8a1aef37133d72f5794c56a5a8b Mon Sep 17 00:00:00 2001 From: Roman Nurik Date: Fri, 26 Jul 2013 11:13:44 -0700 Subject: [PATCH] Under-the-hood improvements to Device Art Generator. Use Canvas.toBlob with a polyfill, to avoid img src with massive data URLs, which causes some browsers to crash Also change the resulting filename to be more appropriate, and make dragging-out to your desktop use this filename. Change-Id: I13d8b4e119af8fecf567ecd6ccf3bb3e7b2d0fae (cherry picked from commit 9da49f160612433e8ba562796ca5d6486ab48d83) --- docs/html/distribute/promote/device-art.jd | 88 +++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 15 deletions(-) diff --git a/docs/html/distribute/promote/device-art.jd b/docs/html/distribute/promote/device-art.jd index 09a39417fe46..76def1ff8fdb 100644 --- a/docs/html/distribute/promote/device-art.jd +++ b/docs/html/distribute/promote/device-art.jd @@ -47,7 +47,9 @@ feature image or screenshots for your Google Play app listing.

-
No input image.
+ +
No input image.
@@ -143,6 +145,8 @@ feature image or screenshots for your Google Play app listing.

// Global variables var g_currentImage; var g_currentDevice; + var g_currentObjectURL; + var g_currentBlob; // Global constants var MSG_INVALID_INPUT_IMAGE = 'Invalid screenshot provided. Screenshots must be PNG files ' @@ -267,14 +271,15 @@ feature image or screenshots for your Google Play app listing.

return; } + polyfillCanvasToBlob(); setupUI(); // Set up Chrome drag-out $.event.props.push("dataTransfer"); document.body.addEventListener('dragstart', function(e) { - var a = e.target; - if (a.classList.contains('dragout')) { - e.dataTransfer.setData('DownloadURL', a.dataset.downloadurl); + var target = e.target; + if (target.classList.contains('dragout')) { + e.dataTransfer.setData('DownloadURL', target.dataset.downloadurl); } }, false); }); @@ -419,7 +424,7 @@ feature image or screenshots for your Google Play app listing.

ctx.translate(-h, 0); ctx.drawImage(g_currentImage, 0, 0); - loadImageFromUri(canvas.toDataURL(), function(img) { + loadImageFromUri(canvas.toDataURL('image/png'), function(img) { g_currentImage = img; createFrame(); }); @@ -459,10 +464,10 @@ feature image or screenshots for your Google Play app listing.

var resourceImages = {}; loadImageResources(resList, function(r) { resourceImages = r; - continuation_(); + continueWithResources_(); }); - function continuation_() { + function continueWithResources_() { var width = resourceImages['back'].naturalWidth; var height = resourceImages['back'].naturalHeight; var offset = port ? g_currentDevice.portOffset : g_currentDevice.landOffset; @@ -486,17 +491,46 @@ feature image or screenshots for your Google Play app listing.

ctx.drawImage(resourceImages['fore'], 0, 0); } - var dataUrl = canvas.toDataURL(); + window.URL = window.URL || window.webkitURL; + if (canvas.toBlob && window.URL.createObjectURL) { + if (g_currentObjectURL) { + window.URL.revokeObjectURL(g_currentObjectURL); + g_currentObjectURL = null; + } + if (g_currentBlob) { + if (g_currentBlob.close) { + g_currentBlob.close(); + } + g_currentBlob = null; + } + + canvas.toBlob(function(blob) { + if (!blob) { + continueWithFinalUrl_(canvas.toDataURL('image/png')); + return; + } + g_currentBlob = blob; + g_currentObjectURL = window.URL.createObjectURL(blob); + continueWithFinalUrl_(g_currentObjectURL); + }, 'image/png'); + } else { + continueWithFinalUrl_(canvas.toDataURL('image/png')); + } + } + + function continueWithFinalUrl_(imageUrl) { var filename = g_currentFilename - ? ('framed_' + g_currentFilename) + ? g_currentFilename.replace(/^(.+?)(\.\w+)?$/, '$1_framed.png') : 'framed_screenshot.png'; var $link = $('') .attr('download', filename) - .attr('href', dataUrl) - .attr('draggable', true) - .attr('data-downloadurl', ['image/png', filename, dataUrl].join(':')) - .append($('').attr('src', dataUrl)) + .attr('href', imageUrl) + .append($('') + .addClass('dragout') + .attr('src', imageUrl) + .attr('draggable', true) + .attr('data-downloadurl', ['image/png', filename, imageUrl].join(':'))) .appendTo($('#output').empty()); $('#frame-customizations').show(); @@ -566,14 +600,14 @@ feature image or screenshots for your Google Play app listing.

var file = null; for (var i = 0; i < fileList.length; i++) { - if (fileList[i].type.toLowerCase().match(/^image\/png/)) { + if (fileList[i].type.toLowerCase().match(/^image\/(png|jpeg|jpg)/)) { file = fileList[i]; break; } } if (!file) { - alert('Please use a valid screenshot file (PNG format).'); + alert('Please use a valid screenshot file (PNG or JPEG format).'); callback(null); return; } @@ -609,4 +643,28 @@ feature image or screenshots for your Google Play app listing.

fileReader.readAsDataURL(file); } + + /** + * Adds a simple version of Canvas.toBlob if toBlob isn't available. + */ + function polyfillCanvasToBlob() { + if (!HTMLCanvasElement.prototype.toBlob && window.Blob) { + HTMLCanvasElement.prototype.toBlob = function(callback, mimeType, quality) { + if (typeof callback != 'function') { + throw new TypeError('Function expected'); + } + var dataURL = this.toDataURL(mimeType, quality); + mimeType = dataURL.split(';')[0].split(':')[1]; + var bs = window.atob(dataURL.split(',')[1]); + if (dataURL == 'data:,' || !bs.length) { + callback(null); + return; + } + for (var ui8arr = new Uint8Array(bs.length), i = 0; i < bs.length; ++i) { + ui8arr[i] = bs.charCodeAt(i); + } + callback(new Blob([ui8arr.buffer /* req'd for Safari */ || ui8arr], {type: mimeType})); + }; + } + } -- 2.11.0