dorko Posted August 22, 2023 Share Posted August 22, 2023 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: How it appears after being pasted into Paint Tool SAI: Behavior seems to be consistent regardless of image size, in other words it's always three pixels off even if I downscale the image: 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. Quote Link to comment Share on other sites More sharing options...
Tactilis Posted August 22, 2023 Share Posted August 22, 2023 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. Quote Link to comment Share on other sites More sharing options...
dorko Posted August 22, 2023 Author Share Posted August 22, 2023 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. Quote Link to comment Share on other sites More sharing options...
toe_head2001 Posted August 22, 2023 Share Posted August 22, 2023 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: 1 Quote (September 25th, 2023) Sorry about any broken images in my posts. I am aware of the issue. My Gallery | My Plugin Pack Layman's Guide to CodeLab Link to comment Share on other sites More sharing options...
dorko Posted August 23, 2023 Author Share Posted August 23, 2023 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. Quote Link to comment Share on other sites More sharing options...
Reptillian Posted August 23, 2023 Share Posted August 23, 2023 (edited) I have this issue when copy and pasting from Paint.NET into Firefox. Unfortunately, I'll just shrug and say "I'll just live then.". Edited August 23, 2023 by Reptillian Quote G'MIC Filter Developer I am away from this forum for undetermined amount of time: If you really need anything related to my PDN plugin or my G'MIC filter within G'MIC plugin, then you can contact me via Paint.NET discord, and mention me. Link to comment Share on other sites More sharing options...
Rick Brewster Posted August 23, 2023 Share Posted August 23, 2023 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: 1 Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Rick Brewster Posted August 23, 2023 Share Posted August 23, 2023 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) 1 Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Rick Brewster Posted August 23, 2023 Share Posted August 23, 2023 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. 1 Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
dorko Posted August 23, 2023 Author Share Posted August 23, 2023 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. Quote Link to comment Share on other sites More sharing options...
Tactilis Posted August 23, 2023 Share Posted August 23, 2023 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: Copy from Paint.NET Paste into IrfanView Copy from IrfanView 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. 1 Quote Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 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? Quote Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 Other software I tested, e.g. GIMP or many-years-old Photoshop, use RGB DIBv5, and for transparent imagery they utilize other formats, e.g. Metafile. Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted November 26, 2023 Share Posted November 26, 2023 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"). Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Rick Brewster Posted November 26, 2023 Share Posted November 26, 2023 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. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Rick Brewster Posted November 26, 2023 Share Posted November 26, 2023 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? Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 Who does not copy in BI_BITFIELDS for himself but expects those 12 bytes from other software… WinXP’s CLIPBRD.EXE XnView Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted November 26, 2023 Share Posted November 26, 2023 @AndersM might have some extra insight, if he's got notifications enabled for mentions Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 4 minutes ago, Rick Brewster said: 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? You, in Paint.NET land. It’s not treated as header but as colour table consisting of three entries. Quote Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 If I were involved for myself, I’d just write “Paint.NET creates BI_BITFIELDS w/o colour table, check for it.” Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted November 26, 2023 Share Posted November 26, 2023 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. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 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 Quote Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 (edited) Also, as I said, old WinXP’s CLIPBRD.EXE expects those 12 bytes. But Clipboard Viewer is not critical software and does not check for buffer overruns, unlike Firefox. Edited November 26, 2023 by Mercury13 Quote Link to comment Share on other sites More sharing options...
Mercury13 Posted November 26, 2023 Share Posted November 26, 2023 (edited) 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 November 26, 2023 by Mercury13 More info Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted November 26, 2023 Share Posted November 26, 2023 Do you have a link to this code? Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.