-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue with sixel rendering: stretched bands #17711
Comments
@lhecker for Atlas @PhMajerus do you by chance know whether you’re using the D2D or D3D backend? I think you can test it by switching to a font with a long single-glyph ligature (Cascadia Code works well) and trying to color it in multiple colors:
If it shows up in four colors, you’re on D3D. One color, D2D. |
This happens with both D2D and D3D. It's a lot easier to test now that we can switch between them manually in the "Rendering" settings. |
@DHowett the |
I did try to call that out. ;) |
Oops, sorry, forgot you mentioned switching to Cascadia Code in the meantime while I was testing. BTW, showing which rendering engine got selected when set to |
I think what's happening here is that the first image is actual 24 pixels high, due to the nature of sixel images (they're always a multiple of 6). This means it extends over two lines, and the second line's image slice is thus preallocated with a width of 40, even though it's entirely transparent at that point. Then when you write the second image immediately below that, it's actually overlapping the first, so the first image slice for that image will have a width of 40, but the second slice will have its expected width of 32. When it comes time to rendering, we've now got two lines that look like they ought to be the same, but the image slice for the first line has additional transparent padding that's making it wider. Ideally this shouldn't be a problem, but I think there are possibly rounding errors when we scale the image slices that results in them being misaligned. For the GDI renderer in particular, this calculation looks wrong. terminal/src/renderer/gdi/paint.cpp Lines 687 to 688 in 9c14367
I'm assuming it should be rounding, rather than truncating, although it may be more complicated than that. I don't know if the Atlas engine is affected in the same way, or there's something else involved there. |
On further investigation, I think the solution may be much simpler. The rounding shouldn't be an issue if the image slices were always a multiple of the virtual cell width, and they already would be if it weren't for this line: terminal/src/buffer/out/ImageSlice.cpp Line 68 in 1511d2c
But I'm not sure that's actually needed. I think it's the byte width of the image buffer that needs to be a multiple of 4, and that's already going to be the case if we're storing our pixels as I need to do some more tests to confirm, but dropping that line seems to fix the issue in both the GDI and Atlas renderers. |
At least the
So, I think removing that line should be safe. |
Yeah, the Windows DIB format uses a whole number of bytes per line. A monochrome DIB that's 12px wide will use 2 bytes and waste 4 bits per line. |
The 4 byte alignment thing is mentioned in the
|
@PhMajerus I forgot to say thank you for spotting this. The early testing is much appreciated. |
Yeah, I checked my DIB code and it's aligned on 4 bytes boundaries.
You're welcome, I really like the feature, and has been experimenting with it. Thanks for implementing it. Do you have some good reference or recommendations on interleaving text and sixel images? |
On a standard Sixel implementation that's what I would do, but on most Linux terminals you won't know how many columns the image will occupy (see below), so you won't know how far right to move the cursor. Some support a proprietary mode (8452) that should leave the cursor positioned to the right of the image, but that may still not be the correct row.
Again, if you only need to work with standard Sixel implementations, that would be perfect. That's the cell size of the VT340, and what real terminal emulators are likely to emulate. But that's not going to work on most Linux terminals, because their cell size will be dependent on whatever font size the user happens to have set at the time. They expect you to query the size every time you want to output an image, and then rescale the image to match. Personally I just don't bother trying to support non-standard terminals. There are VT libraries (like notcurses) that have some level of cross-platform image support, so it is doable, but I think they are more geared towards fullscreen apps. |
One other thing I forgot to mention: a 20 pixel high image has an effective height of 24 pixels, so be aware that it'll trigger a scroll on the last line of the page. The cursor will still remain on the starting row (now scrolled up), so your layout should be fine, but the scrolling may come as a surprise. If you want to avoid that scrolling, you'll need to limit the image height to 18 pixels, but that means you can't completely fill the line height. |
Windows Terminal version
Canary 1.22.2261.0
Windows build number
10.0.22631.4037 x64
Description of the problem
I believe I may have found an issue with sixels images rendering.
When displaying sixels images with a transparent background (by using
P0;1
and not drawing some pixels in any of the colors), it renders perfectly when displayed on its own.But when it gets close to another sixel image, added either on the previous line, or on the second line of the multi-line image with transparency, its width gets weird.
When the other sixel image is added above, the first band/line of the multi-line image gets slightly stretched.
When the other sixel image is appended after the second line of the multi-line image, that band gets stretched.
Note this also seems to happen in conhost, but with less visible stretching (only noticeable at some font sizes).
Steps to reproduce
Here is the repro text file: test.txt
Expected Behavior
The sixel images to keep their dimensions regardless of other contents displayed in the terminal.
Actual Behavior
Sixel images sometimes get distorted with some bands stretched when other contents is displayed near them.
The text was updated successfully, but these errors were encountered: