Displaying preloaded image (p5.js) - javascript

I'm trying a basic display of a preloaded image with p5.js library (instantiation mode):
var sketch = function(p) {
var fondo;
p.preload = function() {
fondo = p.loadImage('app/themes/mrg/dist/images/tramas/example.jpg');
};
var viewportWidth = $(window).width();
p.setup = function(){
canvas = p.createCanvas(viewportWidth, 200);
canvas.background(255);
canvas.image(fondo, 0, 0);
};
};
new p5(sketch);
The canvas was created but no image is there.
Here is a working example:
https://stage.margenesdelarte.org/
The canvas is at the end of the page (with white background) but no image is rendered inside.
Image path is right, since there is no error in the console and it can be reached in its place:
https://stage.margenesdelarte.org/app/themes/mrg/dist/images/tramas/example.jpg
What is wrong, and how can I display this image? Thanks!

That's correct version? (I used BASE64 because I didn't want to run a local server)
var sketch = function(p) {
var fondo;
p.preload = function() {
fondo = p.loadImage("data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7");
};
var viewportWidth = 500;
p.setup = function(){
var canvas = p.createCanvas(viewportWidth, 200);
canvas.image(fondo, 0, 0); // doesn't work
p.image(fondo, 0, 0); // works fine
console.log(p.image, canvas.image); //there are different functions
};
};
new p5(sketch);
https://codepen.io/anon/pen/yPENXx?editors=1111
Explanation:
Both p and canvas has a image function but there are different image functions. You have to use p.image(). I think canvas.image() is has some relations with https://p5js.org/reference/#/p5.Image, but that's only my assumptions.

Is your file being localhosted? For p5 to access local files such as images, it needs to be localhosted... I recommend apache

Related

Pan-zoom a PDF (Javascript)

I'm trying to pan-zoom with the mouse a <div> that contains a PDF document.
I'm using PDF.js and panzoom libraries (but other working alternatives are welcome)
The snippet below basically does this task, but unfortunately, after the <div> is panzoomed, the PDF is not re-rendered, then its image gets blurry (pan the PDF with the mouse and zoom it with the mouse-wheel):
HTML
<script src="https://mozilla.github.io/pdf.js/build/pdf.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#panzoom/panzoom#4.3.2/dist/panzoom.min.js"></script>
<div id="panzoom-container">
<canvas id="the-canvas"></canvas>
</div>
<style>
#the-canvas {
border: 1px solid black;
direction: ltr;
}
</style>
JAVASCRIPT
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://mozilla.github.io/pdf.js/build/pdf.worker.js';
var pdfDoc = null,
canvas = document.getElementById('the-canvas'),
ctx = canvas.getContext('2d');
var container = document.getElementById("panzoom-container")
function renderPage(desiredHeight) {
pdfDoc.getPage(1).then(function(page) {
var viewport = page.getViewport({ scale: 1, });
var scale = desiredHeight / viewport.height;
var scaledViewport = page.getViewport({ scale: scale, });
canvas.height = scaledViewport.height;
canvas.width = scaledViewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: ctx,
viewport: scaledViewport
};
page.render(renderContext);
});
}
// Get the PDF
var url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf';
pdfjsLib.getDocument(url).promise.then(function(pdfDoc_) {
pdfDoc = pdfDoc_;
// Initial/first page rendering
renderPage(250);
});
var panzoom = Panzoom(container, {
setTransform: (container, { scale, x, y }) => {
// here I can re-render the page, but I don't know how
// renderPage(container.getBoundingClientRect().height);
panzoom.setStyle('transform', `scale(${scale}) translate(${x}px, ${y}px)`)
}
})
container.addEventListener('wheel', zoomWithWheel)
function zoomWithWheel(event) {
panzoom.zoomWithWheel(event)
}
https://jsfiddle.net/9rkh7o0e/5/
I think that the procedure is correct, but unfortunately I'm stuck into two issues that must be fixed (then I ask for your help):
I don't know how to re-render correctly the PDF after the panzoom happened.
consecutive renderings have to be queued in order to make this work properly (so that the PDF doesn't blink when panzooming)
How could I fix 1 and 2 ? I could not find any tool for doing that on a PDF, apart the panzoom lib.
Thanks
After some days of attempts, I solved the problem.
The tricky part was to scale down the contained canvas after the container has been scaled, with a transform-origin CSS attribute set:
canvas.style.transform = "scale("+1/panzoom.getScale()+")"
Here is a fiddle of a PDF that can pan-zoomed. Each new render is done after a small delay (here it is set to 250ms) which corresponds to a sort of "wheel stop event".
function zoomWithWheel(event) {
panzoom.zoomWithWheel(event)
clearTimeout(wheelTimeoutHandler);
wheelTimeoutHandler = setTimeout(function() {
canvas.style.transform = "scale("+1/panzoom.getScale()+")"
if (pdfDoc)
renderPage(panzoom.getScale());
}, wheelTimeout)
}
https://jsfiddle.net/7tmk0z42/

Export Highcharts to PDF (using javascript and local server - no internet connection)

I am using Highcharts in my application (without any internet connection)
I have multiple charts on a html page, and I want to generate a PDF report that contains all the charts from this page.
How can I do this without sending the data to any server on the internet ?
I will be thankful for any help or any example you can provide.
Thank you in advance :)
Yes this is possible but involves a few different libraries to get working. The first Library is jsPDF which allows the creation of PDF in the browser. The second is canvg which allows for the rendering and parsing of SVG's, the bit that is really cool though is it can render an svg on to canvas element. Lastly is Highcharts export module which will allow us to send the svg to the canvg to turn into a data URL which can then be given to jsPDF to turn into your pdf.
Here is an example http://fiddle.jshell.net/leighking2/dct9tfvn/ you can also see in there source files you will need to include in your project.
So to start highcharts provides an example of using canvg with it's export to save a chart as a png. because you want all the iamges in a pdf this has been slightly altered for our purpose to just return the data url
// create canvas function from highcharts example http://jsfiddle.net/highcharts/PDnmQ/
(function (H) {
H.Chart.prototype.createCanvas = function (divId) {
var svg = this.getSVG(),
width = parseInt(svg.match(/width="([0-9]+)"/)[1]),
height = parseInt(svg.match(/height="([0-9]+)"/)[1]),
canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
if (canvas.getContext && canvas.getContext('2d')) {
canvg(canvas, svg);
return canvas.toDataURL("image/jpeg");
} 
else {
alert("Your browser doesn't support this feature, please use a modern browser");
return false;
}
}
}(Highcharts));
Then for the example i have set up export on a button click. This will look for all elements of a certain class (so choose one to add to all of your chart elements) and then call their highcharts.createCanvas function.
$('#export_all').click(function () {
var doc = new jsPDF();
// chart height defined here so each chart can be palced
// in a different position
var chartHeight = 80;
// All units are in the set measurement for the document
// This can be changed to "pt" (points), "mm" (Default), "cm", "in"
doc.setFontSize(40);
doc.text(35, 25, "My Exported Charts");
//loop through each chart
$('.myChart').each(function (index) {
var imageData = $(this).highcharts().createCanvas();
// add image to doc, if you have lots of charts,
// you will need to check if you have gone bigger
// than a page and do doc.addPage() before adding
// another image.
/**
* addImage(imagedata, type, x, y, width, height)
*/
doc.addImage(imageData, 'JPEG', 45, (index * chartHeight) + 40, 120, chartHeight);
});
//save with name
doc.save('demo.pdf');
});
important to note here that if you have lots of charts you will need to handle placing them on a new page. The documentation for jsPDF looks really outdated (they do have a good demos page though just not a lot to explain all the options possible), there is an addPage() function and then you can just play with widths and heights until you find something that works.
the last part is to just setup the graphs with an extra option to not display the export button on each graph that would normally display.
//charts
$('#chart1').highcharts({
navigation: {
buttonOptions: {
enabled: false
}
},
//this is just normal highcharts setup form here for two graphs see fiddle for full details
The result isn't too bad i'm impressed with the quality of the graphs as I wasn't expecting much from this, with some playing of the pdf positions and sizes could look really good.
Here is a screen shot showing the network requests made before and after the export, when the export is made no requests are made http://i.imgur.com/ppML6Gk.jpg
here is an example of what the pdf looks like http://i.imgur.com/6fQxLZf.png (looks better when view as actual pdf)
quick example to be tried on local https://github.com/leighquince/HighChartLocalExport
You need to setup your own exporting server, locally like in the article
Here is an example using the library pdfmake:
html:
<div id="chart_exchange" style="width: 450px; height: 400px; margin: 0 auto"></div>
<button id="export">export</button>
<canvas id="chart_exchange_canvas" width="450" height="400" style="display: none;"></canvas>
javascript:
function drawInlineSVG(svgElement, canvas_id, callback) {
var can = document.getElementById(canvas_id);
var ctx = can.getContext('2d');
var img = new Image();
img.setAttribute('src', 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgElement))));
img.onload = function() {
ctx.drawImage(img, 0, 0);
callback(can.toDataURL("image/png"));
}
}
full working code:
https://jsfiddle.net/dimitrisscript/f6sbdsps/
Maybe this link can help you out.
http://bit.ly/1IYJIyF
Try refer to the exporting properties (fallbackToExportServer: false) and the necessary file that need to be include (offline-exporting.js).
Whereas for the export all at once part, currently I myself also still trying. Will update here if any.
This question is a bit old but was something i was working on myself recently and had some trouble with it.
I used the jsPDF library: https://github.com/MrRio/jsPDF
Issues i ran into involved jsPDF not supporting the SVG image exported by the high chart + images being blurry and low quality.
Below is the solution I used to get two charts into one pdf document:
function createPDF() {
var doc = new jsPDF('p', 'pt', 'a4'); //Create pdf
if ($('#chart1').length > 0) {
var chartSVG = $('#chart1').highcharts().getSVG();
var chartImg = new Image();
chartImg.onload = function () {
var w = 762;
var h = 600;
var chartCanvas = document.createElement('canvas');
chartCanvas.width = w * 2;
chartCanvas.height = h * 2;
chartCanvas.style.width = w + 'px';
chartCanvas.style.height = h + 'px';
var context = chartCanvas.getContext('2d');
chartCanvas.webkitImageSmoothingEnabled = true;
chartCanvas.mozImageSmoothingEnabled = true;
chartCanvas.imageSmoothingEnabled = true;
chartCanvas.imageSmoothingQuality = "high";
context.scale(2, 2);
chartCanvas.getContext('2d').drawImage(chartImg, 0, 0, 762, 600);
var chartImgData = chartCanvas.toDataURL("image/png");
doc.addImage(chartImgData, 'png', 40, 260, 250, 275);
if ($('#chart2').length > 0) {
var chart2SVG = $('#chart2').highcharts().getSVG(),
chart2Img = new Image();
chart2Img.onload = function () {
var chart2Canvas = document.createElement('canvas');
chart2Canvas.width = w * 2;
chart2Canvas.height = h * 2;
chart2Canvas.style.width = w + 'px';
chart2Canvas.style.height = h + 'px';
var context = chart2Canvas.getContext('2d');
chart2Canvas.webkitImageSmoothingEnabled = true;
chart2Canvas.mozImageSmoothingEnabled = true;
chart2Canvas.imageSmoothingEnabled = true;
chart2Canvas.imageSmoothingQuality = "high";
context.scale(2, 2);
chart2Canvas.getContext('2d').drawImage(chart2Img, 0, 0, 762, 600);
var chart2ImgData = chart2Canvas.toDataURL("image/png");
doc.addImage(chart2ImgData, 'PNG', 300, 260, 250, 275);
doc.save('ChartReport.pdf');
}
chart2Img.src = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(chart2SVG)));
}
}
chartImg.src = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(chartSVG)));
}
}
scripts to include:
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js"></script>

replacing an image in canvs - javascript

I'm attempting to make a very simple meme generator, whereby you select the image you want to add text onto using a drop down menu. I can successfully select the image I want and display it within the canvas, however when I change my selection, instead of changing the image it adds it over the first image.
I'd like to be able to chose the image, and if i change my mind it simply replaces the current image. Any suggestions you might have would be very welcome!
Here's my code:
window.onload = function init(){
var selector = document.getElementById('selector');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
var imagesObj = {
"fry" : ['images/fry.jpg'],
"badluck" : ['images/badluck.jpg'],
"success" : ['images/success.jpg']
};
selector.addEventListener('change', function(){
imagesObj[selector.value].forEach(function(item){
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
};
imageObj.src = item;
});
});
}
It looks like this did the trick:
context.clearRect(0, 0, 298, 350);

Using canvas to create desktop notification images, only one image works from background page

I'm having an issue while using canvas in a background page to create data URLs for desktop notifications' images.
I want to use the "image" notifications which require a 3:2 ratio to display properly. The images I want to use (from hulu.com) are a different ratio, so I decided to use the canvas element to create the corresponding data URL off of these images so that the ratio is correct. It kind of works in theory, but…
…I'm having issues if I'm creating more than one canvas/notification in the background page. One image is created properly, but the rest comes out empty.
Confusingly, opening the same background page in a new tab (i.e. exact same code) makes everything works just fine: all the notifications are created with the images loaded from hulu.com. Also, just changing the dimensions from 360x240 to 300x200 makes it work. Finally, though they're similar computers with the same Chrome version (34.0.1847.116), it works without modification at work while it doesn't on my own laptop.
I made a test extension available at the bottom of this post. Basically, it only has a generated background page. The code for that page is this:
var images = ["http://ib2.huluim.com/video/60376901?size=290x160&img=1",
"http://ib2.huluim.com/video/60366793?size=290x160&img=1",
"http://ib4.huluim.com/video/60372951?size=290x160&img=1",
"http://ib1.huluim.com/video/60365336?size=290x160&img=1",
"http://ib3.huluim.com/video/60376290?size=290x160&img=1",
"http://ib4.huluim.com/video/60377231?size=290x160&img=1",
"http://ib4.huluim.com/video/60312203?size=290x160&img=1",
"http://ib1.huluim.com/video/60376972?size=290x160&img=1",
"http://ib4.huluim.com/video/60376971?size=290x160&img=1",
"http://ib1.huluim.com/video/60376616?size=290x160&img=1"];
for (var i = 0; i < 10; i++) {
getDataURL(i);
}
/*
* Gets the data URL for an image URL
*/
function getDataURL(i) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = 360;
canvas.height = 240;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0);
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
var dataURL = canvas.toDataURL('image/png');
chrome.notifications.create('', {
type: 'image',
iconUrl: 'logo_128x128.png',
title: String(i),
message: 'message',
imageUrl: dataURL
}, function(id) {});
}
//img.src = chrome.extension.getURL('logo_128x128.png');;
img.src = images[i];
}
The commented out line for img.src = ... is a test where it loads a local file instead of a remote one. In that case, all the images are created.
The red rectangle added to the canvas is to show that it's not just the remote image that is an issue: the whole resulting canvas is empty, without any red rectangle.
If you download and add the test extension below, you should get 10 notifications but only one with an image.
Then, to open the background page in a new tab, you can inspect the background page, type this in the console:
chrome.extension.getURL('_generated_background_page.html')
and right-click the URL, and click "Open in a new Tab" (or window). Once open you should get 10 notifications that look fine.
Any idea of what is going on? I haven't been able to find any kind of limitations for background pages relevant to that. Any help would be appreciated, because this has been driving me crazy!
Files available here: https://www.dropbox.com/s/ejbh6wq0qixb7a8/canvastest.zip
edit: based on #GameAlchemist's comment, I also tried the following: same getDataURL method, but the loop wrapped inside an onload for the logo:
function loop() {
for (var i = 0; i < 10; i++) {
getDataURL(i);
}
}
var logo = new Image();
logo.onload = function () {
loop();
}
logo.src = chrome.extension.getURL('logo_128x128.png');
Remember that the create() method is asynchronous and you should use a callback with. The callback can invoke next image fetching.
I would suggest doing this in two steps:
Load all the images first
Process the image queue
The reason is that you can utilize the asynchronous image loading better this way instead of chaining the callbacks which would force you to load one and one image.
For example:
Image loader
var urls = ["http://ib2.huluim.com/video/60376901?size=290x160&img=1",
"http://ib2.huluim.com/video/60366793?size=290x160&img=1",
"http://ib4.huluim.com/video/60372951?size=290x160&img=1",
"http://ib1.huluim.com/video/60365336?size=290x160&img=1",
"http://ib3.huluim.com/video/60376290?size=290x160&img=1",
"http://ib4.huluim.com/video/60377231?size=290x160&img=1",
"http://ib4.huluim.com/video/60312203?size=290x160&img=1",
"http://ib1.huluim.com/video/60376972?size=290x160&img=1",
"http://ib4.huluim.com/video/60376971?size=290x160&img=1",
"http://ib1.huluim.com/video/60376616?size=290x160&img=1"];
var images = [], // store image objects
count = urls.length; // for loader
for (var i = 0; i < urls.length; i++) {
var img = new Image; // create image
img.onload = loader; // share loader handler
img.src = urls[i]; // start loading
images.push(img); // push image object in array
}
function loader() {
count--;
if (count === 0) process(); // all loaded, start processing
}
//TODO need error handling here as well
Fiddle with concept code for loader
Processing
Now the processing can be isolated from the loading:
function process() {
// share a single canvas (use clearRect() later if needed)
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
current = 0;
canvas.width = 360;
canvas.height = 240;
createImage(); // invoke processing for first image
function createImage() {
ctx.drawImage(images[current], 0, 0); // draw current image
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
chrome.notifications.create('', {
type : 'image',
iconUrl : 'logo_128x128.png',
title : String(i),
message : 'message',
imageUrl: canvas.toDataURL() // png is default
},
function(id) { // use callback
current++; // next in queue
if (current < images.length) {
createImage(); // call again if more images
}
else {
done(); // we're done -> continue to done()
}
});
}
}
Disclaimer: I don't have a test environment to test Chrome extensions so typos/errors may be present.
Hope this helps!

cc.sprite.create not working? cocos2d-html

I am new to Cocos2d-html5 v2.2.1 and I am trying to add a sprite (simple image) to the canvas. The code does add an image with the correct width and height but it is just black.
I cant seem to find any errors so I am kinda stuck.
Any help would be great. My code is below:
In main.js i load the resources:
applicationDidFinishLaunching:function () {
if(cc.RenderDoesnotSupport()){
//show Information to user
alert("Browser doesn't support WebGL");
return false;
}
// initialize director
var director = cc.Director.getInstance();
//cc.EGLView.getInstance()._adjustSizeToBrowser();
//cc.EGLView.getInstance()._resizeWithBrowserSize(true);
//cc.EGLView.getInstance().setDesignResolutionSize(600, 400, cc.RESOLUTION_POLICY.SHOW_ALL);
// set FPS. the default value is 1.0/60 if you don't call this
director.setAnimationInterval(1.0 / this.config['frameRate']);
//load resources
cc.LoaderScene.preload(g_resources, function () {
director.replaceScene(new this.startScene());
}, this);
return true;
}
g_resources is defined in resource.js:
var s_jet = "images/jet.png";
var s_character = "images/p1_front.png";
var g_resources = [
//image
{src:s_jet},
{src:s_character}];
spriteScene.js:
init:function () {
var selfPointer = this;
this._super();
var size = cc.Director.getInstance().getWinSize();
var lazyLayer = cc.LayerColor.create(new cc.Color4B(45, 50, 128, 255), 600, 600);
//var lazyLayer = cc.Layer.create();
lazyLayer.setAnchorPoint(new cc.Point(0.5,0.5));
var characterSprite = cc.Sprite.create("./images/p1_front.png");
lazyLayer.addChild(characterSprite, 0);
this.addChild(lazyLayer);
var rotateToA = cc.RotateTo.create(2, 0);
var scaleToA = cc.ScaleTo.create(2, 1, 1);
characterSprite.setPosition(new cc.Point(size.width/2,size.height/2));
I just dont understand why the sprite is just being drawn as a black box.
Edit: When I uncomment the line below from main.js; at first the image is still black but when I resize the browser, the image appears:-
cc.EGLView.getInstance().setDesignResolutionSize(600, 400, cc.RESOLUTION_POLICY.SHOW_ALL);
I dont know what this is implying.
Ok guys! I figured it out and I am pissed. Changed this line:
this.characterSprite.setPosition(new cc.Point(size.width/2,size.height/2));
to:
this.characterSprite.setPosition(cc.p(size.width/2, size.height/2));
Documentation/tutorials for cocos2d-html5 are outdated and this is getting frustrating.

Categories