Open Bug 1866655 Opened 7 months ago Updated 7 months ago

Support PNG and/or “short” BI_BITFIELDS DIBv5 when pasting images (pixel data shifted when copy/pasting from Paint.NET)

Categories

(Core :: Graphics: ImageLib, defect)

Firefox 120
defect

Tracking

()

UNCONFIRMED

People

(Reporter: mercury13, Unassigned)

References

(Depends on 1 open bug)

Details

Attachments

(4 files)

Attached file images.zip

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0

Steps to reproduce:

  1. Go to any site that pastes images from clipboard, e.g. https://madebyevan.com/clipboard-test/
    (first seen on Github)
  2. Copy image from Paint.NET (other software does not work)
  3. 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.

Attached image Original file
Attached image How it pasted

UPD. Probably Paint.NET is to blame, as I repeated on Paint.NET and XnView, but why?

Component: Untriaged → DOM: Copy & Paste and Drag & Drop
Product: Firefox → Core

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”.

I’ll consult author of Paint.NET.

So Paint.NET is surely wrong.

But you can also do something — prefer PNG over DIB.

Or you can check for too short buffer and hunt for other format.

Component: DOM: Copy & Paste and Drag & Drop → Graphics: ImageLib

I’ll repeat what I see.

  1. Paint.NET is surely wrong, as lots of software, incl. W10’s screenshot function, create/require these twelve bytes.
  2. But you can do something from your behalf: prefer PNG over DIB, detect too short DIBv5 and fall back to other formats.

Criterion for short DIB is simple: stream_size < header_size (dword 00) + palette_size (computed by header) + image_data_size (dword 0x14)

Possibly also wrong image_data_size for uncompressed data, ≠ width·height·bpp.

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).

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.

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.

Severity: -- → S3

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.

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 :)

Depends on: 460969

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.

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.

GIMP: I said long DIBv5? As it’s BI_RGB, there’s no difference between long and short.

Summary: Strange “synergy” in copy/paste images with Paint.NET → Support PNG and/or “short” DIBv5 when pasting images (strange “synergy” with Paint.NET)
Summary: Support PNG and/or “short” DIBv5 when pasting images (strange “synergy” with Paint.NET) → Support PNG and/or “short” BI_BITFIELDS DIBv5 when pasting images (strange “synergy” with Paint.NET)
Summary: Support PNG and/or “short” BI_BITFIELDS DIBv5 when pasting images (strange “synergy” with Paint.NET) → Support PNG and/or “short” BI_BITFIELDS DIBv5 when pasting images (pixel data shifted when copy/pasting from Paint.NET)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: