Images loaded from data: url encoded data is staggered by one pixel




12 years ago
2 years ago


(Reporter: t3rmin4t0r, Unassigned)



Firefox Tracking Flags

(Not tracked)





12 years ago
User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060414 CentOS/1.0.8-1.4.1.centos4 Firefox/1.0.8
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060414 CentOS/1.0.8-1.4.1.centos4 Firefox/1.0.8

Images loaded from a URL encoded data: stream adds an extra pixel at the start of the image. The images which are loaded from base64 encoded streams do not display this particular problem and the cause could be a bug in the encodeURI or the corresponding decode operations. 

The test code has the same image displayed in two ways.

document.getElementById("img0").src= "data:image/bmp;base64," + Base64.encode(img.render());

document.getElementById("img1").src= "data:image/bmp," + encodeURI(img.render());

img0 is displayed correctly, while the img1 is staggered by 1px.

Reproducible: Always

Steps to Reproduce:
1. Open URL

Actual Results:  
The two images are identical (they are from the same data).

Expected Results:  
The second image is offset by a single pixel.

Each pixel is three bytes, so three full bytes have to be ignored or added to for the colours to remain the same. If it was a single byte off by one read error, at least a few pixels would've been a single colour (R, G or B).

On my Amd64 running fc3, the url "data: image/bmp;base64," caused a segfault, which doesn't seem to be happening on this machine.

Comment 1

12 years ago
In case you're wondering "Why ?!!!" ...  I was just bored.
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9a1) Gecko/20060610 Minefield/3.0a1 - Build ID: 0000000000
Confirmed, although I don't think I'm getting the symptoms you described: for me, the first image is missing the top-left corner, and the second has some corruption of the colours.
Ever confirmed: true
Not an imagelib issue at all.

The basic problem is that encodeURI doesn't encode what you think it encodes.  It encode _chars_, not _bytes.  In particular, it takes the JS string (which is UTF-16 encoded), converts it to UTF8, and encodes the resulting bytes.

Now one of the bytes you put in (when you do "s.writeInt32(3780);") is 196.  This, viewed as a UTF-16 char, requires _two_ bytes to encode in UTF8.  So you end up with different bytes in your bitmap, and everything shifted by at least two bytes (since you write this number twice).

Now when the data: protocol deals with the URI it just unescapes it and then proceeds to use the resulting bytes, whereas you want it to take the bytes, treat them as UTF8, decode into UTF32, reencode as UTF16, and then flatten to ISO-8859-1.  Except it's not obvious at all that this is what it should do, and would clearly break other use cases of data:.

That's not likely to start happening, especially since the base64 encoding exists precisely to handle issues like this.

biesi, it feels to me like this is invalid... thoughts?
Assignee: pavlov → nobody
Component: ImageLib → Networking
QA Contact: networking
Last Resolved: 2 years ago
Resolution: --- → INVALID
You need to log in before you can comment on or make changes to this bug.