#coding=utf-8 # tkinter的Label控件以及三种布局管理方法 # https://www.cnblogs.com/jackie-lee/p/16191662.html # python 对话框图形界面显示图片 # https://blog.csdn.net/SAPmatinal/article/details/131818285 # 菜单设置 # https://blog.csdn.net/weixin_42272768/article/details/100808828 #opencv PIL格式互相转换 # https://blog.csdn.net/qq_19707521/article/details/78367617 #Pyinstaller 打包exe后,打开出现can‘t find package tkdnd 报错 #https://blog.csdn.net/qq_43079386/article/details/139725149 #1 BUILD # pyinstaller -F --windowed oplus_imageview.py --paths "C:\Program Files\Python311\lib\site-packages" --add-data "C:\Program Files\Python311\lib\site-packages\tkinterdnd2;tkinterdnd2" --hidden-import=tkinterdnd2 --hidden-import=tkdnd --clean # 2 DEBUG # 如果在打包过程中遇到问题,可以将输出重定向到一个日志文件中,以便详细检查: # pyinstaller -F ccc.py --paths C:\Program Files\Python311\lib\site-packages --add-data "C:\Program Files\Python311\lib\site-packages\tkinterdnd2;tkinterdnd2" --hidden-import=tkinterdnd2 --hidden-import=tkdnd --clean > build_log.txt 2>&1 # 这样所有输出(包括错误信息)都会保存到 build_log.txt 文件中,你可以查看该文件以获取详细的调试信息。 import tkinter as tk import tkinter.filedialog from tkinter import messagebox from tkinterdnd2 import DND_FILES, TkinterDnD from PIL import Image, ImageTk import cv2 import numpy as np import os import re image_show_width = 1024 image_show_height = 768 window_width = image_show_width+100 window_height = image_show_height+100 def NV21_P8_CONVERT_BGR(yuv_path,width,height): with open(yuv_path, 'rb') as f: yuvdata = np.fromfile(f, dtype=np.uint8) cv_format=cv2.COLOR_YUV2BGR_NV21 bgr_img = cv2.cvtColor(yuvdata.reshape(((int)(height*3/2), width)), cv_format) return bgr_img def NV21_P010_CONVERT_BGR(file_path, width10, height10): width8 = int(width10 / 2) height8 = height10 databuf10 = np.fromfile(file_path, dtype=np.uint16) databuf8 = (databuf10 / 4).astype(np.uint8); cv_format=cv2.COLOR_YUV2BGR_NV12 bgr_img = cv2.cvtColor(databuf8.reshape(((int)(height8*3/2), width8)), cv_format) return bgr_img def find_number_x_number(s): # 定义正则表达式模式 # pattern = r'\b(\d+)x(\d+)\b' # input_string = "IMG20240926193220_wh=4096x3072_ss=4096x3072_idx0_beforebeauty_doBokehEffect" pattern = r'ss\=(\d+)x(\d+)\_' #find _ss=4096x3072_ # 使用 re.findall() 查找所有匹配的内容 matches = re.findall(pattern, s) if len(matches) == 0: # input_string = "IMG20240926193220_4096x3072_idx0_beforebeauty_doBokehEffect" pattern = r'\_(\d+)x(\d+)\_' #find _4096x3072_ # 使用 re.findall() 查找所有匹配的内容 matches = re.findall(pattern, s) return matches def find_yuvimage_size(input_string): results = find_number_x_number(input_string) width = -1 height = -1 for match in results: # print(f"{match[0]}x{match[1]}") width = int(match[0]) height = int(match[1]) return width, height class ImageDropApp: def __init__(self, root): self.root = root self.root.title("图片查看器--IMAGE_VIEW_1.0") self.root.geometry(f"{window_width}x{window_height}+100+100") self.image_has_open = False # 创建标签用于显示图片 self.label = tk.Label(root, text="拖拽图片到这里", width=image_show_width, height=image_show_height, bg="lightgrey") self.label.pack(padx=0, pady=0, side="left", fill="both", expand = True) # 注册拖放功能 self.label.drop_target_register(DND_FILES) self.label.dnd_bind('<<Drop>>', self.on_drop) #设置打开关闭菜单 menubar = tk.Menu(root) filemenu=tk.Menu(menubar,activebackground='blue',tearoff=False) filemenu.add_command(label='打开文件',command=self.open_file) filemenu.add_command(label='另存文件',command=self.save_file_choosefolder) menubar.add_cascade(label='文件', menu=filemenu) menubar.add_command(label='退出',command=root.destroy) root.bind('<Control-o>',self.open_file) root.config(menu=menubar) def winshow_image(self, image_path): self.current_image_path = image_path self.image_format = "." + image_path.split('.')[-1] if self.image_format == ".yuv": #fine image size self.image_srcwidth, self.image_srcheight = find_yuvimage_size(image_path) print("image src size " + str(self.image_srcwidth) + "x" + str(self.image_srcheight)) if self.image_srcwidth == -1: messagebox.showinfo("prompt","not find yuv image size") #存储opencv原图 if self.image_srcwidth > 6000: print("input p010 yuv ") self.save_image_cv = NV21_P010_CONVERT_BGR(self.current_image_path, self.image_srcwidth, self.image_srcheight) self.image_srcwidth = int(self.image_srcwidth / 2) print("image src size p010_TO_p8 " + str(self.image_srcwidth) + "x" + str(self.image_srcheight)) else: self.save_image_cv = NV21_P8_CONVERT_BGR(self.current_image_path, self.image_srcwidth, self.image_srcheight) #opencv图像转换为PTL图像进行显示 self.show_image_PIL = Image.fromarray(cv2.cvtColor(self.save_image_cv,cv2.COLOR_BGR2RGB)) self.show_image_PIL = self.show_image_PIL.resize((image_show_width, image_show_height))#, Image.ANTIALIAS) # 将图片转换为Tkinter格式 photo = ImageTk.PhotoImage(self.show_image_PIL) # 更新标签内容以显示图片 self.label.config(image=photo) self.label.image = photo # 保持引用以避免被垃圾回收 self.image_has_open = True else: image = Image.open(image_path) self.image_srcwidth = image.size[0] self.image_srcheight = image.size[0] print("image src size " + str(self.image_srcwidth) + "x" + str(self.image_srcheight)) #存储opencv原图 self.save_image_cv = cv2.cvtColor(np.asarray(image),cv2.COLOR_RGB2BGR) # 调整图片大小以适应标签 self.show_image_PIL = image.resize((image_show_width, image_show_height))#, Image.ANTIALIAS) # 将图片转换为Tkinter格式 photo = ImageTk.PhotoImage(self.show_image_PIL) # 更新标签内容以显示图片 self.label.config(image=photo) self.label.image = photo # 保持引用以避免被垃圾回收 self.image_has_open = True def on_drop(self, event): # 获取文件路径 file_path = event.data #如果文件路径出现中文"新建文件夹",file_path会增加{file_path} if(len(file_path)> 2): if file_path[0] == "{" and file_path[-1] == "}": print("chinese path " + file_path) file_path = file_path[1:-1] print("remove {} in path " + file_path) if file_path.endswith(('.yuv', '.png', '.jpg', '.jpeg', '.gif', '.bmp')): print("find " + file_path) self.winshow_image(file_path) else: print(file_path + " format not support") messagebox.showinfo("prompt","this file format not support, please choose format like these , \ '.yuv', '.png', '.jpg', '.jpeg', '.gif', '.bmp'") def open_file(self): file_path = tkinter.filedialog.askopenfilename() if file_path.endswith(('.yuv', '.png', '.jpg', '.jpeg', '.gif', '.bmp')): print("find " + file_path) self.winshow_image(file_path) else: print(file_path + " format not support") messagebox.showinfo("prompt","this file format not support, please choose format like these , \ '.yuv', '.png', '.jpg', '.jpeg', '.gif', '.bmp'") def save_file_choosefolder(self): if self.image_has_open: defaultextension = ".png" init_current_image_name = self.current_image_path.replace(self.image_format, defaultextension) # print("src file " + init_current_image_name) savefolderpath = tkinter.filedialog.asksaveasfilename( title="保存图像", defaultextension=".png", initialfile=os.path.basename(init_current_image_name), initialdir=os.path.dirname(self.current_image_path), filetypes=(("PNG files", "*.png"), ("JPEG files", "*.jpg"), ("All files", "*.*"))) image_save_format = "." + savefolderpath.split('.')[-1] if savefolderpath: print("save file " + savefolderpath) # image = cv_imread(self.current_image_path) cv2.imencode(image_save_format, self.save_image_cv)[1].tofile(savefolderpath) else: print("please open image file") messagebox.showinfo("prompt","please open image file") if __name__ == "__main__": root = TkinterDnD.Tk() app = ImageDropApp(root) root.mainloop()
标签:查看器,python,image,show,file,format,path,self,图片 From: https://www.cnblogs.com/adong7639/p/18442460