Skip to content
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

Add background_image_anchor #4167

Merged
merged 6 commits into from
Oct 30, 2021
Merged

Conversation

itepechi
Copy link
Contributor

@itepechi itepechi commented Oct 29, 2021

This PR adds two new options: background_image_anchor and background_image_layout clamped.

chicken_clamp_bottom_right

The story

We already have a nice option called background_image_layout. But there are situations where tiled and scaled are not enough. Let's take an example:

I want to show a cute kitty on the bottom edge of the screen, so I created a background image that matches the size of my window. Looks like the problem has been solved.

kitty_scaled

But once I change the size of the window, everything is messed up.

the_problem_with_scaled

This occurred because the size of the image is synchronized with the size of the window.

Since I don't want to squash my kitty, I changed background_image_layout to tiled, and created a new background image with a large padding to align it with size of the window.

However, this still did not solve the problem. When I enlarged the window, not only did my kitty move from the center, but their entire body appeared from the bottom of the window.

the_problem_with_tiled

Here we can take advantage of the options that are added in this PR.

I cropped the background image to the size of the area I wanted to show, and set background_image_anchor to bottom, background_image_layout to clamped.

Now, the problem is solved, and my kitty stays at the bottom of the window, no matter how small or large I make it.

problem_solved

I hope you like this.

Other examples

More natural tiling

background_image_layout tiled
# background_image_anchor center

bandana_current

background_image_layout tiled
background_image_anchor center

bandana_bgimage_options

Current process' logo at the bottom-right corner

background_image_layout clamped
background_image_anchor bottom-right
function on_preexec --on-event fish_preexec
  switch (string split -m1 ' ' "$argv")
    case nvim
      kitty @set-background-image --no-response &>/dev/null ~/.config/kitty/logo/nvim.png
    case podman
      kitty @set-background-image --no-response &>/dev/null ~/.config/kitty/logo/podman.png
    case '*'
      kitty @set-background-image --no-response &>/dev/null ~/.config/kitty/logo/unknown.png
  end
end

function on_prompt --on-event fish_prompt
  kitty @set-background-image --no-response &>/dev/null ~/.config/kitty/logo/fish.png &
    disown
end
dynamic_bgimage_update.mp4

@itepechi
Copy link
Contributor Author

itepechi commented Oct 29, 2021

Sorry for the PR with no description, i accidentally hit the enter key. I'm going to write it now.
Done.

@kovidgoyal
Copy link
Owner

I am fine with it in principle, I will review the code later when I have some time.

@kovidgoyal kovidgoyal merged commit e703103 into kovidgoyal:master Oct 30, 2021
@Elysium1436
Copy link

Elysium1436 commented Dec 1, 2021

Some distortions show up when on i3wm I, for example, open another terminal side by side.
2021-11-30-205322_1920x1080_scrot
2021-11-30-204758_142x182_scrot

It only shows up when I create another window and put them side by side.
I'm using nightly version.

@page-down
Copy link
Contributor

I found that the background image renders strangely when testing with the google logo png.

https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png

kitty --config=NONE -o 'background_image /tmp/google.png' -o 'background_image_layout clamped' -o 'background_image_anchor center'

kitty_bg_img_debug

@kovidgoyal
Copy link
Owner

@page-down ef07e29

@Elysium1436 I cannot reproduce in i3

@page-down
Copy link
Contributor

I cannot reproduce in i3

I can reproduce this issue on Linux.

Same command, same png image.


The usage mentioned by OP is nice, however it only works with a single kitty window. The process is associated with the kitty window, not OS window.

It would be nice if each window could have a separate background image. This way you can use a tiled background image for OS windows, and use a special logo background image for kitty windows.

This would be a nifty feature.

@Elysium1436
Copy link

Elysium1436 commented Dec 1, 2021

@kovidgoyal

I changed the wallpaper and it disappeared. Weird.

@page-down
Copy link
Contributor

page-down commented Dec 2, 2021

I also found that this did not occur today.
After trying, I found a way to reproduce the issue consistently.

Install today's nightly version. Execute the command I mentioned above and keep resizing the window after it opens. It will randomly appear normal or broken. This can be reproduced under Ubuntu Latest LTS LiveCD VM.

The images rendered under macOS are all binary identical.

@kovidgoyal
Copy link
Owner

I decided to implement per window logos instead. And that fixes @page-down issue as well

@page-down
Copy link
Contributor

I tried the new window logo feature and it is very useful.
However, I found inconsistent rendering after changing the window size under macOS. Similar to the previous issue with Linux, but less obvious. No longer remains binary identical.

kitty_window_logo_issue.png

The issue is also reproduced under Linux X11, with pixel-level jaggies.


Since I have monitor hardware with different DPI, I also tested the usage at HiDPI.

I found that the logo did not stay at the same visual size when moving the window to a different DPI monitor.

This may require specifying the scale level of the image, either with a separate parameter or from the file name, for example logo/beam-cursor@2x.png in the source repository. This allows the 2x logo to be displayed pixel by pixel on a 200% scaled display. Displayed at 50% on a 100% scaled LowDPI monitor.

Then I found out that while background_image can be visually consistent in size across DPI, it does not support HiDPI. The background image image@2x.png uses 4 pixels to display one image pixel on a 4K monitor.


Finally, to make this feature complete, it would be nice to be able to specify the offset values of the coordinates x-axis and y-axis, which also support HiDPI scaling.

Sometimes users may want to set x y offset values, either a fixed value (with HiDPI scaling), or percentage values. The percentage value can be used to, for example, show the percentage of the file download progress, and the percentage image (that maybe dynamically generated) will move on an edge according to the progress.


And for the original anchor function, I think it makes sense to be able to center the tiled image.

background_image_layout tiled
background_image_anchor center

@kovidgoyal
Copy link
Owner

Sorry I've spent about as much time on this as I care too. If you want
further improvements, patches are welcome.

@page-down
Copy link
Contributor

I troubleshot and found that the jaggies were caused by rescaling the image. It rescales even when the image is smaller than the window size.

I think I can set the original scaling of the logo, compare the current screen DPI, and calculate the x y pixel coordinates. How can I draw the image at the coordinates as is?

@kovidgoyal
Copy link
Owner

kovidgoyal commented Dec 5, 2021 via email

@kovidgoyal
Copy link
Owner

Oh and in send_logo_to_gpu you can try passing false for linear that should get etter interpolation.

@page-down
Copy link
Contributor

As far as I understand, it's basically what you're describing. After the floating point is calculated and converted to actual rendered pixels, it may differ from the original image width and height by one pixel. It is this one pixel that causes the image to be rescaled.

draw_window_logo(...) {
    ...
    GLfloat logo_width_gl = 2.f * ((float)wl->instance->width) / os_window->viewport_width;
    GLfloat logo_height_gl = 2.f * ((float)wl->instance->height) / os_window->viewport_height;
  • One approach is to compute the converted pixel integer value, compensating for floating point by one pixel, as the viewport width allows.
  • Another is to see if it is possible for OpenGL to render per pixel, skipping the floating point coordinate conversion, when rescaling is not required.

Thanks for the heads up on the workaround, but rendering the logo will not involve rescaling in most scenarios. There is almost no need to introduce various better resampling algorithms, after all, there will be performance penalty.

@kovidgoyal
Copy link
Owner

kovidgoyal commented Dec 5, 2021 via email

@kovidgoyal
Copy link
Owner

Here this should clear it up for you: https://www.realtimerendering.com/blog/the-center-of-the-pixel-is-0-50-5/

@page-down
Copy link
Contributor

page-down commented Dec 5, 2021

Thank you for the reference link about coordinate calculation.

I tried GL_NEAREST and changing the window size under macOS does not render jaggies randomly anymore. The pixels remain the same as the original image.
However, under Linux, the previous severe jaggedness issue appears again.

No OpenGL doesn't render per pixel. What you can do is set a
orthographic transform and use pixel co-ords as your vertices ...

I don't know much about image rendering. Is there something like GLSL texelFetch() that can be used? I thought this was a solved problem in image rendering, but I didn't expect it to be so tricky.

If all existing solutions run out, then one has to go to tweaking floating numbers.


A floating point projection to the pixel plane would result in resampling, which I can understand. However it is so strange that it causes the image to change randomly when the window size is changed. The reason may be that the strict image centering (0.5 pixel) cannot be reflected in the integer pixel display interface.

For example, you can perfectly center a 1 pixel image in a window that is only 3 pixels wide. [ 0, 1, 0 ]
But it is definitely not possible to center a 2 pixel image, which will lead to image resampling. [ 0.5, 1, 0.5 ]
It would be possible to find the starting x-coordinate and then offset the floating point projection by 0.5 pixels. This will render the image starting at the second pixel. [ 0, 1, 1 ]

@kovidgoyal
Copy link
Owner

See if this does the trick: 525a32b

@page-down
Copy link
Contributor

It seems that the issue still exists.

It is worth noting that by using -o window_logo_position=top-left, instead of centering, the image will not change after the window is resized, for obvious reasons.

@kovidgoyal
Copy link
Owner

Use the same trick I did for size, for position as well and you should be
fine.

@page-down
Copy link
Contributor

page-down commented Dec 5, 2021

Yes, thank you. Tested on macOS / Linux and everything works fine.

I continued testing rc set-window-logo and found that it outputs a lot of kitty-cmd{"ok": true}. This will happen in the shell or in the kitty shell.

-cmd{"ok": true}^[\^[P@kitty-cmd{"ok": true}^[\^[P@kitty-cmd{"ok": true}^[\^[P@kitty-cmd{"ok": true} ...

In the kitty shell, there is no chance to do os.path.expanduser() image path resolution because imghdr.what() has thrown an exception.

Unhandled error:
...
  File ".../imghdr.py", line 16, in what
    f = open(file, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: '~/path/to/png'

Executing kitty @ set-window-logo does not have this problem. This is because the shell does path expansion. I'm thinking about doing path resolution first and then checking if the image is valid.

EDIT: I noticed that the above issues have been fixed in the latest master branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants