Jump to content

1 px line on top of every image pasted into Firefox from paint.net


Recommended Posts

That's a very odd bug. When I select an image from paint.net selection tool then copy it on firefox on whatsapp web or google docs, there's a 1 pixel line on top of the image:

3yofmlah6sgc1.webp.8ad0d8498c595c60ed59c7386ee5fb04.webp

The line gets literally incorporated into the image. If I download the image, the black line is on top of it replacing the first row of pixels.

This does not occur on Edge, and it also does not occur when I try to paste something from other image editors, like mspaint. Firefox version is 122.0 and paint.net is 5.0.12 and Windows 11. This bug just won't occur if I don't use firefox or paint.net, and it only occurs when both are present. I have also posted this question on firefox support forum.

Bug is also present in my laptop with the same apps, so it's not exclusive to my computer.

Link to comment
Share on other sites

@Marvin321 There are lots of references to this already: https://forums.getpaint.net/topic/124444-screenshots-are-corruptedshifted-when-pasting-from-paintnet-into-firefox

It's a Firefox issue.

 

11 minutes ago, Marvin321 said:

What now? Is there a solution?


Until this is fixed in Firefox, your options are to:

1. Save the image as a .png and upload that file via Firefox to WhatsApp Web or Google Docs (or wherever).
or
2. Copy from paint.net, paste into IrfanView or MS Paint. Copy from Irfanview/MS Paint and paste to Firefox.
 

 

Link to comment
Share on other sites

Here:

Ok it looks like paint.net doesn't want to add the default 12 bytes header on DIBV5. Just why not?

BoltBait said "Just because a bunch of software does it, doesn't make it right."

 

I mean who cares if it is right or not, at least it works for everyone. I do not see firefox solving this issue soon because they just won't care enough, so why can't paintnet add these 12 bytes and call it a go? Problem is fixed.

It is like "Ok, if you won't fix it on your side, let me fix it myself for the sake of the users". Stuff like this occur every time and that's why open source projects have so many forks.

Link to comment
Share on other sites

19 minutes ago, Marvin321 said:

because https://bugzilla.mozilla.org/show_bug.cgi?id=1866655 says paint.net is faulty on that one

 

That is not the conclusion in the bug report.

 

22 minutes ago, Marvin321 said:

The bug is 2 months old and we got no fix yet :/

 

I think it's safe to say a niche clipboard bug is not a top priority, so it may take some time for them to address it.

(September 25th, 2023)  Sorry about any broken images in my posts. I am aware of the issue.

bp-sig.png
My Gallery  |  My Plugin Pack

Layman's Guide to CodeLab

Link to comment
Share on other sites

8 minutes ago, Marvin321 said:

Ok it looks like paint.net doesn't want to add the default 12 bytes header on DIBV5. Just why not?

 

Because it's not supposed to be there

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

8 minutes ago, Marvin321 said:

why can't paintnet add these 12 bytes and call it a go?

 

Because Firefox should either 1) fix how they handle DIBV5, or -- even better -- 2) use the PNG which is placed at a higher priority in the clipboard, which sidesteps ALL of these issues.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Basically it's like this,

  1. Paint.NET is placing a correctly formed DIBV5 on the clipboard. I'm going to assume this unless proven otherwise, such as via an in-depth technical discussion by experts here at https://forums.getpaint.net/topic/122848-pasting-dibv5-image/)
  2. Apps have varying degrees of buggy ways of copying and pasting DIBV5s
  3. DIBV5 is supposed to be a simple format, but it isn't due to how it's evolved over the last ~30 years and its poor documentation/specification
  4. This led to DIBV5 essentially being an ambiguously defined format due to both its buggy specification and inconsistent implementations across many, many apps
  5. PNG does not have any of these issues and is far superior in all ways except for encoding performance (i.o.w. how long it takes to copy it to the clipboard). This could probably be rectified if we got a PNG library with a "super fast compression" mode (which may already exist, although WIC certainly doesn't support that unfortunately).
  6. Therefore, if a PNG is on the clipboard alongside the DIBv5, just use the PNG. All this pain would be avoided if Firefox and Paint Tool SAI would just do that.

 

DIBV5 should be considered a legacy clipboard format at this point, only included for the sake of apps that don't (yet) handle PNG. No matter what changes I make to the DIBV5 clipboard copy/paste code, it's guaranteed that a bunch of other apps will either 1) not copy its data to the clipboard correctly such that PDN will handle it, or 2) not read PDN's DIBV5 from the clipboard correctly. This is what happens Every. Single. Time. I. Have. Ever. Changed. The. Clipboard. Code. It is not possible to get 100% compatibility between all apps. At this point you need the equivalent of winning a case at the US Supreme Court to get me to change this code (which I considered that discussion linked in #1 to be an example of). It's not worth the trouble otherwise.

  • Like 1
  • Upvote 1

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Thank you for that reply, Rick. It helped me to understand the issue better.

I got another question if you don't mind answering: If DIBV5 is that problematic, then why keep it? Even mspaint doesn't use it anymore. Haven't apps moved to png yet in all these years? Firefox does give preference to DIBV5 over PNG for some reason, but it certainly accepts PNG. Don't know much about the other apps.

Link to comment
Share on other sites

8 minutes ago, Marvin321 said:

If DIBV5 is that problematic, then why keep it?

 

Because DIB(non-V5) doesn't support transparency, and not all apps handle PNG. When I say "it's a legacy format" I mean that we shouldn't be shedding blood and tears over getting it right, we should just consider it to be a lost cause and accept it how it is, and encourage other apps to support and prefer PNG.

 

You could also say that cash is legacy and problematic compared to debit/credit cards. Why keep using it then? Because it's still useful for a variety of reasons, and we're not yet to the point where we can just stop. And maybe we'll never reach that point, either for DIBV5 or cash, and that's something we have to accept. It's not a lost cause, we can still improve the state of the world with respect to either, but there will always be some app that someone wants to use that only supports DIB/DIBV5, just like there will always be someone out there who only has cash or some merchant who isn't willing/able to handle cards. (Also, there isn't yet a law banning cash in favor of cards, at least not in the U.S.)

 

(I'm not sure cash vs. card is a proper good analogy, and I'm not trying to stake out a political position on the matter, but hopefully you got the point)

 

Another way to improve this situation would be for Windows itself to step in and fix up / homogenize the clipboard data, possibly with compatibility shims for legacy apps which are known to do the wrong thing. 

  • Upvote 1

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

I just searched the Firefox source for CF_DIBV5, BITMAPV4HEADER and BITMAPV5HEADER in order to find out how they handle DIBs - and now I need to book an appointment with my therapist...

 

As far as I can tell Firefox has used the renowned method of rolling a dice to decide what method to use when reading/writing V4/V5 bitmaps. In most places the DIB data does not contain the extra three color masks, but in a few places it does, and in one gloriously stupid case, when writing a bitmap file, the masks are included but only if the data is specified as having alpha. WTH?

Edited by AndersM
  • Haha 2
Link to comment
Share on other sites

A practical solution might be to write a little program that implements something called a clipboard hook. Basically it gets notified whenever the clipboard changes. When it sees a DIBV5 put onto the clipboard, it will either 1) Remove it if a PNG is also on the clipboard, or 2) Decode the DIBV5, re-encode as PNG, put the PNG on the clipboard, and remove the DIBV5.

 

Obviously this would break pasting into apps that don't support PNG, but I'm sure things could be filtered with allow/block lists.

 

Anyway this is just an idea.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

Btw, as far as I remember there is a bug, at least in Windows 10, where pasting CF_DIB will corrupt the CF_DIBV5 on the clipboard - or maybe vice versa. I can't remember which it is.

 

Edit: I see that I already mentioned this in the original thread:

The comment that mentions the clipboard bugs predates Windows 10 so I probably discovered them in Windows 7 (I only upgraded from Win7 to Win10 a few months ago).

Edited by AndersM
Link to comment
Share on other sites

  • Tactilis changed the title to 1 px line on top of every image pasted into Firefox from paint.net

Alas, it seems I have to concede defeat on this issue. I was wrong.

 

I noticed that the MSDN documentation on bitmap headers has once again been rephrased and now reads:

Quote

The red, green, and blue bitfield masks for BI_BITFIELD bitmaps immediately follow the BITMAPINFOHEADER, BITMAPV4HEADER, and BITMAPV5HEADER structures. The BITMAPV4HEADER and BITMAPV5HEADER structures contain additional members for red, green, and blue masks as follows. [...]

The text that follows shows evidence of having been copied from somewhere else (it makes reference to the function which has no meaning in that context) but regardless of that it doesn't really leave room for ambiguity; The color masks must follow BITMAPV5HEADER.

 

Since MSDN nowadays is semi-community-edited I didn't take the above as definite proof (I've seen the documentation on this topic change back and forth so many times). Instead I decided to consult "the source" (I'll leave it to you to guess what "the source" is).

 

So I now have it on good authority that the following is how the Windows clipboard calculates the size of a DIB (brought to you in beautiful Pascal):

 

Size of the color table

if (BitmapInfoHeader.biCompression = BI_RGB) then
begin
  if (BitmapInfoHeader.biClrUsed) then
    ColorTableSize := BitmapInfoHeader.biClrUsed * SizeOf(DWORD)
  else
  if (BitmapInfoHeader.biBitCount <= 8) then
    ColorTableSize := (1 shl BitmapInfoHeader.biBitCount) * SizeOf(RGBQUAD)
  else
    ColorTableSize := 0;
end else
if (BitmapInfoHeader.biCompression = BI_BITFIELDS) then
begin
  if (BitmapInfoHeader.biBitCount = 16) or (BitmapInfoHeader.biBitCount = 32) then
    ColorTableSize := 3 * SizeOf(DWORD)
  else
    ColorTableSize := 0;
end else
if (BitmapInfoHeader.biCompression = BI_RLE4) {
  ColorTableSize := 16 * SizeOf(DWORD)
else 
if (BitmapInfoHeader.biCompression = BI_RLE8) {
  ColorTableSize := 256 * SizeOf(DWORD)
else
  ColorTableSize := 0;

 

Size of the pixel data

PixelDataSize := (((BitmapInfoheader.biWidth * BitmapInfoheader.biBitCount + 31) and not 31) shr 3) * Abs(BitmapInfoheader.biHeight); // 32 bit aligned

 

Size of DIB

DIBSize := BitmapInfoHeader.biSize + ColorTableSize + PixelDataSize;

 

 

Notes:

  • The above only applies for (BitmapInfoHeader.biSize >= SizeOf(BITMAPINFOHEADER)).
    The rules for BITMAPCOREHEADER (i.e an OS/2 DIB) are different.
     
  • For BITMAPV5HEADER, when writing DIBs, the header color masks are duplicated into the color table.
    This is a requirement but I guess it's a good idea since we don't know which of the two set of masks the reader will use.
     

My guess regarding the cause of this mess is that the DIB spec, internally at Microsoft, has evolved through time from the masks originally being included in the header to them being excluded because that was how most people implemented it.
This would explain the ever changing documentation and the fact that different Microsoft tools has implemented different formats - and in the case of the clipboard, different formats within the same code. It's also interesting that so many Windows tools are able to correctly read both versions of the format...

Link to comment
Share on other sites

1 hour ago, AndersM said:

I noticed that the MSDN documentation on bitmap headers has once again been rephrased and now reads:

It doesn't look like it's actually be edited, there's just a bunch of commits for infra stuff: https://github.com/MicrosoftDocs/win32/commits/docs/desktop-src/gdi/bitmap-header-types.md

 

The documentation for BITMAPV5HEADER still states, in several different ways (but of course never really directly saying it) that this is not the way it should be done. It does say that bV5ClrUsed can be non-zero for a 32-bpp DIB, but that those color values are to be used for some kind of palette optimization (obviously a legacy consideration at this point).

 

It also has a nonsensical explanation for how color profiles should be encoded (3rd paragraph in Remarks) ... I actually implemented color profiles support in the v5.1 codebase for BMP files as part of the color management feature work, but it's disabled because that's a Pandora's box I'm not willing to open yet.

 

And yet, as you point out, the Bitmap Header Types page does explicitly say that there should be 3 color mask values in addition to the embedded color mask values (bV5RedMask et. al.).

 

I'm still not convinced that the 2nd copy of the masks is supposed to be there, other than the "normalization of deviancy" Wikipedia link you provided -- in other words, the spec is de facto the implementation, which was accidentally crowdsourced out to every application or library that handles DIBV5s. And everyone got it wrong in a multitude of different ways and we just have to deal with it now.

 

So we must find a way to unambiguously encode and decode in a way that achieves maximum compatibility.

 

At least for decoding you can look at the total size of the payload (header + bitmap + anything else) -- if there's an extra 12 bytes then assume that the 3 masks are there, otherwise they're not. Easy enough. On the Paint.NET side I haven't been seeing any issues here, so my code for that seems to be working (knock on wood).

 

Encoding is another matter because then you're contending with the decoding implementation of every other app. That's currently where the trouble is. And there isn't really a good unit test for this because it would require obtaining all of those other apps, something I am not interested in paying for or dealing with. At least for now we can probably focus on Chrome, Firefox, Office (Word, etc.), GIMP, Krita, mspaint, and any other popular free(ware) software.

 

I'll reopen the issue over on GitHub and poke into this some more for the 5.0.13 servicing release. It sounds like what you're saying is that the fix is to add in the 3 masks. It may also make sense to just punt this over to WIC -- have it save a BMP to an in-memory stream, skip past the BITMAPFILEHEADER, and copy the remaining bytes to the clipboard.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

I've had an idea and hope it might be useful to you.

What if Rick adds an option somewhere in paint.net (interface or config files) so you can disable/enable DIBV5 format from the clipboard? That would be a workaround this Firefox issue, and if some incompatibility is noticed with other apps, just turn it back on.

Link to comment
Share on other sites

3 hours ago, Marvin321 said:

What if Rick adds an option somewhere in paint.net (interface or config files) so you can disable/enable DIBV5 format from the clipboard?

I'm not doing that

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

On 2/6/2024 at 4:19 AM, Rick Brewster said:

I'll reopen the issue over on GitHub and poke into this some more for the 5.0.13 servicing release. It sounds like what you're saying is that the fix is to add in the 3 masks. It may also make sense to just punt this over to WIC -- have it save a BMP to an in-memory stream, skip past the BITMAPFILEHEADER, and copy the remaining bytes to the clipboard.

 

I think I'm going crazy.

As you've seen I have implemented the change in Graphics32 and closed the issue there.

Since many of the bitmaps I used for unit testing were made under the old assumption I decided to regenerate all the bitmaps. And now that I had the bitmaps I thought I would see how Windows Paint handled them - and this is where things got really depressing.

 

I've attached a zip with two 16x16x32bit bitmaps in v4 BI_BITFIELDS format. One with the color table and one without. The bitmaps look like this (in my own bitmap editor):

image.png.998fc37930dcbbaafedf8387051fb8d9.png

And this is what they look like in Paint when I load them from file:

bgra_v4_bottomup.bmp (with color table)

image.png.6eaa3a94b1c4c0846fc9a6e3eb662c8a.png

bgra_v4_bottomup_missing_color_table.bmp (without color table)

image.png.ae72c40881130f9dd19bcff2b7b5dfe5.png

Okay, I thought, I guess I was wrong about being wrong. But then I did a copy from my editor (which now produce CF_DIBV5 data with the color table) and pasted into Paint:

image.png.2ef5efaed267b3befb14f986097d11bf.png

(╯°□°)╯︵ ┻━┻

 

Anyway, I'm too busy with work and stuff to get to the bottom of this right now but I just wanted to give you a heads up.

bgra_v4_bottomup.zip

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...