var createContextBackground = (function() { var canvas = document.createElement("canvas") ,ctx = canvas.getContext('2d') /** @const */ ,WIDTH = canvas.width = 250 /** @const */ ,HEIGHT = canvas.height = 290 /** @const */ ,MARGIN = 20 /** @const */ ,NB_ITEM = 3 /** @const */ ,ITEM_SIZE = (WIDTH -2*MARGIN) / NB_ITEM /** @const */ ,ITEM_SPACING = 0.1 * ITEM_SIZE /** @const */ ,ITEM_INNER_SIZE = Math.floor(ITEM_SIZE -(ITEM_SPACING*2)) /** @const */ ,AVATAR_SIZE = ITEM_INNER_SIZE * 0.5; var drawItem = function(background, avatar, x0, y0) { var y0Index = Math.floor(y0) ,y1Index = Math.floor(y0 + ITEM_SIZE) ,topColor = [ background.data[y0Index *WIDTH *4 +0] ,background.data[y0Index *WIDTH *4 +1] ,background.data[y0Index *WIDTH *4 +2] ] ,botColor = [ background.data[y1Index *WIDTH *4 +0] ,background.data[y1Index *WIDTH *4 +1] ,background.data[y1Index *WIDTH *4 +2] ] ,topGrey = (topColor[0] +topColor[1] +topColor [2]) /3 ,botGrey = (botColor[0] +botColor[1] +botColor [2]) /3 ,targetGrey = Math.floor(Math.random() * Math.abs(topGrey -botGrey) +Math.min(botGrey, topGrey)) ,targetPcent = (targetGrey / topGrey) * 1.2 ,targetColor = (((topColor[0] *targetPcent) << 16) | ((topColor[1] *targetPcent) << 8) | (topColor[2] *targetPcent)).toString(16); ctx.fillStyle = '#' +targetColor; ctx.beginPath(); ctx.moveTo(x0 +ITEM_SIZE /2, y0 +ITEM_SPACING); ctx.lineTo(x0 -ITEM_SPACING +ITEM_SIZE, y0 +ITEM_SIZE /2); ctx.lineTo(x0 +ITEM_SIZE /2, y0 -ITEM_SPACING +ITEM_SIZE); ctx.lineTo(x0 +ITEM_SPACING, y0 +ITEM_SIZE /2); ctx.closePath(); ctx.fill(); ctx.putImageData( blend( ctx.getImageData( x0 +ITEM_SPACING, y0 +ITEM_SPACING, ITEM_INNER_SIZE, ITEM_INNER_SIZE), avatar), x0 +ITEM_SPACING, y0 +ITEM_SPACING); }; var blend = function(img, img2) { var margin = (img.height -img2.height) /2; for (var i =0; i < img2.height; i++) for (var j =0; j < img2.width; j++) { var img2Grey = (img2.data[(i *img2.width +j) *4]) / 255 ,iImg = ((i +margin) *img.width +j +margin) *4; img.data[iImg] *= img2Grey; img.data[iImg +1] *= img2Grey; img.data[iImg +2] *= img2Grey; } return img; } var drawBackground = function() { var grd = ctx.createLinearGradient(0, 0, 0, HEIGHT); grd.addColorStop(0, "#4D394B"); grd.addColorStop(1, "#201820"); ctx.fillStyle = grd; ctx.fillRect(0, 0, WIDTH, HEIGHT); return ctx.getImageData(0, 0, WIDTH, HEIGHT) }; var filterImage = function(img) { var pixelSum = 0; for (var i =0; i < img.width *img.height *4; i +=4) { img.data[i] = img.data[i +1] = img.data[i +2] = (img.data[i] +img.data[i +1] +img.data[i +2]) / 3; img.data[i +3] = 50; pixelSum += img.data[i]; } // Invert colors if image is dark if (pixelSum / (img.height * img.width) < 50) for (var i =0; i < img.width *img.height *4; i +=4) img.data[i] = img.data[i +1] = img.data[i +2] = 255 - img.data[i]; return img; } var loadImgFromUrl = function(src, cb) { var xhr = new XMLHttpRequest(); xhr.responseType = 'blob'; xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if (xhr.response) { var img = new Image(); img.onload = function() { var imgCanvas = document.createElement("canvas"); imgCanvas.height = imgCanvas.width = AVATAR_SIZE; var imgCtx = imgCanvas.getContext('2d'); imgCtx.drawImage(img, 0, 0, AVATAR_SIZE, AVATAR_SIZE); cb(filterImage(imgCtx.getImageData(0, 0, AVATAR_SIZE, AVATAR_SIZE))); }; img.src = window.URL.createObjectURL(/** @type {Blob!} */ (xhr.response)); } else { cb(null); } } }; xhr.open('GET', src, true); xhr.send(null); }; var loadImages = function(userImgs, doneImgLoading) { for (var i =0, nbImgs = userImgs.length; i < nbImgs; i++) { if (userImgs[i].img === undefined) { // Do load image loadImgFromUrl(userImgs[i].src, function(img) { userImgs[i].img = img; loadImages(userImgs, doneImgLoading); }); return; } } var imgs = []; userImgs.forEach(function(i) { if (i.img) imgs.push(i.img); }); doneImgLoading(imgs); }; var renderAvatars = function(background, imgs) { imgs.sort(function(a, b) { return Math.random() - 0.5; }); for (var imgIndex =0, i =MARGIN; i < WIDTH -MARGIN*2; i += ITEM_SIZE) for (var j =0; j +ITEM_SIZE <= HEIGHT; j += ITEM_SIZE) { drawItem(background, imgs[imgIndex], i, j); imgIndex++; if (imgIndex === imgs.length) { imgs.sort(function(a, b) { if (!a.img) return 1; if (!b.img) return -1; return Math.random() - 0.5; }); imgIndex = 0; } } } return function(cb) { var background = drawBackground() ,userImgs = []; for (var userId in SLACK.context.users) { userImgs.push({ src: SLACK.context.users[userId].icons.image_48 }); } loadImages(userImgs, function(imgs) { renderAvatars(background, imgs); cb(canvas.toDataURL()); }); } })();