Support “short” BI_BITFIELDS DIBv5 when pasting images (pixel data shifted when copy/pasting from Paint.NET)
Categories
(Core :: Graphics: ImageLib, defect)
Tracking
()
People
(Reporter: mercury13, Unassigned)
References
(Blocks 1 open bug)
Details
Attachments
(4 files)
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Steps to reproduce:
- Go to any site that pastes images from clipboard, e.g. https://madebyevan.com/clipboard-test/
(first seen on Github) - Copy image from Paint.NET (other software does not work)
- Paste at the site.
Actual results:
Pixel data is strangely shifted
Expected results:
Image should be copy-pasted as-is.
Cannot repeat on Win+Sh+S and Fx, XnView and Fx, Pain.NET and Vivaldi.
UPD. Probably Paint.NET is to blame, as I repeated on Paint.NET and XnView, but why?
Updated•2 years ago
|
Men at Paint.NET forum went to conclusion that something happened to DIBv5, but I cannot confirm. As pixel data is normal at the first glance (and IDK how to save it to file), maybe a common clipboard library does tricks?
More data. BI_BITFIELDS compression is commonly parsed badly.
Confirmed DIB or DIBv5 problem, cannot investigate further. CLIPBRD.EXE from old Windows does the same, but why?
From Paint.NET:
Because they are incorrectly parsing the BITMAPV5HEADER data. They are reading an additional 3 4-byte values at the end of the header, which is where the first 3 pixels of the bottom row are supposed to be. The DIB has its pixels in left-to-right, bottom-to-top order (which is oddly the standard for DIBs). So the image shifts left by 3 pixels because they're skipping 3 pixels worth of data, and then the rightmost 3 pixels of the bottom row are pulled from the left edge of the next row. And so on up until the last 3 pixels (the top rightmost pixels) are garbage values -- so this is also technically a buffer overrun bug on their part (which can actually be a serious security concern depending on context).
Also, a great way to remove this type of bug -- because DIBs and DIBV5s are a monstrous pain to work with and it's no surprise they got it wrong because lots of apps also get it wrong -- is to process the PNG clipboard format instead. It's a PNG ... should be very easily parsable by an app like Paint Tool SAI.
Paint.NET puts PNG onto the clipboard first for a reason: so that other apps will (hopefully) prioritize it over the DIB variants that are so error prone across the whole ecosystem of Windows apps.
Confirmed problem: Lots of software insert three dwords to BI_BITFIELDS DIBv5 at offsets 7C…87. They sat in image data old DIB there because they were absent in header, but in DIBv5 they are in header, at offset 28…37 (bV5RedMask…bV5AlphaMask).
But those twelve bytes are so commonly used that the only way to check whether DIBv5 is good or bad is…
those_three_dwords_present = (bV5Compression == BI_BITFIELDS) && ((format < DIBv5) || ([data_size] ≥ bV5Size + bV5SizeImage + 12));
And why you’ve got that black stripe? DIB is written bottom-to-top, and Fx is critical software and constantly checks for buffer overruns. When three dwords are erroneously skipped, it tries to get a byte range for line beyond limit, and one function says “Nope”, and the other does nothing in response for this “Nope”.
| Reporter | ||
Comment 10•2 years ago
|
||
I’ll consult author of Paint.NET.
| Reporter | ||
Comment 11•2 years ago
|
||
So Paint.NET is surely wrong.
| Reporter | ||
Comment 12•2 years ago
|
||
But you can also do something — prefer PNG over DIB.
| Reporter | ||
Comment 13•2 years ago
|
||
Or you can check for too short buffer and hunt for other format.
Updated•2 years ago
|
| Reporter | ||
Comment 14•2 years ago
|
||
I’ll repeat what I see.
- Paint.NET is surely wrong, as lots of software, incl. W10’s screenshot function, create/require these twelve bytes.
- But you can do something from your behalf: prefer PNG over DIB, detect too short DIBv5 and fall back to other formats.
| Reporter | ||
Comment 15•2 years ago
|
||
Criterion for short DIB is simple: stream_size < header_size (dword 00) + palette_size (computed by header) + image_data_size (dword 0x14)
| Reporter | ||
Comment 16•2 years ago
|
||
Possibly also wrong image_data_size for uncompressed data, ≠ width·height·bpp.
| Reporter | ||
Comment 17•2 years ago
|
||
More data, interesting!
Windows itself always creates long DIBv5 (e.g. from PrintScreen, DIB). But if you make short DIBv5, it’ll happily recognize short format and convert it to other formats (BITMAP/DIB).
| Reporter | ||
Comment 18•2 years ago
|
||
And if you make long DIBv5… it will convert badly! Strange.
So everything I can say. DIBv5 is so broken that you should either support both short and long DIBv5, or use other formats instead.
| Reporter | ||
Comment 19•2 years ago
|
||
So, here’s the info and why you should support both short and long DIBv5. Or prefer more manageable formats like PNG. Sorry for being a chameleon here.
Copy in old DIB format (AND NO OTHER FORMATS). Everything works, Windows successfully auto-converts to Bitmap and LONG DIBv5.
Copy in BITMAP format. Same.
Copy in SHORT DIBv5 format. Windows successfully auto-converts to Bitmap and DIB. Bad: Fx, XnView. Good: Paint.NET, some old Photoshop, GIMP, Vivaldi
Copy in LONG DIBv5 format. Auto-conversion to Bitmap and DIB incorrect. Bad: Vivaldi, Photoshop, GIMP (probably use Bitmap/DIB that are incorrect, won’t blame from the start). Good: Fx, XnView
Create different images in BITMAP/DIB/DIBv5 to see who. Vivaldi, GIMP → DIB. Photoshop → BITMAP. Fx → DIBv5, parsing long format only. XnView → DIBv5, long only, with its own bugs.
I played with this program: https://github.com/Mercury13/clipboard-demo
DIBv5 is pink. DIB is cyan. BITMAP is white.
Updated•2 years ago
|
| Reporter | ||
Comment 20•2 years ago
|
||
In a nutshell. Screenshot, CLIPBRD.EXE, auto-conversion from BITMAP/DIB produce/require long DIBv5.
Auto-conversion from DIBv5 requires short DIBv5.
That’s why you need to CREATE long, but ACCEPT both.
Comment 21•2 years ago
|
||
This is fascinating, and very relevant to my work on fixing the clipboard handling in https://bugzilla.mozilla.org/show_bug.cgi?id=460969, thank you for the information :)
| Reporter | ||
Comment 22•2 years ago
|
||
Ashley Hale [:ahale]
Thank you.
UPD. IDK how to copy data in alternate formats, and need as simple example as possible, so I didn’t test PNG. I just tested three standard formats, BITMAP, DIB and DIBv5. Did not even test transparency for now.
| Reporter | ||
Comment 23•2 years ago
|
||
Ashley, you made me check COPYING transparent images, lady.
Translucent DIBv5 short ONLY:
- Totally OK: Paint.NET, Vivaldi
- Shifted pixel data: Fx, XnView
- No transparency: some old Photoshop, GIMP
(Let me skip DIBv5 long, as it won’t make any difference)
Translucent DIB ONLY:
- OK: Paint.NET, Fx, Vivaldi
- No transparency: XnView, Photoshop, GIMP
Translucent BITMAP ONLY:
- OK: Paint.NET
- No transparency: Fx, Photoshop
- No transparency, strange pixel data troubles: Vivaldi, GIMP
Probably Windows works by converting BITMAP → long DIBv5 → buggy DIB (both Vivaldi and GIMP prefer DIB).
How other image editors work here:
Photoshop: creates lot of formats, no one understands except Photoshop itself
GIMP: creates PNG + BI_RGB DIB/long DIBv5 w/transparency, understood by Paint.NET and Vivaldi
Paint.NET: creates PNG + BI_BITFIELDS DIB/short DIBv5, understood by everyone except Photoshop (Fx/XnView make artifacts, as always)
XnView: creates correct but premultiplied images, don’t even bother to support (Paint.NET managed to bother)
What and in which order should you COPY to avoid most bugs?
ALL FOUR FORMATS in any order: PNG, BITMAP, DIB, DIBv5
But that’s copying, not pasting. When pasting, it’s better to understand PNG and/or short DIBv5.
| Reporter | ||
Comment 24•2 years ago
|
||
GIMP: I said long DIBv5? As it’s BI_RGB, there’s no difference between long and short.
Comment 25•1 year ago
|
||
Firefox 132.0.2 (64-bit)
In other browsers/programm work correctly
https://docs.google.com/
From me topic:
https://forums.getpaint.net/topic/130993-copy-paste-image/
Im copy image from paint.net to Google docs and image broke.
Image
1 Copy part/full image from Paint.net Ctrl+C
https://i.imgur.com/bIQTdr0.png
2-3 Image after paste Ctrl+V in Google docs and this broke
https://i.imgur.com/5J8lx7j.png
https://i.imgur.com/HRqXvHT.png
4 Copy image from paint.net to Discord good work
https://i.imgur.com/osHLsGa.png
5 Copy-paste from discord to Google docs also broke transparent.
https://i.imgur.com/nSNdfk7.png
6 Im copy white square from Paint.net Ctrl+C
https://i.imgur.com/BbCA2Tq.png
7 After paste Ctrl+V in Google doc, black line appeared. Broke image
https://i.imgur.com/gR0sEzq.png
Not only me
https://bugzilla.mozilla.org/show_bug.cgi?id=1866655
https://support.mozilla.org/en-US/questions/1436969
https://github.com/graphics32/graphics32/issues/257
https://community.atlassian.com/t5/Confluence-questions/Screenshots-are-corrupted-when-pasting-from-paint-net-into/qaq-p/2581186#M290501
https://forums.getpaint.net/topic/124628-1-px-line-on-top-of-every-image-pasted-into-firefox-from-paintnet/ - 2 page ideas how fix
https://forums.getpaint.net/topic/124444-screenshots-are-corruptedshifted-when-pasting-from-paintnet-into-firefox
| Reporter | ||
Comment 27•1 year ago
|
||
Yes, that bug is duplicate. And I even wrote “easy” and “hard” way what to do.
| Reporter | ||
Comment 28•1 year ago
|
||
Repeat.
SHORT way. Support both short and long DIBv5 formats.
SHORT BUT WORSE way. Try old DIB if DIBv5 failed somehow.
LONG way. Support PNG as a better format of transparent images.
Updated•1 year ago
|
Comment 29•1 year ago
|
||
(In reply to mercury13 from comment #28)
LONG way. Support PNG as a better format of transparent images.
This part is really a Widget: Win32 bug; I'll break that out separately. (We still need to handle BMPs correctly, but there's not really any overlap between the two tasks.)
| Reporter | ||
Comment 30•1 year ago
|
||
As you implemented PNG, now it works for me.
There were several issues that made Swiss cheese together. Fixing at least one — OK.
What we are doing next?
| Reporter | ||
Comment 31•1 year ago
|
||
Paint.NET is surely wrong, as Windows itself creates/converts “long” DIBs. Few pieces of software create this format.
SIMPLE WAY. Calm down and close bug.
SHORT WAY. Check for short DIBv5 and fall back to other formats.
LONGER WAY. Support short DIBv5.
| Reporter | ||
Comment 32•1 year ago
|
||
Sign of short DIBv5: format = BI_BITFIELDS, length is enough for short, but not enough for long.
Description
•