diff --git a/latentblending/gradio_ui.py b/latentblending/gradio_ui.py index 5ae93bd..686f2c9 100644 --- a/latentblending/gradio_ui.py +++ b/latentblending/gradio_ui.py @@ -50,17 +50,19 @@ class BlendingFrontend(): self.list_seeds = [] self.list_images_preview = [] self.data = [] - self.idx_img_selected = None + self.idx_img_preview_selected = None + self.idx_img_movie_selected = None self.jpg_quality = 80 self.fp_movie = '' self.duration_single_trans = 10 - def preview_img_selected(self, data: gr.SelectData, button): - self.idx_img_selected = data.index - print(f"gallery image {self.idx_img_selected} selected, seed {self.list_seeds[self.idx_img_selected]}") - return gr.Button(interactive=True) + self.idx_img_preview_selected = data.index + print(f"preview image {self.idx_img_preview_selected} selected, seed {self.list_seeds[self.idx_img_preview_selected]}") + def movie_img_selected(self, data: gr.SelectData, button): + self.idx_img_movie_selected = data.index + print(f"movie image {self.idx_img_movie_selected} selected") def compute_imgs(self, prompt, negative_prompt): self.prompt = prompt @@ -70,7 +72,7 @@ class BlendingFrontend(): self.be.set_negative_prompt(negative_prompt) self.list_seeds = [] self.list_images_preview = [] - self.idx_img_selected = None + self.idx_img_preview_selected = None for i in range(self.nmb_preview_images): seed = np.random.randint(0, np.iinfo(np.int32).max) self.be.seed1 = seed @@ -85,15 +87,21 @@ class BlendingFrontend(): def get_list_images_movie(self): - return [entry["preview_image"] for entry in self.data[1:]] + return [entry["preview_image"] for entry in self.data] def init_new_movie(self): current_time = datetime.datetime.now() self.fp_movie = "movie_" + current_time.strftime("%y%m%d_%H%M") + ".mp4" self.fp_json = "movie_" + current_time.strftime("%y%m%d_%H%M") + ".json" - self.data.append({"settings": "sdxl", "width": bf.be.dh.width_img, "height": self.be.dh.height_img, "num_inference_steps": self.be.dh.num_inference_steps}) + + def write_json(self): + # Write the data list to a JSON file + data_copy = self.data.copy() + data_copy.insert(0, {"settings": "sdxl", "width": self.be.dh.width_img, "height": self.be.dh.height_img, "num_inference_steps": self.be.dh.num_inference_steps}) + with open(self.fp_json, 'w') as f: + json.dump(data_copy, f, indent=4) def add_image_to_video(self): if self.prompt is None: @@ -103,21 +111,45 @@ class BlendingFrontend(): self.init_new_movie() self.data.append({"iteration": self.idx_movie, - "seed": self.list_seeds[self.idx_img_selected], + "seed": self.list_seeds[self.idx_img_preview_selected], "prompt": self.prompt, "negative_prompt": self.negative_prompt, - "preview_image": self.list_images_preview[self.idx_img_selected] + "preview_image": self.list_images_preview[self.idx_img_preview_selected] }) - # Write the data list to a JSON file - with open(self.fp_json, 'w') as f: - json.dump(self.data, f, indent=4) - + self.write_json() self.idx_movie += 1 - self.prompt = None - return self.get_list_images_movie() + def img_movie_delete(self): + if self.idx_img_movie_selected is not None and 0 <= self.idx_img_movie_selected < len(self.data)+1: + del self.data[self.idx_img_movie_selected] + self.idx_img_movie_selected = None + else: + print("Invalid movie image index for deletion.") + return self.get_list_images_movie() + + def img_movie_later(self): + if self.idx_img_movie_selected is not None and self.idx_img_movie_selected < len(self.data): + # Swap the selected image with the next one + self.data[self.idx_img_movie_selected], self.data[self.idx_img_movie_selected + 1] = \ + self.data[self.idx_img_movie_selected+1], self.data[self.idx_img_movie_selected] + self.idx_img_movie_selected = None + else: + print("Cannot move the image later in the sequence.") + return self.get_list_images_movie() + + def img_movie_earlier(self): + if self.idx_img_movie_selected is not None and self.idx_img_movie_selected > 0: + # Swap the selected image with the previous one + self.data[self.idx_img_movie_selected-1], self.data[self.idx_img_movie_selected] = \ + self.data[self.idx_img_movie_selected], self.data[self.idx_img_movie_selected-1] + self.idx_img_movie_selected = None + else: + print("Cannot move the image earlier in the sequence.") + return self.get_list_images_movie() + + def generate_movie(self): print("starting movie gen") list_prompts = [] @@ -125,7 +157,7 @@ class BlendingFrontend(): list_seeds = [] # Extract prompts, negative prompts, and seeds from the data - for item in self.data[1:]: # Skip the first item as it contains settings + for item in self.data: list_prompts.append(item["prompt"]) list_negative_prompts.append(item["negative_prompt"]) list_seeds.append(item["seed"]) @@ -183,8 +215,7 @@ if __name__ == "__main__": prompt = gr.Textbox(label="prompt") negative_prompt = gr.Textbox(label="negative prompt") b_compute = gr.Button('generate preview images', variant='primary') - - # with gr.Row(): + b_select = gr.Button('add selected image to video', variant='primary') with gr.Row(): @@ -193,10 +224,6 @@ if __name__ == "__main__": , columns=[bf.nmb_preview_images], rows=[1], object_fit="contain", height="auto", allow_preview=False, interactive=False) - with gr.Row(): - b_select = gr.Button('add selected image to video', variant='primary', interactive=False) - - with gr.Row(): gr.Markdown("Your movie contains so far the below frames") with gr.Row(): @@ -204,18 +231,27 @@ if __name__ == "__main__": label="Generated images", show_label=False, elem_id="gallery" , columns=[20], rows=[1], object_fit="contain", height="auto", allow_preview=False, interactive=False) + + with gr.Row(): + b_delete = gr.Button('delete selected image') + b_move_earlier = gr.Button('move to earlier time') + b_move_later = gr.Button('move to later time') + with gr.Row(): b_generate_movie = gr.Button('generate movie', variant='primary') with gr.Row(): movie = gr.Video() - # bindings b_compute.click(bf.compute_imgs, inputs=[prompt, negative_prompt], outputs=gallery_preview) b_select.click(bf.add_image_to_video, None, gallery_movie) b_generate_movie.click(bf.generate_movie, None, movie) - gallery_preview.select(bf.preview_img_selected, None, b_select) + gallery_preview.select(bf.preview_img_selected, None, None) + gallery_movie.select(bf.movie_img_selected, None, None) + b_delete.click(bf.img_movie_delete, None, gallery_movie) + b_move_earlier.click(bf.img_movie_earlier, None, gallery_movie) + b_move_later.click(bf.img_movie_later, None, gallery_movie)