canvas.toDataURL('image/png') losing data?

1,698 views
Skip to first unread message

Mr.doob

unread,
Apr 11, 2010, 10:04:23 AM4/11/10
to Chromium-dev
Hello,

I've been working on a drawing application recently. While
implementing localStorage so the user wouldn't lose their work when
closing the browser I faced some issues. This seems to work fine on
Firefox, but in Chromium (Linux) I get this:

Original drawing:
http://twitpic.com/1ev1be

Drawing I get from the localStorage:
http://twitpic.com/1ev1cw

I don't think this has to do with localStorage but with the way I save
the image to localStorage:

localStorage.canvas = canvas.toDataURL('image/png');

I think toDataURL() is losing colour data on the pixels with opacity >
1. I guess this has something to do with premultiplied alpha?

I have also found the annoying premultiplied alpha thing when drawing
with dark colours. This is something I already had to fight with in
Flash/Actionscript and I got a bit disappointed that it's here on
<canvas> too.

Here it's the link to test all this:

http://mrdoob.com/projects/harmony/next/

Draw something, wait 2 seconds (time until it saves to localStorage)
and then refresh the page.

Is this something under the radar? Is Chromium going to fix this?
Also, is Chromium planning to implement toDataURL('image/svg+xml')?

Thanks in advance!
--
Mr.doob

Brett Wilson

unread,
Apr 11, 2010, 11:03:37 AM4/11/10
to ricardo...@gmail.com, Chromium-dev
On Sun, Apr 11, 2010 at 7:04 AM, Mr.doob <ricardo...@gmail.com> wrote:
> Hello,
>
> I've been working on a drawing application recently. While
> implementing localStorage so the user wouldn't lose their work when
> closing the browser I faced some issues. This seems to work fine on
> Firefox, but in Chromium (Linux) I get this:
>
> Original drawing:
> http://twitpic.com/1ev1be
>
> Drawing I get from the localStorage:
> http://twitpic.com/1ev1cw
>
> I don't think this has to do with localStorage but with the way I save
> the image to localStorage:
>
> localStorage.canvas = canvas.toDataURL('image/png');
>
> I think toDataURL() is losing colour data on the pixels with opacity >
> 1. I guess this has something to do with premultiplied alpha?
>
> I have also found the annoying premultiplied alpha thing when drawing
> with dark colours. This is something I already had to fight with in
> Flash/Actionscript and I got a bit disappointed that it's here on
> <canvas> too.

We do use premultipled alpha internally for canvas. When we do
toDataURL, we have to unpremultiply it to save it as a PNG.

I'm not sure I follow your theory about what's happening. Can you
elaborate on what you're doing and what you think is causing the
problem?

Thanks,
Brett

ricardo cabello

unread,
Apr 11, 2010, 11:15:36 AM4/11/10
to Brett Wilson, Chromium-dev
Thanks for replying back Brett.

Is there any way to workaround the premultiplied alpha being used
internally? Doesn't this make practically impossible to make a drawing
application wtihout glitches like these:

http://twitpic.com/mqkqh (Notice the darkening at the edges of the
brush, that's supposed to be the same color)

I'm going to research a bit more on the canvas.toDataURL() issue. I've
realised that there are many steps on what I'm doing and is not clear
where the pixel data is getting lost.

--
Mr.doob

Brett Wilson

unread,
Apr 11, 2010, 11:23:58 AM4/11/10
to ricardo cabello, Chromium-dev
On Sun, Apr 11, 2010 at 8:15 AM, ricardo cabello
<ricardo...@gmail.com> wrote:
> Thanks for replying back Brett.
>
> Is there any way to workaround the premultiplied alpha being used
> internally?

No.

> Doesn't this make practically impossible to make a drawing
> application wtihout glitches like these:

You can take an non-premultipled image and make it premultiplied,
paint it to the screen, and lose nothing. I'm not sure what it makes
impossible unless there's a bug in Chrome or your program is making
some incompatible assumptions about how the data is stored (but I'm
not sure what this could be).

Brett

ricardo cabello

unread,
Apr 11, 2010, 11:37:20 AM4/11/10
to Brett Wilson, Chromium-dev
Thanks again for replying Brett.

I've done more tests and as suspected the problem comes from the toDataURL()

I drawn this:

http://twitpic.com/1evnjd

This is a screen capture of what the browser was displaying. A
<canvas> with some red pixels, most of them with opacity > 1. And the
<body> having a blue-ish background colour. The composition in the
browser seems correct.

I've changed the save method so at the moment does the toDataURL()
from the <canvas> without flattening it with the background. This is a
screen capture of the result:

http://twitpic.com/1evnkv

As you can see, the generated .png is showing some darkening. Instead
of being simply reds and reds with opacity > 1. But to double check, I
saved that png to my desktop, opened it on Gimp and added the same
blueish background on a layer under it. This is a screengrab:

http://twitpic.com/1evnlw

Compare it again with what the browser was showing before the toDataURL():

http://twitpic.com/1evnjd

(I'm using Chromium 5.0.374.0 (44177) Ubuntu and Chrome 5.0.342.9 beta Ubuntu)

--
Mr.doob

Mike Mammarella

unread,
Apr 11, 2010, 1:24:38 PM4/11/10
to ricardo...@gmail.com, Brett Wilson, Chromium-dev
On Apr 11, 2010, at 8:37 AM, ricardo cabello wrote:

> Thanks again for replying Brett.
>
> I've done more tests and as suspected the problem comes from the
> toDataURL()
>
> I drawn this:
>
> http://twitpic.com/1evnjd
>
> This is a screen capture of what the browser was displaying. A
> <canvas> with some red pixels, most of them with opacity > 1. And the
> <body> having a blue-ish background colour. The composition in the
> browser seems correct.

I am no graphics expert, but do you really mean opacity > 1? As far as
I know it only makes sense when 0 <= opacity <= 1, so if somehow you
really do have opacity > 1 then maybe that could have something to do
with the problem here...

> --
> Chromium Developers mailing list: chromi...@chromium.org
> View archives, change email options, or unsubscribe:
> http://groups.google.com/a/chromium.org/group/chromium-dev

Mr.doob

unread,
Apr 11, 2010, 4:01:07 PM4/11/10
to Chromium-dev
I'm sorry, yes!

opacity < 1 (or alpha channel < 255).

> > Chromium Developers mailing list: chromium-...@chromium.org

Mr.doob

unread,
Apr 12, 2010, 6:56:09 AM4/12/10
to Chromium-dev
Brett,

Would it be helpful if I provide more information/examples about this?
I can try to record a video if it helps...

Cheers!

Nico Weber

unread,
Apr 12, 2010, 10:20:47 AM4/12/10
to ricardo...@gmail.com, Chromium-dev
Ideally, you create a reduced test case (a web page that draws to
canvas, then gets the data and puts it into another image), then file
a bug with the test case attached, and then reply here with the bug
number.

> Chromium Developers mailing list: chromi...@chromium.org

Mr.doob

unread,
Apr 12, 2010, 10:42:18 AM4/12/10
to Chromium-dev

John Tamplin

unread,
Apr 12, 2010, 10:46:56 AM4/12/10
to bre...@chromium.org, ricardo...@gmail.com, Chromium-dev
On Sun, Apr 11, 2010 at 11:03 AM, Brett Wilson <bre...@chromium.org> wrote:
We do use premultipled alpha internally for canvas. When we do
toDataURL, we have to unpremultiply it to save it as a PNG.

I'm not sure I follow your theory about what's happening. Can you
elaborate on what you're doing and what you think is causing the
problem?

Conversion will lose data due to roundoff. Imagine unpremultiplied A=1 RGB=128, which then gets premultiplied to A=1 RGB=0/1 depending on how you round.  When you convert back to unpremultiplied, you are probably going to get A=1 RGB=0/255.  The problem is less severe with larger alpha values, but still exists.

--
John A. Tamplin
Software Engineer (GWT), Google

Mr.doob

unread,
Apr 12, 2010, 3:28:37 PM4/12/10
to Chromium-dev
I've tested on Chrome/Windows with the same results (premultiplied
alpha on the output).

I've also tested on Safari and Firefox and in both cases the output is
correct...
I don't think I can provide more information for this, the example on
the already opened ticket shows the bug quite well.

I hope this gets fixed soon.

Thanks!

Reply all
Reply to author
Forward
0 new messages