Skip to content

Instantly share code, notes, and snippets.

@benni12er
Last active July 4, 2022 21:39
Show Gist options
  • Select an option

  • Save benni12er/95a45eb168fc33a4fcd2d545af692dad to your computer and use it in GitHub Desktop.

Select an option

Save benni12er/95a45eb168fc33a4fcd2d545af692dad to your computer and use it in GitHub Desktop.
Kivy image fit crop in frame/layout automatically
from kivy.graphics.context_instructions import Color
from kivy.graphics.vertex_instructions import Rectangle
from kivy.properties import StringProperty, Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import Image
from kivy.uix.widget import Widget
"""
By Benedikt Zwölfer
Example usage:
BoxLayout:
size_hint_y: None
height: dp(200)
orientation: 'vertical'
FitImage:
size_hint_y: 3
source: 'images/img1.jpg'
FitImage:
size_hint_y: 1
source: 'images/img2.jpg'
Works with KivyMD
"""
class FitImage(BoxLayout):
source = StringProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_once(self._late_init)
def _late_init(self, *args):
self.container = Container(self.source)
self.add_widget(self.container)
class Container(Widget):
def __init__(self, source, **kwargs):
super().__init__(**kwargs)
self.bind(size=self.adjust_size)
self.image = Image(source=source)
def adjust_size(self, *args):
(par_x, par_y) = self.parent.size
if par_x == 0 or par_y == 0:
with self.canvas:
self.canvas.clear()
return
par_scale = par_x / par_y
(img_x, img_y) = self.image.texture.size
img_scale = img_x / img_y
if par_scale > img_scale:
(img_x_new, img_y_new) = (img_x, img_x / par_scale)
else:
(img_x_new, img_y_new) = (img_y * par_scale, img_y)
crop_pos_x = (img_x - img_x_new) / 2
crop_pos_y = (img_y - img_y_new) / 2
subtexture = self.image.texture.get_region(crop_pos_x, crop_pos_y, img_x_new, img_y_new)
with self.canvas:
self.canvas.clear()
Color(1, 1, 1)
Rectangle(texture=subtexture, pos=self.pos, size=(par_x, par_y))
@HeaTTheatR
Copy link

@BernardinD
Copy link

I'd like to request that a binding to the Image source be added as well so that it can be dynamically updated. I'm not able to do it from kv using container.image.soure for some reason

@faziletgokbudak
Copy link

Instead of Rectangle, when I make it RoundedRectangle, the whole texture is shown.

@Nobby89
Copy link

Nobby89 commented Apr 1, 2022

i am new to this so forgive me.

i am using source to tell me the name of the file used as the source, but it does not always give me the correct name.

it gives me the name of the previous file selected, if i do more then one.

can you have a look at this please?

@gikpro
Copy link

gikpro commented Apr 21, 2022

Hello ! Why you use Image instead of AsyncImage widget ?

@Nobby89
Copy link

Nobby89 commented Apr 22, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment