1

I manipulate the RGBA values of an image and save it with toDataUrl like this:

image.src = ctx.toDataURL("image/png");

Now I want to read out the RGBA values of this saved image. It should have the same RGBA values, but in fact some values are changed, i.e.: from RGB(0,0,1) to RGB(0,0,0). This doesn't seem like a big problem But I need the exact same values I've already manipulated to decode my encoded image since I programm a steganography, otherwise I can't be sure that the manipulated image and its RGBA values are saved correctly.

Edit: The encoded image is loaded on my server by the user and added in the DOM as img element. Than my encoding function accesses on this image by canvas with ctx.getImageData. Now I manipulate the RGBA values after the LSB-Method. (The message in binary is embedded on the last Bit of every R, G, B and A value)

The encoding function itself is working, but when it comes to decoding (of the manipulated image saved with toDataURL), the data arrays - before and after - of getImageData are not equal.

I guess it could be some kind of data loss caused by toDataURL

Armin Bu
  • 1,330
  • 9
  • 17

3 Answers3

2

toDataURL("image/png") outputs a PNG8 image, which only supports 256 colors at the most. So it's unreliable if you want exactly accurate output. In such case you have to craft your own encoding algorithm (e.g. get color data with the help of getImageData, and encode as a PNG24 image).

Leo
  • 13,428
  • 5
  • 43
  • 61
  • Well, I am sry. But I had to compress my question and code. I'll edit my question. – Armin Bu Dec 13 '14 at 14:09
  • I have researched the internet. PNG has a loseless compression, not as JPEG or webp. I guess this is the reason, why the second parameter of toDataURL is not needed with png… – Armin Bu Dec 14 '14 at 12:06
  • @Reijo according to [**spec**](http://www.w3.org/TR/2011/WD-html5-20110405/the-canvas-element.html#dom-canvas-todataurl), PNG is the only MIME type required to support. Other types like JPG are up to the browser vendor. But W3C does give suggestion on when the second argument is used. – Leo Dec 14 '14 at 12:48
2

Unequal values are caused during the .getImageData -> .putImageData cycle. This cycle is lossy.

The WhatWG (standards board) specification allows browsers to change your image data values when you do .putImageData. Therefore, your resulting .toDataURL will have equivalent (but not identical) color values from the values you manipulated. The browser is allowed to change your values in order to more easily combine pixels that overlay/underlay the canvas.

Due to the lossy nature of converting to and from premultiplied alpha colour values, pixels that have just been set using putImageData() might be returned to an equivalent getImageData() as different values.

https://html.spec.whatwg.org/multipage/scripting.html#the-canvas-element

markE
  • 102,905
  • 11
  • 164
  • 176
  • ctx.putImageData(): "The globalAlpha and globalCompositeOperation attributes, as well as the shadow attributes, are ignored for the purposes of this method call; pixels in the canvas are replaced wholesale, with no composition, alpha blending, no shadows, etc." Related to my steganography problem, that means, I can not use the alpha-chanel, only RGB could work for me. Is this correct? Doesn't the alpha also influence RGB values? – Armin Bu Dec 14 '14 at 12:29
0

I know this question is quite old, but I was recently experimenting, and from what I can tell the canvas (and most current image tools) don't return direct RGBA data. Instead, they seem to work with pre-multiplied RGBA values.

One way to work around this is to use 0xFF as the alpha value. Another is to write an pre-multiplied RGBA directly. Though I'd recommend the former route, as the latter still seems subject to conversation between the formats.

seph
  • 813
  • 6
  • 16