pythonkivykivy-language

How to insert an image with rounded borders in Kivy while cropping it to keep its ratio?


I have a square image and I want to display it as background of a rounded rectangle. I want to avoid this image to be deformed. Here is a visual explanation of what I mean.

Here is an illustration image:

Explanation_Image

I tried to create a canvas and to set my image as the source of a RoundedRectangle to obtain the desired visual. Nevertheless the image is distorted to fit into the rectangle, which changes the ratio of the image. This is not what I want to obtain; is there a way to crop the image automatically? I tried to use the property fit_mode of Kivy 2.2 but it doesn't apply to RoundedRectangle.

Here is my Python file:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
  
class CustomImage(RelativeLayout):
    pass

class MyScreen(RelativeLayout):
    pass
  
kv = Builder.load_file("draft_question.kv")
  
class MyApp(App):
    def build(self):
        return kv
  
if __name__ == "__main__":
    MyApp().run()

Here is my .kv file:

#:kivy 2.2.1

<CustomImage>:

    canvas.before:
        RoundedRectangle:
            pos: (0,0)
            size: self.size
            source: "image.jpg"
            radius: [40,]
            #fit_mode: "cover"

MyScreen:
    CustomImage:
        size_hint: (0.6, 0.2)
        pos_hint: {"center_x": 0.5, "center_y": 0.5}

Thank you in advance for your help!


Solution

  • Another approach is to make your CustomImage extend Image and modify the kv rule for the basic Image class:

    <-CustomImage>:
        canvas:
            Color:
                rgba: self.color
            StencilPush
            RoundedRectangle:
                pos: self.pos
                size: self.size
                radius: [40]
            StencilUse
            Rectangle:
                texture: self.texture
                size: self.norm_image_size
                pos: self.center_x - self.norm_image_size[0] / 2., self.center_y - self.norm_image_size[1] / 2.
            StencilUnUse
            RoundedRectangle:
                pos: self.pos
                size: self.size
                radius: [40]
            StencilPop
            
    MyScreen:
        CustomImage:
            source: 'image.jpg'
            fit_mode: 'cover'
            size_hint: (0.6, 0.2)
            pos_hint: {"center_x": 0.5, "center_y": 0.5}
    

    The CustomImage class definition then becomes:

    class CustomImage(Image):
        pass
    

    If you need to affect the pos and size of the Rectangle, you can add Properties to the CustomImage class that can then be referenced in the kv.