Skip to content
This repository has been archived by the owner on Nov 20, 2018. It is now read-only.

Allow an alternate library to be used to generate resized images #1576

Merged
merged 28 commits into from
Jun 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
54a03d0
feat(scaling): Start of feature to allow alternate scaling code
rnicholus May 25, 2016
d86a600
feat(scaling): Use of custom resize function now available
rnicholus May 27, 2016
02f3675
fix(methods.jmd): Syntax error in docs
rnicholus May 27, 2016
c3f6ee7
fix(methods.jmd): Format of resizeInfo object
rnicholus May 27, 2016
187eb13
fix(methods.jmd): Format of resizeInfo object
rnicholus May 27, 2016
e261c5b
fix(methods.jmd): Format of resizeInfo object
rnicholus May 27, 2016
fcf5925
fix(methods.jmd): Format of resizeInfo object
rnicholus May 27, 2016
70c2ee8
fix(options.jmd): Format of resizeInfo object
rnicholus May 27, 2016
785e7c3
fix(options/methods.jmd): Format of resizeInfo object
rnicholus May 27, 2016
dafd6c8
fix(methods.jmd): Format of resizeInfo object
rnicholus May 27, 2016
0b701b7
docs(async.md): onResizeImage event no longer exists
rnicholus May 27, 2016
a0177cd
feat(megapix-image): Rotate images before custom resize
rnicholus May 31, 2016
e61e360
chore(devenv.js): updates to manual dev testing code
rnicholus Jun 3, 2016
1820564
simpler, faster travis build
Jun 4, 2016
a7060ad
chore(build) only run grunt travis on travis VM
Jun 4, 2016
8d0734d
test(scaling): start of third-party resizer unit tests
Jun 4, 2016
10be8a3
test(scaling): dont run 3rd-party scaling tests on iOS & obey the lint
Jun 4, 2016
62fdc21
test(scaling): completed additional scaling tests
Jun 5, 2016
cbcd591
docs(methods): syntax error in scaleImage docs
Jun 5, 2016
3272d3e
docs(methods): _another_ syntax error in scaleImage docs
Jun 5, 2016
1922a49
docs(methods): bad formatting in scaleImage docs
Jun 5, 2016
00ae62a
docs(methods): bad formatting in scaleImage docs
Jun 5, 2016
9934307
docs(methods): bad formatting in scaleImage docs
Jun 5, 2016
f1290bc
docs(thumbnails & scaling): feature docs for custom reszier
rnicholus Jun 15, 2016
0ffbb27
docs(thumbnails & scaling): broken link
rnicholus Jun 15, 2016
7b7dc56
docs(thumbnails): wrong headline type for 3rd party scaler
rnicholus Jun 15, 2016
f65b938
Merge branch 'develop' into feature/1525-better-scaling
rnicholus Jun 15, 2016
ca22c8e
chore(build): inc build num
rnicholus Jun 15, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
addons:
firefox: "38.0"
firefox: "latest"

sudo: false
language: node_js
Expand All @@ -21,23 +21,13 @@ env:
awR42/q/Akos2eA8NWx5yU+hRC5rr+oQG5Eio0tzi9+y3a6VXDvgS1h2SaQz
TR/MjA/29gFvV7bnp1LSs2TdZx+NGhLd4zHv01XZ+pQk/nQiW9w=

before_install:
- npm install -g grunt-cli
- git submodule update --init --recursive

before_script:
- "sh -e /etc/init.d/xvfb start"

script:
- grunt travis

branches:
only:
- master
- develop
- /^feature.*$/
- /^.*fix.*$/
- /^release.*$/
notifications:
slack:
secure: qb1LdOGlBVKCLxNi86tWrabIKs9TFa3ttpLIwu1vtEeh+R9XDeG32X89sM3a5CHRwLqkHwrs6JNcIC4qhTAKiUOiaPYPbv7PkZXX1GIuOPMBp20ghpnWA7QHv6SpmW4qDCTixZSzf0B0m97muzWm1VnotgRELbfKr9Cf/7h3jS0=
13 changes: 8 additions & 5 deletions client/js/image-support/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ qq.ImageGenerator = function(log) {
maxWidth: maxSize,
maxHeight: maxSize,
orientation: orientation,
mime: mime
mime: mime,
resize: options.customResizeFunction
});
},

Expand All @@ -177,7 +178,8 @@ qq.ImageGenerator = function(log) {
mpImg.render(container, {
maxWidth: maxSize,
maxHeight: maxSize,
mime: mime
mime: mime,
resize: options.customResizeFunction
});
}
);
Expand All @@ -193,7 +195,7 @@ qq.ImageGenerator = function(log) {
return drawPreview;
}

function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize) {
function drawOnCanvasOrImgFromUrl(url, canvasOrImg, draw, maxSize, customResizeFunction) {
var tempImg = new Image(),
tempImgRender = new qq.Promise();

Expand All @@ -213,7 +215,8 @@ qq.ImageGenerator = function(log) {
mpImg.render(canvasOrImg, {
maxWidth: maxSize,
maxHeight: maxSize,
mime: determineMimeOfFileName(url)
mime: determineMimeOfFileName(url),
resize: customResizeFunction
});
},

Expand Down Expand Up @@ -287,7 +290,7 @@ qq.ImageGenerator = function(log) {
*
* @param fileBlobOrUrl a `File`, `Blob`, or a URL pointing to the image
* @param container <img> or <canvas> to contain the preview
* @param options possible properties include `maxSize` (int), `orient` (bool - default true), and `resize` (bool - default true)
* @param options possible properties include `maxSize` (int), `orient` (bool - default true), resize` (bool - default true), and `customResizeFunction`.
* @returns qq.Promise fulfilled when the preview has been drawn, or the attempt has failed
*/
generate: function(fileBlobOrUrl, container, options) {
Expand Down
88 changes: 78 additions & 10 deletions client/js/image-support/megapix-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,19 @@
/**
* Rendering image element (with resizing) and get its data URL
*/
function renderImageToDataURL(img, options, doSquash) {
function renderImageToDataURL(img, blob, options, doSquash) {
var canvas = document.createElement("canvas"),
mime = options.mime || "image/jpeg";
mime = options.mime || "image/jpeg",
promise = new qq.Promise();

renderImageToCanvas(img, canvas, options, doSquash);
return canvas.toDataURL(mime, options.quality || 0.8);
renderImageToCanvas(img, blob, canvas, options, doSquash)
.then(function() {
promise.success(
canvas.toDataURL(mime, options.quality || 0.8)
);
})

return promise;
}

function maybeCalculateDownsampledDimensions(spec) {
Expand All @@ -98,16 +105,31 @@
/**
* Rendering image element (with resizing) into the canvas element
*/
function renderImageToCanvas(img, canvas, options, doSquash) {
function renderImageToCanvas(img, blob, canvas, options, doSquash) {
var iw = img.naturalWidth,
ih = img.naturalHeight,
width = options.width,
height = options.height,
ctx = canvas.getContext("2d"),
promise = new qq.Promise(),
modifiedDimensions;

ctx.save();

if (options.resize) {
return renderImageToCanvasWithCustomResizer({
blob: blob,
canvas: canvas,
image: img,
imageHeight: ih,
imageWidth: iw,
orientation: options.orientation,
resize: options.resize,
targetHeight: height,
targetWidth: width
})
}

if (!qq.supportedFeatures.unlimitedScaledImageSize) {
modifiedDimensions = maybeCalculateDownsampledDimensions({
origWidth: width,
Expand All @@ -117,7 +139,7 @@
if (modifiedDimensions) {
qq.log(qq.format("Had to reduce dimensions due to device limitations from {}w / {}h to {}w / {}h",
width, height, modifiedDimensions.newWidth, modifiedDimensions.newHeight),
"warn");
"warn");

width = modifiedDimensions.newWidth;
height = modifiedDimensions.newHeight;
Expand Down Expand Up @@ -148,7 +170,7 @@
tmpCtx = tmpCanvas.getContext("2d");

while (sy < ih) {
sx = 0,
sx = 0;
dx = 0;
while (sx < iw) {
tmpCtx.clearRect(0, 0, d, d);
Expand All @@ -169,6 +191,49 @@
}

canvas.qqImageRendered && canvas.qqImageRendered();
promise.success();

return promise;
}

function renderImageToCanvasWithCustomResizer(resizeInfo) {
var blob = resizeInfo.blob,
image = resizeInfo.image,
imageHeight = resizeInfo.imageHeight,
imageWidth = resizeInfo.imageWidth,
orientation = resizeInfo.orientation,
promise = new qq.Promise(),
resize = resizeInfo.resize,
sourceCanvas = document.createElement("canvas"),
sourceCanvasContext = sourceCanvas.getContext("2d"),
targetCanvas = resizeInfo.canvas,
targetHeight = resizeInfo.targetHeight,
targetWidth = resizeInfo.targetWidth;

transformCoordinate(sourceCanvas, imageWidth, imageHeight, orientation);

targetCanvas.height = targetHeight;
targetCanvas.width = targetWidth;

sourceCanvasContext.drawImage(image, 0, 0);

resize({
blob: blob,
height: targetHeight,
image: image,
sourceCanvas: sourceCanvas,
targetCanvas: targetCanvas,
width: targetWidth
})
.then(
function success() {
targetCanvas.qqImageRendered && targetCanvas.qqImageRendered();
promise.success();
},
promise.failure
)

return promise;
}

/**
Expand Down Expand Up @@ -315,11 +380,14 @@
if (tagName === "img") {
(function() {
var oldTargetSrc = target.src;
target.src = renderImageToDataURL(self.srcImage, opt, doSquash);
oldTargetSrc === target.src && target.onload();
renderImageToDataURL(self.srcImage, self.blob, opt, doSquash)
.then(function(dataUri) {
target.src = dataUri;
oldTargetSrc === target.src && target.onload();
});
}())
} else if (tagName === "canvas") {
renderImageToCanvas(this.srcImage, target, opt, doSquash);
renderImageToCanvas(this.srcImage, this.blob, target, opt, doSquash);
}
if (typeof this.onrender === "function") {
this.onrender(target);
Expand Down
6 changes: 5 additions & 1 deletion client/js/image-support/scaler.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ qq.Scaler = function(spec, log) {
"use strict";

var self = this,
customResizeFunction = spec.customResizer,
includeOriginal = spec.sendOriginal,
orient = spec.orient,
defaultType = spec.defaultType,
Expand Down Expand Up @@ -51,6 +52,7 @@ qq.Scaler = function(spec, log) {
}),
blob: new qq.BlobProxy(originalBlob,
qq.bind(self._generateScaledImage, self, {
customResizeFunction: customResizeFunction,
maxSize: sizeRecord.maxSize,
orient: orient,
type: outputType,
Expand Down Expand Up @@ -170,6 +172,7 @@ qq.extend(qq.Scaler.prototype, {
name = uploadData && uploadData.name,
uuid = uploadData && uploadData.uuid,
scalingOptions = {
customResizer: specs.customResizer,
sendOriginal: false,
orient: specs.orient,
defaultType: specs.type || null,
Expand Down Expand Up @@ -290,6 +293,7 @@ qq.extend(qq.Scaler.prototype, {
"use strict";

var self = this,
customResizeFunction = spec.customResizeFunction,
log = spec.log,
maxSize = spec.maxSize,
orient = spec.orient,
Expand All @@ -303,7 +307,7 @@ qq.extend(qq.Scaler.prototype, {

log("Attempting to generate scaled version for " + sourceFile.name);

imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient}).then(function() {
imageGenerator.generate(sourceFile, canvas, {maxSize: maxSize, orient: orient, customResizeFunction: customResizeFunction}).then(function() {
var scaledImageDataUri = canvas.toDataURL(type, quality),
signalSuccess = function() {
log("Success generating scaled version for " + sourceFile.name);
Expand Down
18 changes: 10 additions & 8 deletions client/js/templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,10 @@ qq.Templating = function(spec) {
relatedThumbnailId = optFileOrBlob && optFileOrBlob.qqThumbnailId,
thumbnail = getThumbnail(id),
spec = {
customResizeFunction: queuedThumbRequest.customResizeFunction,
maxSize: thumbnailMaxSize,
scale: true,
orient: true
orient: true,
scale: true
};

if (qq.supportedFeatures.imagePreviews) {
Expand Down Expand Up @@ -534,8 +535,9 @@ qq.Templating = function(spec) {
showWaitingImg = queuedThumbRequest.showWaitingImg,
thumbnail = getThumbnail(id),
spec = {
maxSize: thumbnailMaxSize,
scale: serverScale
customResizeFunction: queuedThumbRequest.customResizeFunction,
scale: serverScale,
maxSize: thumbnailMaxSize
};

if (thumbnail) {
Expand Down Expand Up @@ -982,16 +984,16 @@ qq.Templating = function(spec) {
show(getSpinner(id));
},

generatePreview: function(id, optFileOrBlob) {
generatePreview: function(id, optFileOrBlob, customResizeFunction) {
if (!this.isHiddenForever(id)) {
thumbGenerationQueue.push({id: id, optFileOrBlob: optFileOrBlob});
thumbGenerationQueue.push({id: id, customResizeFunction: customResizeFunction, optFileOrBlob: optFileOrBlob});
!thumbnailQueueMonitorRunning && generateNextQueuedPreview();
}
},

updateThumbnail: function(id, thumbnailUrl, showWaitingImg) {
updateThumbnail: function(id, thumbnailUrl, showWaitingImg, customResizeFunction) {
if (!this.isHiddenForever(id)) {
thumbGenerationQueue.push({update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});
thumbGenerationQueue.push({customResizeFunction: customResizeFunction, update: true, id: id, thumbnailUrl: thumbnailUrl, showWaitingImg: showWaitingImg});
!thumbnailQueueMonitorRunning && generateNextQueuedPreview();
}
},
Expand Down
6 changes: 3 additions & 3 deletions client/js/uploader.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,11 +574,11 @@

if (canned) {
this._templating.addFileToCache(id, this._options.formatFileName(name), prependData, dontDisplay);
this._templating.updateThumbnail(id, this._thumbnailUrls[id], true);
this._templating.updateThumbnail(id, this._thumbnailUrls[id], true, this._options.thumbnails.customResizer);
}
else {
this._templating.addFile(id, this._options.formatFileName(name), prependData, dontDisplay);
this._templating.generatePreview(id, this.getFile(id));
this._templating.generatePreview(id, this.getFile(id), this._options.thumbnails.customResizer);
}

this._filesInBatchAddedToUi += 1;
Expand Down Expand Up @@ -696,7 +696,7 @@

// This will replace the "waiting" placeholder with a "preview not available" placeholder
// if called with a null thumbnailUrl.
this._templating.updateThumbnail(fileId, thumbnailUrl);
this._templating.updateThumbnail(fileId, thumbnailUrl, this._options.thumbnails.customResizer);
}
},

Expand Down
7 changes: 4 additions & 3 deletions client/js/uploader.basic.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,15 +163,16 @@
// returning a promise that is fulfilled when the attempt completes.
// Thumbnail can either be based off of a URL for an image returned
// by the server in the upload response, or the associated `Blob`.
drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer) {
drawThumbnail: function(fileId, imgOrCanvas, maxSize, fromServer, customResizeFunction) {
var promiseToReturn = new qq.Promise(),
fileOrUrl, options;

if (this._imageGenerator) {
fileOrUrl = this._thumbnailUrls[fileId];
options = {
scale: maxSize > 0,
maxSize: maxSize > 0 ? maxSize : null
customResizeFunction: customResizeFunction,
maxSize: maxSize > 0 ? maxSize : null,
scale: maxSize > 0
};

// If client-side preview generation is possible
Expand Down
2 changes: 2 additions & 0 deletions client/js/uploader.basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@

// scale images client side, upload a new file for each scaled version
scaling: {
customResizer: null,

// send the original file as well
sendOriginal: true,

Expand Down
1 change: 1 addition & 0 deletions client/js/uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ qq.FineUploader = function(o, namespace) {
},

thumbnails: {
customResizer: null,
maxCount: 0,
placeholders: {
waitUntilResponse: false,
Expand Down
2 changes: 1 addition & 1 deletion client/js/version.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/*global qq */
qq.version = "5.10.0";
qq.version = "5.10.0-2";
Loading