I am using html2canvas lib to generate png image from html code. The html combine local images (from images folder) and remote images (from url address - server). The image is looking great but the remote images is missing. any idea how can i fix that issue?
$('#save').click(function () {
var elm = $('.media_container_1200628').get(0);
var width = "1200";
var height = "628";
html2canvas(elm).then(function (canvas) {
Canvas2Image.saveAsPNG(canvas, width, height);
})
});
As explained in the documentation you should allow cross-origin images to taint the canvas.
https://html2canvas.hertzen.com/configuration
In your specific case you can do the following:
$('#save').click(function () {
var elm = $('.media_container_1200628').get(0);
var width = "1200";
var height = "628";
html2canvas(elm, { allowTaint: true }).then(function (canvas) {
Canvas2Image.saveAsPNG(canvas, width, height);
})
});
Related
We are a team of 5 developers working on a video rendering implementation. This implementation consists out of two parts.
A live video preview in the browser using angular + konva.
A node.js (node 14) serverless (AWS lambda container) implementation using konva-node that pipes frames to ffmpeg for rendering a mp4 video in higher quality for later download.
Both ways are working for us. Now we extracted the parts of the animation that are the same for frontend and backend implementation to an internal library. We imported them in BE and FE. That also works nicely for most parts.
We noticed here that konva-node is deprecated since a short time. Documentation says to use canvas + konva instead on node.js. But this just doesn't work. If we don't use konva-node we cannot create a stage without a 'container' value. Also we cannot create a raw image buffer anymore, because stage.toCanvas() actually returns a HTMLCanvas, which does not have this functionality.
So what does konva-node actually do to konva API?
Is node.js still supported after deprecation of konva-node?
How can we get toBuffer() and new Stage() functionality without konva-node in node.js?
backend (konva-node)
import konvaNode = require('konva-node');
this.stage = new konvaNode.Stage({
width: stageSize.width,
height: stageSize.height
});
// [draw stuff on stage here]
// create raw frames to pipe to ffmpeg
const frame = await this.stage.toCanvas();
const buffer: Buffer = frame.toBuffer('raw');
frontend (konva)
import Konva from 'konva';
this.stage = new Konva.Stage({
width: stageSize.width,
height: stageSize.height,
// connect stage to html element in browser
container: 'container'
});
// [draw stuff on stage here]
Finally in an ideal world (if we could just Konva in frontend and backend without konva-node the following should be possible for a shared code.
loading images
public static loadKonvaImage(element, canvas): Promise<any> {
return new Promise(resolve => {
let image;
if (canvas) {
// node.js canvas image
image = new canvas.Image();
} else {
// html browser image
image = new Image();
}
image.src = element.url;
image.onload = function () {
const konvaImage = new Konva.Image(
{image, element.width, element.height});
konvaImage.cache();
resolve(konvaImage);
};
});
}
Many props to the developer for the good work. We would look forward to use the library for a long time, but how can we if some core functionality that we rely on is outdated shortly after we started the project?
Another stack overflow answer mentioned Konva.isBrowser = false;. Maybe this is used to differentiate between a browser and a node canvas?
So what does konva-node actually do to konva API?
It slightly patches Konva code to use canvas nodejs library to use 2d canvas API. So, Konva will not use browser DOM API.
Is node.js still supported after deprecation of konva-node?
Yes. https://github.com/konvajs/konva#4-nodejs-env
How can we get toBuffer() and new Stage() functionality without konva-node in node.js?
You can try to use this:
const canvas = layer.getNativeCanvasElement();
const buffer = canvas.toBuffer();
We have solved the problems we had the following way:
create stage (shared between Be+FE)
public static createStage(stageWidth: number, stageHeight: number, canvas?: any): Konva.Stage {
const stage = new Konva.Stage({
width: stageWidth,
height: stageHeight,
container: canvas ? canvas : 'container'
});
return stage;
}
create raw image buffer (BE)
const frame: any = await this.stage.toCanvas();
const buffer: Buffer = frame.toBuffer('raw');
loading images (shared between Be+FE)
public static loadKonvaImage(element, canvas?: any): Promise<Konva.Image> {
return new Promise(resolve => {
const image = canvas ? new canvas.Image() : new Image();
image.src = element.url;
image.onload = function () {
const konvaImage = new Konva.Image(
{image, element.width, element.height});
konvaImage.cache();
resolve(konvaImage);
};
});
}
Two things we had to do.
We have rewritten our whole backend and library code to use ESM modules and we got rid of konva-node and konva 7 in general.
We defined the node module canvas in all places as any. It seems like Konva accepts more inputs than expected and like specified in the type interfaces of the classes. canvas is only installed in the backend and inserted in some library methods like shown above.
#lavrton nice to hear from you. Your answer might also work for getting the Buffer, but you didn't answer on how to create the stage. Luckily we found a solution for both issues.
What Nodejs image processing lib should I use with Heroku to make a dynamic png?
I was first trying to make easy SVG file but it seems Facebook sharing does not accept SVG, so I need to generate PNG/GIF.
I was hoping a code like this that would return the image binary stream in http server Response.
//create image
var gd = require('node-gd');
var img = gd.createSync(200, 80);
img.colorAllocate(0, 255, 0);
img.savePng('../test.png', 0, function(error) {
if (error) throw error;
img.destroy();
})
I am making a Node.js/Electron application that downloads and displays images. I am downloading an image from the internet using request. I want to save this image in memory and display it without saving the file on the local hard drive. I am aware I could accomplish what I am asking here by inserting <img src="url"> into the DOM, but this is a heavily simplified version of my code and what I am trying to accomplish can not be done with that.
var image = fs.createWriteStream(?); // Is there anyway to save the image to memory?
request(url).pipe(image);
$('img').exampleScriptToSetImage(image); // And is there any way to display that image in a element without saving it to the local disk and loading its path?
Indeed! You can pipe your requested image data into a concat stream, convert the buffer to base64, and set the base64 encoding as your image source.
var path = require('path')
var request = require('request') // or hyperquest, simple-get, etc...
var concat = require('concat-stream')
var image = request(url)
image.pipe(concat({ encoding: 'buffer' }, function (buf) {
var ext = path.extname(file.name).slice(1) // assuming you have the file name
if (ext === 'svg') ext = 'svg+xml'
var src = 'data:image/' + ext + ';base64,' + buf.toString('base64')
var img = document.createElement('img')
img.src = src
document.body.appendChild(img)
})
I have an Electron app that loads URL from PHP server. And the page contains an iFrame having a source to PDF. The PDF page seems absolutely ok in a normal web browser but asks for download in Electron. Any help?
My codes for html page is
<h1>Hello World!</h1>
Some html content here...
<iframe src="http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf" width="1200" height="800"></iframe>
And my js code is something like
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
app.on('ready', createWindow)
Any help would be really greatful...
Electron is shipping already with an integrated PDF viewer.
So you can load PDF files just like normal HTML files, the PDF viewer will automatically show up.
E.g. in BrowserWindow with .loadURL(…), in <iframes>, <object> and also with the, at the moment discouraged, <webview>.
PS: The need to enable the plugins property in the BrowserWindow or <webview> is no more needed since Electron 9.
You will need
https://github.com/gerhardberger/electron-pdf-window
Example:
const { app } = require('electron')
const PDFWindow = require('electron-pdf-window')
app.on('ready', () => {
const win = new PDFWindow({
width: 800,
height: 600
})
win.loadURL('http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf')
})
This answer will focus on implementation with Angular.
After year of waiting (to be solved by the Electron) finally I decided to apply a workaround. For the people who needs it done, here it goes. Workaround comes with a cost of increasing bundle size totally 500K. (For Angular)
Workaround to use Mozilla PDF.js library.
NPM
GitHub
Implementation 1 (Setting nodeIntegration: true)
This implementation has no issue, you can implement by the document of the library mentioned. But if you run into additional problem like creating white window when route is changed, it is due to the setting nodeIntegration property to true. If so, use the following implementation.
Implementation 2 (Setting nodeIntegration: false)
This is the default by Electron. Using this configuration and viewing the PDF is bit tricky. Solution is to use Uint8Array instead of a blob or base64.
You can use the following function to convert base64 to Uint8Array.
base64ToArrayBuffer(data): Uint8Array {
const input = data.substring(data.indexOf(',') + 1);
const binaryString = window.atob(input ? input : data);
const binaryLen = binaryString.length;
const bytes = new Uint8Array(binaryLen);
for (let i = 0; i < binaryLen; i++) {
const ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
Or convert blob to array buffer
const blob = response;
let arrayBuffer = null;
arrayBuffer = await new Response(blob).arrayBuffer();
then pass the generated Uint8Array as the pdfSource to the ng2-pdfjs-viewer.
HTML
<ng2-pdfjs-viewer zoom="100" [pdfSrc]="pdfSource"></ng2-pdfjs-viewer>
Electron 9.0.0 has enabled PDF viewer already.
npm install electron#9.0.0
I uploaded some image to cloudinary - tried to manipulate (crop) the image but get the same image url (not cropped) - bug in cloudinary npm or I miss something?
var cloudinary = require('cloudinary');
....
var sourceUrl = cloudinaryImageDetails.url;
var croppedUrl = cloudinary.url(sourceUrl, {
width:30,
height: 30,
crop:'fill'
})
cloudinary.url works when supplied with the public_id of the uploaded image as first argument (instead of full image's URL).
For example,
cloudinary.url (`public_id`, { width:30, height: 30, crop:'fill' })
outputs -
http://res.cloudinary.com/cloud_name/image/upload/c_fill,h_30,w_30/public_id