@@ -36,6 +36,39 @@ def save_gif_and_print(bytes_io):
3636 b64 = base64 .b64encode (bytes_io .getvalue ()).decode ('utf-8' )
3737 print (f"BASE64:{ b64 } " )
3838
39+ def parse_frame_duration (arg ):
40+ if not arg :
41+ return 300
42+
43+ p_float = r"\d{1,4}(?:\.\d{1,3})?"
44+ if match := re .fullmatch (rf"({ p_float } )ms" , arg , re .I ):
45+ duration = float (match .group (1 ))
46+ elif match := re .fullmatch (rf"({ p_float } )s" , arg , re .I ):
47+ duration = float (match .group (1 )) * 1000
48+ elif match := re .fullmatch (rf"({ p_float } )fps" , arg , re .I ):
49+ fps = float (match .group (1 ))
50+ if fps <= 0 :
51+ raise Exception ("请使用正确的帧间隔格式,如:200ms、0.5s、2fps" )
52+ duration = 1000 / fps
53+ else :
54+ raise Exception ("请使用正确的帧间隔格式,如:200ms、0.5s、2fps" )
55+
56+ if duration <= 0 :
57+ raise Exception ("请使用正确的帧间隔格式,如:200ms、0.5s、2fps" )
58+ return max (20 , int (round (duration )))
59+
60+ def parse_grid_gif_args (arg ):
61+ parts = arg .split ()
62+ if not parts or parts [0 ] not in ["4" , "9" , "16" , "25" , "36" ]:
63+ raise Exception ("请提供宫格数量:#宫格转gif 4/9/16/25/36 [200ms/0.5s/2fps]" )
64+ if len (parts ) > 2 :
65+ raise Exception ("请使用正确格式:#宫格转gif 4/9/16/25/36 [200ms/0.5s/2fps]" )
66+
67+ total = int (parts [0 ])
68+ grid_size = {4 : 2 , 9 : 3 , 16 : 4 , 25 : 5 , 36 : 6 }[total ]
69+ duration = parse_frame_duration (parts [1 ] if len (parts ) == 2 else "" )
70+ return grid_size , duration
71+
3972def process_image ():
4073 cmd = sys .argv [1 ]
4174 arg = sys .argv [2 ]
@@ -179,6 +212,33 @@ def process_image():
179212 out = BytesIO ()
180213 frames [0 ].save (out , format = "GIF" , save_all = True , append_images = frames [1 :], loop = 0 , duration = duration )
181214 save_gif_and_print (out )
215+
216+ elif cmd == "宫格转gif" :
217+ grid_size , duration = parse_grid_gif_args (arg )
218+ image = imgs [0 ].image
219+ if image .width != image .height :
220+ raise Exception ("宫格转gif 需要正方形宫格图片" )
221+
222+ usable_side = image .width - (image .width % grid_size )
223+ if usable_side < grid_size :
224+ raise Exception ("图片尺寸过小,无法切分宫格" )
225+
226+ offset = (image .width - usable_side ) // 2
227+ if usable_side != image .width :
228+ image = image .crop ((offset , offset , offset + usable_side , offset + usable_side ))
229+
230+ frame_size = usable_side // grid_size
231+ frames = []
232+ for row in range (grid_size ):
233+ for col in range (grid_size ):
234+ left = col * frame_size
235+ top = row * frame_size
236+ frame = image .crop ((left , top , left + frame_size , top + frame_size )).copy ()
237+ frames .append (frame )
238+
239+ out = BytesIO ()
240+ frames [0 ].save (out , format = "GIF" , save_all = True , append_images = frames [1 :], loop = 0 , duration = duration )
241+ save_gif_and_print (out )
182242
183243 elif cmd == "四宫格" :
184244 img = imgs [0 ].square ()
@@ -227,4 +287,4 @@ def process_image():
227287 print (f"ERROR: { str (e )} " )
228288
229289if __name__ == "__main__" :
230- process_image ()
290+ process_image ()
0 commit comments