2

I have loaded a 47MB image file from server and rendered it on canvas for editing.

After editing, when I try to get image's data URI, the browser freezes up, then asks if the script should be stopped.

I'm currently using this code to get the data URI:

drawingCanvas.toDataURL("image/png");

It's somewhat faster to get a JPEG data URI, but I need the file to be a PNG format only. Is there any way to make this faster?

Qantas 94 Heavy
  • 15,750
  • 31
  • 68
  • 83
  • Try to use `HTMLCanvasElement.prototype.toBlob` method, but it works only for FF and IE10+ (msToBlob). Also you can draw part of image in canvas, read this part by toDataURL/toBlob, and draw new one, read it and make it in a loop :) – Alex Feb 18 '15 at 07:41
  • Several possibilities come to mind: (1) You could use Pinal's advice and break your image into several smaller canvases and save those smaller canvases to images. (2) You could also serialize just the edits instead of trying to save the image plus the edits. (3) Perhaps your project is best done as a desktop/laptop app instead of a browser app (4) Offer your app only on Chrome or Firefox where users can now right-click-save the canvas as an image and have the user send that image to you as a file upload to your server. – markE Feb 18 '15 at 08:00
  • Thank you using "HTMLCanvasElement.prototype.toBlob" getting some what faster ,No problem i have added compatablility for it – user3458948 Feb 18 '15 at 09:16

2 Answers2

0

This file is too large to process via data URI. There are limitations in different browsers, see Data protocol URL size limitations

You may try to post base64 encoded data to your server, decode it and obtain then an ordinary image. Simplified solution presented in PHP, but the environment doesn't matter.

list($type, $data) = explode(';', $_POST['data']);
list(, $base64) = explode(',', $data);
unset($data);
$decoded = base64_decode($base64, true);
unset($base64);

if (false !== $decoded) {
  header('Content-type: ' . $type);
  header('Content-Disposition: attachment; filename="file.png"');
  header('Cache-Control: max-age=0');
  echo $decoded;
} else {
  header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
}
Community
  • 1
  • 1
Max Zuber
  • 1,217
  • 10
  • 16
  • Yes ,can you tell me is there any way to get image from canvas instead of using canvas.toDataURL("image/png"); – user3458948 Feb 18 '15 at 07:36
  • I've appended my answer above – Max Zuber Feb 18 '15 at 07:59
  • Thank you , I need to get data from canvas ,It is containing large image data to get data url from canvas is getting slow – user3458948 Feb 18 '15 at 09:23
  • The image is really huge, as you know. Split up the image into smaller pieces and process them separately. You may copy some rectangle area into virtual hidden canvas, save it contents, copy another part and so on – Max Zuber Feb 18 '15 at 10:08
0

No unfortunately. PNG encoding is a relative slow process in itself (you can see this with large images saved in apps such as Photoshop too).

The only efficient way to speed up things is to reduce the size of the canvas bitmap you want to encode - the browser is not the optimal tool for large data handling such as a large image files (dimension wise) and they where never meant to do these sort of things.

Breaking it down in slices can help you unblocking the UI. But since you cannot encode them in parallel, and there is overhead in producing the Base-64 encoded data-uri, you would need to use async setTimeout to give the browser some time to parse the event queue between each slice, and of course, you would have to piece them together at some point, somewhere, so this would make it slower, more error prone and more complex all-in-all (complex isn't necessary a bad thing though in cases such as these). It's probably your best bet though if reducing bitmap size is not an option. And as Max points out, there is size limits for data-uris.

You could dump the raw buffer using getImageData() but then you would end up with a raw sized buffer which has a chain of other implications.

Shared web workers could in theory do the encoding in parallel but would very likely be much slower than letting the browser do it in compiled code. You would have to provide code to do the encoding too... And as with many of the new things it does not have full or complete support yet.