Пример #1
0
class Homepage(Screen):
    def __init__(self, filepath, **kwargs):
        super(Homepage, self).__init__(**kwargs)

        self.filepath = filepath
        self.filename = filepath.replace('.', '/').split('/')[-2]

        Window.clearcolor = (0.2, 0.2, 0.2, 1)
        self.color_switch = Switch()
        self.canvas.add(self.color_switch)

        # LEFT IMAGE #
        im = Image.open(filepath).convert("RGBA")
        self.image = im.copy()
        width, height = self.image.size
        self.w_h_ratio = width / height
        self.image_rect = Rectangle(texture=CoreImage(self.filepath).texture)
        self.canvas.add(self.image_rect)

        # CENTER PIXELATED IMAGE & SLIDER #
        self.pixeate_image = im.copy()
        self.pixelate_rect = Rectangle()
        self.canvas.add(self.pixelate_rect)
        self.value = None
        self.pixel_slider = Slider(
            1, ((Window.width - self.image_rect.size[0]) // 2,
                (Window.height - self.image_rect.size[1]) // 2),
            self.pixelate_rect.size)

        self.generate_pressed = False
        self.generate_button = Rectangle(
            texture=CoreImage('./buttons/generate_button.png').texture)
        self.canvas.add(self.generate_button)

        # RIGHT DOMINO IMAGE #
        self.domino_image = Image.new(mode='RGBA',
                                      size=(width, height),
                                      color=(235, 74, 90, 150))
        data = BytesIO()
        self.domino_image.save(data, format='png')
        data.seek(0)
        self.domino_rect = Rectangle(
            texture=CoreImage(BytesIO(data.read()), ext='png').texture)
        self.canvas.add(self.domino_rect)

        self.label = Label()
        self.add_widget(self.label)

        self.imgSmall = None

        self.on_update()
        self.on_layout((Window.width, Window.height))

    def on_layout(self, winsize):
        width, height = self.image.size
        display_width = Window.width / 3.5
        self.image_rect.pos = (Window.width - display_width) / 20, (
            Window.height - 1 / self.w_h_ratio * display_width) // 2
        self.image_rect.size = (display_width,
                                1 / self.w_h_ratio * display_width)
        self.pixelate_rect.pos = (Window.width - display_width) / 2, (
            Window.height - 1 / self.w_h_ratio * display_width) // 2
        self.pixelate_rect.size = (display_width,
                                   1 / self.w_h_ratio * display_width)
        self.domino_rect.pos = 19 * (Window.width - display_width) / 20, (
            Window.height - 1 / self.w_h_ratio * display_width) // 2
        self.domino_rect.size = (display_width,
                                 1 / self.w_h_ratio * display_width)

        self.generate_button.pos = (
            Window.width - 0.75 * display_width) / 2, self.pixelate_rect.pos[
                1] - Window.height // 10 - 0.75 * display_width / 4.24
        self.generate_button.size = (0.75 * display_width,
                                     0.75 * display_width / 4.24)

        if self.pixel_slider in self.canvas.children:
            self.canvas.remove(self.pixel_slider)

        self.pixel_slider = Slider(1, self.pixelate_rect.pos,
                                   self.pixelate_rect.size)
        self.canvas.add(self.pixel_slider)

        self.label.center_x = Window.width / 2
        self.label.center_y = (Window.height + 1 / self.w_h_ratio *
                               display_width) // 2 + Window.height / 20
        self.label.font_size = str(Window.width // 170) + 'sp'

        self.color_switch.on_layout()

    def on_touch_down(self, touch):
        self.pixel_slider.on_touch_down(touch)

    def on_touch_up(self, touch):
        self.pixel_slider.on_touch_up(touch)
        self.color_switch.on_touch_up(touch)

        if self.color_switch.on:
            Window.clearcolor = (0.7, 0.7, 0.7, 1)
        else:
            Window.clearcolor = (0.2, 0.2, 0.2, 1)

        # handle generate button press
        if self.generate_button.pos[0] <= touch.pos[0] <= self.generate_button.pos[0] + self.generate_button.size[0] and \
        self.generate_button.pos[1] <= touch.pos[1] <= self.generate_button.pos[1] + self.generate_button.size[1]:
            self.generate_pressed = True
            self.generate_button.texture = CoreImage(
                './buttons/generating_button.png').texture

    def on_touch_move(self, touch):
        self.pixel_slider.on_touch_move(touch)

    def on_update(self):
        if not self.value == self.pixel_slider.on_update():
            self.value = self.pixel_slider.on_update()

            # Scale value based on dominoes produced
            width_in_pixels, height_in_pixels = self.calc_width_and_height()
            self.imgSmall = self.image.resize(
                (width_in_pixels, height_in_pixels), resample=Image.BILINEAR)

            # Scale back up using NEAREST to original size
            self.pixeate_image = self.imgSmall.resize(
                self.image.size, Image.NEAREST).convert("L")

            data = BytesIO()
            self.pixeate_image.save(data, format='png')
            data.seek(0)

            # update image
            self.pixelate_rect.texture = CoreImage(BytesIO(data.read()),
                                                   ext='png').texture

            # update label
            self.label.text = "This would require " + str(
                math.ceil(width_in_pixels * height_in_pixels / 2 /
                          55)) + " sets of dominoes ( " + str(
                              width_in_pixels * height_in_pixels //
                              2) + " dominoes in total )"

        # generate domino image on button press
        if self.generate_pressed:
            # create and update domino image
            self.domino_image = calculate.generate_domino_graphics(
                (ImageOps.invert(self.imgSmall.convert('RGB'))
                 if self.color_switch.on else self.imgSmall),
                self.imgSmall.size[0], self.imgSmall.size[1], self.filename,
                self.color_switch.on)
            self.domino_image.show()
            print("GENERATION COMPLETE")

            data = BytesIO()
            # if image will be too large for kivy texture, resize the image so that it can be rendered
            if self.domino_image.size[0] * self.domino_image.size[
                    1] > 256000000:
                print("must resize image! original size was:",
                      self.domino_image.size)
                self.domino_image.resize((16000, 16000),
                                         Image.NEAREST).save(data,
                                                             format='png')
            else:
                self.domino_image.save(data, format='png')
            data.seek(0)
            self.domino_rect.texture = CoreImage(BytesIO(data.read()),
                                                 ext='png').texture

            # return generate button to former state
            self.generate_button.texture = CoreImage(
                './buttons/generate_button.png').texture
            self.generate_pressed = False

    def calc_width_and_height(self):
        num_sets = self.value
        height_in_pixels = max(1, math.sqrt(55 * num_sets / self.w_h_ratio))
        # make height even so that number of pixels is even and dominoes can fill entire image
        height_in_pixels = height_in_pixels + 1 if round(
            height_in_pixels) % 2 == 1 else height_in_pixels
        # round values to nearest integer
        width_in_pixels = round(max(1, self.w_h_ratio * height_in_pixels))
        height_in_pixels = round(height_in_pixels)
        return (width_in_pixels, height_in_pixels)