As suggested here, I should use canvas renderer so that images can be displayed in nodes. First of all I create a graphClass:
graphClass.g = {
nodes: [],
edges: []
}
Then, I create each node:
graphClass.g.nodes.push({
id: 'n' + data.id,
label: data.username,
x: Math.random(),
y: Math.random(),
size: 20,
type: 'image',
url: data.picture
});
where data.picture is an image URL.
(edges are not relevant here)
And finally, I instantiate Sigma:
s = new sigma({
graph: g,
renderer: {
container: document.getElementById('graph-container'),
type: 'canvas'
},
settings: {
defaultLabelColor: '#fff',
labelColor: '#fff',
enableEdgeHovering: false
}
});
This works as expected, except the images. I can't see them, and black nodes are displayed instead. Any idea of what I am doing wrong?
I've got it. I had to use the example at github
I've just copied this code:
sigma.utils.pkg('sigma.canvas.nodes');
sigma.canvas.nodes.image = (function() {
var _cache = {},
_loading = {},
_callbacks = {};
// Return the renderer itself:
var renderer = function(node, context, settings) {
var args = arguments,
prefix = settings('prefix') || '',
size = node[prefix + 'size'],
color = node.color || settings('defaultNodeColor'),
url = node.url;
if (_cache[url]) {
context.save();
// Draw the clipping disc:
context.beginPath();
context.arc(
node[prefix + 'x'],
node[prefix + 'y'],
node[prefix + 'size'],
0,
Math.PI * 2,
true
);
context.closePath();
context.clip();
// Draw the image
context.drawImage(
_cache[url],
node[prefix + 'x'] - size,
node[prefix + 'y'] - size,
2 * size,
2 * size
);
// Quit the "clipping mode":
context.restore();
// Draw the border:
context.beginPath();
context.arc(
node[prefix + 'x'],
node[prefix + 'y'],
node[prefix + 'size'],
0,
Math.PI * 2,
true
);
context.lineWidth = size / 5;
context.strokeStyle = node.color || settings('defaultNodeColor');
context.stroke();
} else {
sigma.canvas.nodes.image.cache(url);
sigma.canvas.nodes.def.apply(
sigma.canvas.nodes,
args
);
}
};
// Let's add a public method to cache images, to make it possible to
// preload images before the initial rendering:
renderer.cache = function(url, callback) {
if (callback)
_callbacks[url] = callback;
if (_loading[url])
return;
var img = new Image();
img.onload = function() {
_loading[url] = false;
_cache[url] = img;
if (_callbacks[url]) {
_callbacks[url].call(this, img);
delete _callbacks[url];
}
};
_loading[url] = true;
img.src = url;
};
return renderer;
})();
and instantiate sigma like this (caching images):
images.forEach(function(url) {
sigma.canvas.nodes.image.cache(
url,
function() {
if (++loaded === images.length) {
s = new sigma({
graph: g,
renderer: {
// IMPORTANT:
// This works only with the canvas renderer, so the
// renderer type set as "canvas" is necessary here.
container: document.getElementById('graph-container'),
type: 'canvas'
},
settings: {
maxNodeSize: 20,
defaultLabelColor: '#fff',
labelColor: '#fff',
enableEdgeHovering: false
}
});
}
}
);
});
And images are now displayed on nodes.
Related
If I try to print a Large Pdf in IE 11, the printed output doesn't contain all the pages. In a few page cross icons are coming. I have reduced the resolution of the file at the time of printing but still, I am not able to Print it properly. Can someone point to me what I can do to solve this issue? Thanks
My Viewer Code for printing
function renderPage(activeServiceOnEntry, pdfDocument, pageNumber, size) {
var scratchCanvas = activeService.scratchCanvas;
var PRINT_RESOLUTION = _app_options.AppOptions.get('printResolution') || 150;
var PRINT_UNITS = PRINT_RESOLUTION / 72.0;
scratchCanvas.width = Math.floor(size.width * PRINT_UNITS);
scratchCanvas.height = Math.floor(size.height * PRINT_UNITS);
var width = Math.floor(size.width * _ui_utils.CSS_UNITS) + 'px';
var height = Math.floor(size.height * _ui_utils.CSS_UNITS) + 'px';
var ctx = scratchCanvas.getContext('2d');
ctx.save();
ctx.fillStyle = 'rgb(255, 255, 255)';
ctx.fillRect(0, 0, scratchCanvas.width, scratchCanvas.height);
ctx.restore();
return pdfDocument.getPage(pageNumber).then(function (pdfPage) {
var renderContext = {
canvasContext: ctx,
transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
viewport: pdfPage.getViewport({
scale: 1,
rotation: size.rotation
}),
intent: 'print'
};
return pdfPage.render(renderContext).promise;
}).then(function () {
return {
width: width,
height: height
};
});
}
Attempting to create a custom class that will display an image on the top left corner of a Fabric rectangle.
Extending the fabric class and calling ctx.drawImage isn't displaying anything.
var CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'labeledRect',
initialize: function(options) {
options || (options = { });
const image = new Image();
image.src = signBtn;
this.callSuper('initialize', options);
this.set('label', options.label || '');
this.set('image', image);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.get('label')
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
ctx.drawImage(this.image, this.left+10, this.top-5, 15, 15);
}
});
fillText is working fine and displaying the label properly.
Tried a few different things thinking the image isn't loaded. It's imported as an SVG. I've gotten it to display in other ways but prefer to have a custom class handle this instead of event handlers.
You need to set image after load. You can use image.onload event callback, or use fabric.util.loadImage
DEMO
fabric.CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'customRect',
initialize: function(options) {
options || (options = { });
var that = this;
this.imageLoaded = false;
fabric.util.loadImage(options.signBtn,function(img){
that.set('image', img);
that.imageLoaded = true;
that.dirty = true;
//if canvas is global
canvas.renderAll();
},{
crossOrigin : 'annonymous'
});
this.callSuper('initialize', options);
this.set('label', options.label || '');
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.label,
image : this.image
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
this.imageLoaded && ctx.drawImage(this.image, 10, -5, 15, 15);
}
});
fabric.CustomRect.fromObject = function(object, callback) {
return fabric.Object._fromObject('CustomRect', object, callback);
};
var url = 'https://upload.wikimedia.org/wikipedia/en/8/80/Wikipedia-logo-v2.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.CustomRect({
signBtn: url,
left : 10,
top : 10,
width : 200,
height: 200,
fill: 'green',
label : 'test'
});
canvas.add(rect);
function loadfromjson() {
var json = canvas.toJSON();
canvas.clear();
setTimeout(function() {
canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
}, 1000)
}
canvas{
border:2px solid #000;
}
<script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>
<canvas id="canvas" width="300" height="300"></canvas>
<button onclick="loadfromjson()">loadfromjson </button>
I believe there are some missing values like this.width and this.height?
In addition to that, you have to wait until the image is loaded to draw it. You can do something like this:
var CustomRect = fabric.util.createClass(fabric.Rect, {
type: 'labeledRect',
initialize: function(options) {
options || (options = { });
const image = new Image();
image.src = 'https://i.stack.imgur.com/CYp8Y.jpg';
this.callSuper('initialize', options);
image.onload = (function() {
this.width = image.width;
this.height = image.height;
this.image_loaded = true;
}).bind(this);
this.set('label', options.label || '');
this.set('image', image);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
label: this.get('label')
});
},
_render: function(ctx) {
if (this.image_loaded) {
this.callSuper('_render', ctx);
console.log(-this.width / 2, -this.height / 2);
ctx.font = '20px Helvetica';
ctx.fillStyle = '#333';
ctx.fillText(this.label, -this.width/2, -this.height/2 + 20);
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
}
}
});
Note these two changes:
image.onload = (function() {
this.width = image.width;
this.height = image.height;
this.image_loaded = true;
}).bind(this);
I set the image_loaded to true inside the initialize method once the image is loaded. Then in the _render method I check if the image is loaded, and then draw it.
if(this.loaded){
//............
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
}
Here's a fiddle: https://jsfiddle.net/nimeshka/enL61g0w/55/
You might need to click on the canvas to trigger the render event. Otherwise you won't see the rectangle in the output box. (I haven't added it)
Hope it helps :)
Below is provided a script for changing image on click, changes will be affected in canvas.
The script is working properly in Firefox and Chrome but not in Safari
What could be the reason?
<script>
$(function() {
var house = document.getElementById("house");
var ctxHouse = house.getContext("2d");
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctxHand = canvas2.getContext("2d");
var FabricLink;
var imageObj = new Image();
var red = new Image();
red.onload = function() {
canvas.width = red.width;
canvas.height = red.height;
var houseImage = new Image();
houseImage.onload = function() {
house.width = houseImage.width;
house.height = houseImage.height;
ctxHouse.drawImage(houseImage, 0, 0);
}
houseImage.src = "images/img.jpg";
ctx.drawImage(red, 0, 0);
imageObj.onload = function() {
var pattern = ctx.createPattern(imageObj, 'repeat');
ctx.globalCompositeOperation = 'source-in';
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = pattern;
ctx.fill();
};
$(imageObj).attr('src', 'images/' + FabricLink + '.png');
}
red.src = "images/img.png";
var imageObj2 = new Image();
var blue = new Image();
blue.onload = function() {
canvas2.width = blue.width;
canvas2.height = blue.height;
var houseImage = new Image();
houseImage.onload = function() {
house.width = houseImage.width;
house.height = houseImage.height;
ctxHouse.drawImage(houseImage, 0, 0);
}
houseImage.src = "images/img.jpg";
ctxHand.drawImage(blue, 0, 0);
imageObj2.onload = function() {
var pattern = ctx.createPattern(imageObj2, 'repeat');
ctxHand.globalCompositeOperation = 'source-in';
ctxHand.rect(0, 0, canvas2.width, canvas2.height);
ctxHand.fillStyle = pattern;
ctxHand.fill();
};
$(imageObj2).attr('src', 'images/' + FabricLink + '.png');
}
blue.src = "images/img.png";
$('#style li').click(
function() {
//we get our current filename and use it for the src
var linkIndex = $(this).attr("data-filename");
$(red).attr('src', 'images/' + linkIndex + '.png');
}
);
$('#Sleeves li').click(
function() {
$("#canvas2").addClass("show-z");
//we get our current filename and use it for the src
var SleevesLink = $(this).attr("data-filename");
$(blue).attr('src', 'images/' + SleevesLink + '.png');
}
);
$('#Fabric li').click(
function() {
//we get our current filename and use it for the src
FabricLink = $(this).attr("data-filename");
$(imageObj2).attr('src', 'images/' + FabricLink + '.png');
$(imageObj).attr('src', 'images/' + FabricLink + '.png');
}
);
$("#Fabric li:first-child").click();
}); // end $(function(){});
</script>
While debugging, we could see that imageObj.onload is not getting fired in the first click , only on refresh the change occurs in Safari.
jsfiddle.net/qvfx3kz7 (In the fiddle images are not loading, but the complete code is added)
I am not sure what is exactly the problem with Safari, but what I can see is that you are over-complicating everything by trying to load your assets only when requested, which leads to this callback nightmare you have set up.
Instead, prepare your assets so that you can load it only once. Since you are using patterns, I will assume that each pattern is actually a small image.
So instead of loading every little pattern images, load a single sprite-sheet, which will contain all your patterns.
From there, you'll be able to generate dynamically your CanvasPattern synchronously, without having to care for any loading callback. In order to do this, you will have to use a second, off-screen, canvas, that you will use as he source of createPattern() method:
// really dummy implementation...
function AssetsLoader() {}
AssetsLoader.prototype = Object.create({
addImage: function(objs, cb) {
if (!objs || typeof objs !== 'object') return;
if (!Array.isArray(objs)) objs = [];
var toLoad = objs.length,
imgs = objs.map(loadImage, this);
function loadImage(obj) {
if (!obj.src) return;
this.toLoad++;
var img = new Image();
img.src = obj.src;
img.onload = onimgload;
img.onerror = onimgerror;
return obj.img = img;
}
function onimgload(evt) {
if (--toLoad <= 0 && typeof cb === 'function') cb(imgs);
}
function onimgerror(evt) {
console.warn('failed to load image at ', evt.target.src);
}
}
});
// Some info about our assets, there are an infinity of ways to deal with it,
// You would have to determine yourself what's best for your own case
var dests = {
sofa: {
name: 'sofa',
src: 'https://i.stack.imgur.com/ryO42.png'
},
shirt: {
name: 'shirt',
src: 'https://i.stack.imgur.com/cPNbe.png'
}
};
var patterns = {
name: 'patterns',
src: 'https://i.stack.imgur.com/TdIAJ.png',
positions: {
orange: {
x: 0,
y: 0,
width: 173,
height: 173,
out_width: 75,
out_height: 75
},
violet: {
x: 173,
y: 0,
width: 173,
height: 173,
out_width: 35,
out_height: 35
},
psyche: {
x: 0,
y: 173,
width: 173,
height: 173,
out_width: 25,
out_height: 25
},
pink: {
x: 173,
y: 173,
width: 173,
height: 173,
out_width: 125,
out_height: 125
}
}
}
var assets = new AssetsLoader();
// first load all our images, and only then, start the whole thing
assets.addImage([dests.shirt, dests.sofa, patterns], init);
function init() {
// populate our selects
for (var key in dests) {
dest_select.appendChild(new Option(key, key));
}
for (var key in patterns.positions) {
pat_select.appendChild(new Option(key, key));
}
dest_select.onchange = pat_select.onchange = draw;
var ctx = canvas.getContext('2d');
var offscreenCtx = document.createElement('canvas').getContext('2d');
draw();
function draw() {
var dest = dests[dest_select.value].img;
ctx.canvas.width = dest.width;
ctx.canvas.height = dest.height;
ctx.globalCompositeOperation = 'source-over';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(dest, 0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'source-in';
// here we generate the CanvasPattern
ctx.fillStyle = getPattern(pat_select.value);
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'luminosity';
ctx.drawImage(dest, 0, 0, canvas.width, canvas.height);
}
// now that we have our patterns loaded in a single sprite-sheet,
// we can generate the CanvasPatterns synchronously
function getPattern(key) {
var pos = patterns.positions[key]; // get our pattern's position in our dictionary
// resize the offscreen canvas so it matches our pattern
offscreenCtx.canvas.width = pos.out_width;
offscreenCtx.canvas.height = pos.out_height;
offscreenCtx.drawImage(patterns.img, pos.x, pos.y, pos.width, pos.height, 0, 0, pos.out_width, pos.out_height);
return offscreenCtx.createPattern(offscreenCtx.canvas, 'repeat');
}
}
<select id="dest_select"></select>
<select id="pat_select"></select>
<br><br><br>
<canvas id="canvas"></canvas>
This the code that I use for the base64 conversation on the local browser
var render_width = chart.plotWidth;
var render_height = render_width * chart.chartHeight / chart.chartWidth;
// Get the chart's SVG code
var svg = chart.getSVG({
exporting: {
sourceWidth: chart.chartWidth,
sourceHeight: chart.chartHeight
}
});
// Create a canvas
var canvas = document.createElement('canvas');
canvas.id = "render";
canvas.height = render_height;
canvas.width = render_width;
//canvas.setAttribute('crossOrigin', 'anonymous');
//canvas.style = "display:hidden";
document.body.appendChild(canvas);
var dogImage = new Image;
//dogImage.setAttribute('crossOrigin', 'anonymous');
dogImage.onload = function() {
if (chart.plotWidth < chart.plotHeight) {
plot = chart.plotWidth;
} else {
plot = chart.plotHeight;
}
f = 0.65;
var imageHeight = plot * f;
var imageWidth = plot * f;
var textX = (chart.plotLeft + (chart.plotWidth * 0.5)) - (imageHeight / 2);
var textY = (chart.plotTop + (chart.plotHeight * 0.5)) - (imageWidth / 2);
canvas.getContext('2d').drawImage(this, textX, textY, imageWidth, imageHeight);
// Create an image and draw the SVG onto the canvas
var image = new Image;
//image.setAttribute('crossOrigin', 'anonymous');
image.onload = function() {
canvas.getContext('2d').drawImage(this, chart.plotLeft, 0, render_width, render_height);
var d = canvas.toDataURL("image/png");
//var w=window.open('about:blank','image from canvas');
var data = {
chart_image: d,
animal_id: animal_id
};
asyncRequest.postData(url, data, function(data) {
//console.log(data);
$("#loading-modal").addClass('display-none');
location.href = data.file_path;
});
//$('body').append("<img src='"+d+"' alt='from canvas'/>");
document.body.removeChild(canvas);
};
image.src = 'data:image/svg+xml;base64,' + window.btoa(svg);
};
dogImage.src = center_image;
This is working only if the allowHTMl is false inside the high charts options
exporting: {
// allowHTML: true,
buttons: {
exportButton: {
enabled: false
},
printButton: {
enabled: false
},
contextButton: {
enabled: false
}
}
},
is there a way that I can export the base64 with the allowHTML option. If the allowHTML is true and then it will send me back with a base64 that i cant use as an image src.This is for a Custom DOMPDF
When i draw circles of the same color one by one using fill() for each circle. It comes that when they are overlapped, common are color is darker (saturated).
See example 1 (left) in JS Bin.
If i create long path and then use fill() for this common path, it has strange artifacts (yep, of course it's confused by complex path and don't know what i'm trying to draw)
See example 2 (right) in JS Bin.
How i can achieve that common area of circles with the same color was not saturated, it shoud be not darker than other circles with the same color. (exactly what i have in JS Bin right side, but without crazy artifacts)
If circles with different colors has common areas, color should be saturated.
Regarding your .getImageData solution ...
It's faster to use compositing rather than .getImageData to blend your colors.
Here's a function to combine overlapping semi-transparent circles without having the overlap darken.
Draw all identically colored circles on a 2nd canvas in an opaque color.
Set context.globalCompositeOperation='source-in' which causes new drawings to replace existing pixels.
Fill the 2nd canvas with the desired semi-transparent color for this set of indentically colored circles.
The result is a set of overlapping circles without the darkening effect.
function uniformColorCircles(circles){
var PI2=Math.PI*2;
tempctx.globalCompositeOperation='source-over';
tempctx.clearRect(0,0,cw,ch);
tempctx.beginPath();
for(var i=0;i<circles.length;i++){
var c=circles[i];
tempctx.arc(c.x,c.y,c.radius,0,PI2);
}
tempctx.fillStyle='black';
tempctx.fill();
tempctx.globalCompositeOperation='source-in';
tempctx.fillStyle=circles[0].rgba;
tempctx.fill();
}
And here is example code and a Demo involving multiple sets of semi-transparent circles:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
ctx.fillRect(0,0,120,220);
var tempCanvas=canvas.cloneNode();
var tempctx=tempCanvas.getContext('2d');
var c1={x:100,y:200,radius:50,rgba:'rgba(255,0,0,0.5)'};
var c2={x:100,y:240,radius:35,rgba:'rgba(255,0,0,0.5)'};
var c3={x:140,y:200,radius:50,rgba:'rgba(0,255,255,0.5)'};
var c4={x:140,y:240,radius:35,rgba:'rgba(0,255,255,0.5)'};
var c5={x:120,y:140,radius:50,rgba:'rgba(255,255,0,0.5)'};
uniformColorCircles([c1,c2]);
ctx.drawImage(tempCanvas,0,0);
uniformColorCircles([c3,c4]);
ctx.drawImage(tempCanvas,0,0);
uniformColorCircles([c5]);
ctx.drawImage(tempCanvas,0,0);
function uniformColorCircles(circles){
var PI2=Math.PI*2;
tempctx.globalCompositeOperation='source-over';
tempctx.clearRect(0,0,cw,ch);
tempctx.beginPath();
for(var i=0;i<circles.length;i++){
var c=circles[i];
tempctx.arc(c.x,c.y,c.radius,0,PI2);
}
tempctx.fillStyle='black';
tempctx.fill();
tempctx.globalCompositeOperation='source-in';
tempctx.fillStyle=circles[0].rgba;
tempctx.fill();
}
body{ background-color:white; }
#canvas{border:1px solid red; }
<canvas id="canvas" width=512 height=512></canvas>
I have solved the problem using helper canvases and canvas image data processing.
There are data array, which contains coordinates and value which is used to determine which color we need to use.
I draw each circle color in it's own layer, then process each layer with preventSaturation function. Then add all layers into original canvas.
Please if anyone know the better way let me know.
If someone didn't understand what i needed to do it was:
1) i had this
2) i tried to have this
var canvas = document.getElementById('circles');
var ctx = canvas.getContext('2d');
var radius = 30;
var opacity = .7;
var data = [
{
x: 200,
y: 200,
v: 10
},
{
x: 230,
y: 230,
v: 20
},
{
x: 250,
y: 210,
v: 30
},
{
x: 270,
y: 190,
v: 40
},
{
x: 300,
y: 220,
v: 100
},
{
x: 300,
y: 260,
v: 200
},
{
x: 320,
y: 210,
v: 300
},
{
x: 300,
y: 160,
v: 200
},
{
x: 380,
y: 160,
v: 3000
},
{
x: 380,
y: 110,
v: 3000
},
{
x: 320,
y: 190,
v: 3000
}
];
var styles = {
blue: {
edgeValue: 0,
color: [0, 0, 255, 0.7]
},
green: {
edgeValue: 100,
color: [0, 255, 0, 0.7]
},
red: {
edgeValue: 1000,
color: [255, 0, 0, 0.7]
}
};
var layers = {};
for (var prop in styles) {
if(styles.hasOwnProperty(prop)) {
var c = document.createElement('canvas');
c.width = canvas.width;
c.height = canvas.height;
var cx = c.getContext('2d');
var cc = document.createElement('canvas');
cc.width = radius * 2;
cc.height = radius * 2;
var ccx = cc.getContext('2d');
var cColor = styles[prop].color;
ccx.fillStyle = 'rgba(' + cColor[0] + ',' + cColor[1] + ',' + cColor[2] + ',' + cColor[3] + ')';
ccx.beginPath();
ccx.arc(radius, radius, radius, 0, Math.PI * 2, true);
ccx.closePath();
ccx.fill();
layers[prop] = {
color: styles[prop].color,
edgeValue: styles[prop].edgeValue,
canvas: c,
ctx: cx,
canvasC: cc,
ctxC: ccx,
objects: []
};
}
}
data.forEach(function(o) {
var layer = o.v < styles.green.edgeValue ? layers.blue : o.v < styles.red.edgeValue ? layers.green : layers.red;
layer.ctx.drawImage(layer.canvasC, o.x, o.y);
layer.objects.push(o);
});
for(prop in layers) {
if(layers.hasOwnProperty(prop)) {
var image = layers[prop].ctx
.getImageData(0, 0, layers[prop].canvas.width, layers[prop].canvas.height);
preventColorSaturation(image.data, layers[prop].color);
layers[prop].ctx.putImageData(image, 0, 0);
ctx.drawImage(layers[prop].canvas, 0, 0);
}
}
function preventSaturation (d, s) {
var rgb255 = raRGBA255(s);
for (var i = 0; i < d.length; i += 4) {
d[i] = Math.min(d[i], rgb255[0]);
d[i + 1] = Math.min(d[i + 1], rgb255[1]);
d[i + 2] = Math.min(d[i + 2], rgb255[2]);
d[i + 3] = Math.min(d[i + 3], rgb255[3]);
}
}
function raRGBA255 (s) {
return [
s[0],
s[1],
s[2],
255 * s[3]
];
}
function raHexToRGB (s) {
var hexREGEXP = /^#([0-9A-Za-z]{3,6})$/;
var parsedHEX = s.match(hexREGEXP);
if (!parsedHEX) {
return [0, 0, 0];
}
return [
parseInt(parsedHEX[1].slice(0, 2), 16),
parseInt(parsedHEX[1].slice(2, 4), 16),
parseInt(parsedHEX[1].slice(4), 16)
];
}