99
1010from PIL import Image
1111
12+ from ani2xcur .config import LOGGER_COLOR , LOGGER_LEVEL , LOGGER_NAME
1213from ani2xcur .cursor_conversion .native_cursor .models import CursorFrame , CursorImage
14+ from ani2xcur .logger import get_logger
15+
16+ logger = get_logger (
17+ name = LOGGER_NAME ,
18+ level = LOGGER_LEVEL ,
19+ color = LOGGER_COLOR ,
20+ )
1321
1422CUR_MAGIC = b"\x00 \x00 \x02 \x00 "
1523PNG_MAGIC = b"\x89 PNG\r \n \x1a \n "
@@ -41,10 +49,13 @@ def parse_blob(blob: bytes) -> list[CursorFrame]:
4149 ValueError: 光标文件格式不受支持或文件内容损坏时抛出。
4250 """
4351 if blob .startswith (CUR_MAGIC ):
52+ logger .debug ("识别到 Windows CUR 光标文件" )
4453 return parse_cur (blob )
4554 if _is_ani (blob ):
55+ logger .debug ("识别到 Windows ANI 光标文件" )
4656 return parse_ani (blob )
4757 if blob .startswith (XCURSOR_MAGIC ):
58+ logger .debug ("识别到 Xcursor 光标文件" )
4859 return parse_xcursor (blob )
4960 raise ValueError ("Unsupported cursor file format" )
5061
@@ -67,6 +78,7 @@ def parse_cur(blob: bytes) -> list[CursorFrame]:
6778 raise ValueError ("Not a CUR file" )
6879 if image_count <= 0 :
6980 raise ValueError ("CUR file does not contain images" )
81+ logger .debug ("解析 CUR 文件: image_count=%s" , image_count )
7082
7183 entries_start = ICON_DIR .size
7284 entries_end = entries_start + image_count * ICON_DIR_ENTRY .size
@@ -94,6 +106,7 @@ def parse_cur(blob: bytes) -> list[CursorFrame]:
94106 )
95107 )
96108
109+ logger .debug ("CUR 文件解析完成: sizes=%s" , [image .image .size for image in images ])
97110 return [CursorFrame (images = images )]
98111
99112
@@ -147,6 +160,8 @@ def parse_ani(blob: bytes) -> list[CursorFrame]:
147160
148161 frame_count = frame_count or len (icon_frames )
149162 step_count = step_count or frame_count
163+ has_order_chunk = order is not None
164+ has_delay_chunk = delays is not None
150165 order = list (range (frame_count )) if order is None else order
151166 delays = [display_rate for _ in range (step_count )] if delays is None else delays
152167
@@ -155,6 +170,14 @@ def parse_ani(blob: bytes) -> list[CursorFrame]:
155170 if len (delays ) != step_count :
156171 raise ValueError (f"Wrong animation rate size: { len (delays )} , expected { step_count } " )
157172
173+ logger .debug (
174+ "解析 ANI 文件: frame_count=%s, step_count=%s, icon_frames=%s, has_seq=%s, has_rate=%s" ,
175+ frame_count ,
176+ step_count ,
177+ len (icon_frames ),
178+ has_order_chunk ,
179+ has_delay_chunk ,
180+ )
158181 sequence : list [CursorFrame ] = []
159182 for frame_index , delay in zip (order , delays ):
160183 if frame_index >= len (icon_frames ):
@@ -163,6 +186,7 @@ def parse_ani(blob: bytes) -> list[CursorFrame]:
163186 frame .delay = delay / 60
164187 sequence .append (frame )
165188
189+ logger .debug ("ANI 文件解析完成: sequence_frames=%s" , len (sequence ))
166190 return sequence
167191
168192
@@ -194,6 +218,7 @@ def parse_xcursor(blob: bytes) -> list[CursorFrame]:
194218 for _ in range (toc_size ):
195219 chunks .append (XCURSOR_TOC_CHUNK .unpack_from (blob , offset ))
196220 offset += XCURSOR_TOC_CHUNK .size
221+ logger .debug ("解析 Xcursor 文件: toc_size=%s" , toc_size )
197222
198223 images_by_size : dict [int , list [tuple [CursorImage , float ]]] = defaultdict (list )
199224 for chunk_type , chunk_subtype , position in chunks :
@@ -224,6 +249,7 @@ def parse_xcursor(blob: bytes) -> list[CursorFrame]:
224249
225250 if not images_by_size :
226251 raise ValueError ("Xcursor file does not contain images" )
252+ logger .debug ("Xcursor 文件尺寸集合: %s" , sorted (images_by_size ))
227253
228254 frame_counts = {len (images ) for images in images_by_size .values ()}
229255 if len (frame_counts ) != 1 :
@@ -238,6 +264,7 @@ def parse_xcursor(blob: bytes) -> list[CursorFrame]:
238264 raise ValueError ("Xcursor animations must use the same delay for every size in a frame" )
239265 frames .append (CursorFrame (images = images , delay = frame_items [0 ][1 ]))
240266
267+ logger .debug ("Xcursor 文件解析完成: frame_count=%s" , len (frames ))
241268 return frames
242269
243270
0 commit comments