Jump to content

Copy/Paste image offset three pixels when pasted into Paint Tool SAI


Recommended Posts

When I copy an image directly from Paint.NET to Paint Tool SAI, the image appears slightly offset - the image is shifted three pixels to the left, with the leftmost three pixel columns appearing on the right side of the image, shifted down 1 pixel:

 

Example image copied from Paint.NET:

image.png.0a58f35c91ff225a4ca28ddbfdf383be.png

How it appears after being pasted into Paint Tool SAI: 

image.png.3db6d83423c57d30df99a500b2992f00.png

 

Behavior seems to be consistent regardless of image size, in other words it's always three pixels off even if I downscale the image: 

image.png.72a59ff60929c7e4753e2eef5775d887.png image.png.118f7b3a3715156336cddd4e23e30dba.png

This doesn't occur if the same image is pasted from anywhere else I've tested (browser, discord, photoshop, etc) leading me to believe it's an issue with Paint.NET in particular and not with Paint Tool SAI.

Link to comment
Share on other sites

2 hours ago, dorko said:

This doesn't occur if the same image is pasted from anywhere else I've tested (browser, discord, photoshop, etc) leading me to believe it's an issue with Paint.NET in particular and not with Paint Tool SAI.


That conclusion, i.e. that it is a Paint.NET issue, does not necessarily follow from what you have described.

Have you tested pasting the image from Paint.NET to other applications? Do they similarly show the 3 pixel shift?
If they do, then it is quite possibly a Paint.NET issue.
If they do not, then it is more likely that it's a Paint Tool SAI problem.

Link to comment
Share on other sites

1 minute ago, Tactilis said:


That conclusion, i.e. that it is a Paint.NET issue, does not necessarily follow from what you have described.

Have you tested pasting the image from Paint.NET to other applications? Do they similarly show the 3 pixel shift?
If they do, then it is quite possibly a Paint.NET issue.
If they do not, then it is more likely that it's a Paint Tool SAI problem.

They do not, the issue seems to be unique to specifically pasting from Paint.NET to Paint Tool SAI. Pasting from anywhere else to SAI works fine; pasting from Paint.NET to anywhere else works fine. Given the pixel shift only occurs from images copied through Paint.NET, my (perhaps limited) understanding is that SAI seems to not like however Paint.NET in particular handles its clipboard images. Quite curious why, on a technical level, this sort of image distortion would happen as a result.

Link to comment
Share on other sites

Paint.NET places the image onto the clipboard in various formats.

It's up to the consuming program (in this case, Paint Tool SAI) to choose which format it wants to use.

Maybe Paint Tool SAI is choosing a format that it doesn't handle properly.

¯\_(ツ)_/¯

 

These are the formats Paint.NET is placing onto the clipboard:

image.png

  • Like 1

(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

Interesting! Exactly the insight I was hoping for, toe_head. Seems like fixing this sort of issue might be beyond the scope of Paint.NET then, though at least the images will paste properly if I perform an intermediary step, ie paste the image somewhere else and copy from there. 

Link to comment
Share on other sites

As long are you're using the latest version of Paint.NET, then this is a bug in Paint Tool SAI. It is not correctly parsing the DIBv5 header when bV5Compression is equal to BI_BITFIELDS.

 

You should report this bug to them.

 

See more discussion here: 

 

  • Like 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

5 hours ago, dorko said:

Quite curious why, on a technical level, this sort of image distortion would happen as a result.

 

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

 

(btw, DIB = Device Independent Bitmap)

  • Like 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

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.

 

Lastly, make sure you're using the latest versions of both Paint.NET and Paint Tool SAI. You didn't say what versions of each you were using. As far as we can tell you're using old versions of both.

  • Like 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

4 hours ago, Rick Brewster said:

Lastly, make sure you're using the latest versions of both Paint.NET and Paint Tool SAI. You didn't say what versions of each you were using. As far as we can tell you're using old versions of both.

I am using the latest Paint.NET. Though I'm using an older version of SAI (intentionally) I am willing to accept that if not caused by Paint.NET, which seems not to be the case, this issue's likely not one I can solve outside of using a different program to paste into SAI. It is nice to understand why this occurs, though, and to have a workaround I can use to paste images in properly. 

Link to comment
Share on other sites

30 minutes ago, dorko said:

this issue's likely not one I can solve outside of using a different program to paste into SAI


How frequently do you need to copy-paste from Paint.NET to Paint Tool SAI?

If it's something you do often, then I'd be inclined to automate the sequence:

  1. Copy from Paint.NET
  2. Paste into IrfanView
  3. Copy from IrfanView
  4. Paste into SAI


In this comment https://forums.getpaint.net/topic/122164-full-screen-preview-of-current-pic/?do=findComment&comment=610304 I posted an AutoHotkey script to copy from Paint.NET to IrfanView.

It would be simple to extend it to do steps 3 and 4 above. Then, with just a single keypress in Paint.NET you would be able to transfer your image to Paint Tool SAI.

If this capability would be useful to you but you run into any problems while extending the script, then please ask here.

Alternatively, if modifying the script is not something you are keen to do, then I could make the changes.

  • Upvote 1
Link to comment
Share on other sites

  • 3 months later...

So, the problem is those twelve bytes at offset 7C…87 of DIBv5. Should we insert them?

Who inserts…

  • Windows’ “Print Screen” function
  • Skia, by code
    if (bitmap->bmiHeader.biCompression == BI_BITFIELDS)
       color_table_length = 3;
  •  

Documentation states:

BI_BITFIELDS: The bitmap is not compressed, and the color table consists of three DWORD (defined in [MS-DTYP] section 2.2.9) color masks that specify the red, green, and blue components, respectively, of each pixel. This is valid when used with 16 and 32-bits per pixel bitmaps.

 

Maybe you forgot those bytes rather than they inserted erroneously?

Link to comment
Share on other sites

The problem is that the documentation for these things is not very good, you have to read all of it in order to understand where Microsoft made mistakes 😂 For full context, see this discussion: https://forums.getpaint.net/topic/122848-pasting-dibv5-image/

 

 

This is also an area where you/I have to find a happy medium between following the specification exactly ("theory"), versus loosening a bit to fit in with how everyone else is doing it ("practice").

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

The 3 color masks are meant to be placed after the BITMAPINFOHEADER . You don't put them after BITMAPV5HEADER, which is the newer version of that, because they're built-in (bV5RedMask, etc.) Notice how those are the first 3 "new" fields in BITMAPV5HEADER when compared with BITMAPINFOHEADER.

 

image.png

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

22 minutes ago, Mercury13 said:

Should we insert them?

 

Also who are you referring to by "we" ? Us in Paint.NET land? Or are you asking for the sake of another software project you're involved with?

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

31 minutes ago, Mercury13 said:

Skia, by code

if (bitmap->bmiHeader.biCompression == BI_BITFIELDS)

   color_table_length = 3;

 

In this case, if bV5ClrUsed is 3, then that makes sense -- it's saying there are 3 colors after the header. In Paint.NET, I set this to zero.

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

Windows’ screenshot function DOES INSERT these 12 bytes.

I’ll copy a bit of pure white using W10’s Win+Sh+S…

If Windows does, why shouldn’t you?

 

Total data length = 0x130

Size = 0x7C

Width = 6

Height = 7

Planes = 1

Bitcount = 32

Compression = BITFIELDS

SizeImage = 0xA8

XPelsPerMeter = 0

YPelsPerMeter = 0

ClrUsed = 0

ClrImportant = 0

RedMask = 0xFF0000

GreenMask = 0xFF00

BlueMask = 0xFF

AlphaMask = 0

CsType = 'sRGB' (bytes reversed, write as C multi-char constant)

Endpoints = all zeros

Gamma = all zeros

Intent = IMAGES

ProfileData = 0

ProfileSize = 0

Reserved = 0

[dword 0x7C] = 0xFF0000

[dword 0x80] = 0xFF00

[dword 0x84] = 0xFF

And then 0xA8 FF’s

0x7C + 0xA8 + 0x0C = 130

Link to comment
Share on other sites

Here’s more of Skia logic. I don’t see Skia’s WRITING code for now, but this is Skia’s READING code.

 

  switch (bitmap->bmiHeader.biBitCount) {
    case 1:
    case 4:
    case 8:
      color_table_length = bitmap->bmiHeader.biClrUsed
                               ? bitmap->bmiHeader.biClrUsed
                               : 1 << bitmap->bmiHeader.biBitCount;
      break;
    case 16:
    case 32:
      if (bitmap->bmiHeader.biCompression == BI_BITFIELDS)
        color_table_length = 3;
      break;
    case 24:
      break;
    default:
      NOTREACHED();
  }

 

Edited by Mercury13
More info
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...