From b3f0fd4ce34900780243888a768d6c8b221104fa Mon Sep 17 00:00:00 2001 From: Nymiro Date: Mon, 20 Oct 2025 22:07:29 +1300 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20HEIC=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=80=BB=E8=BE=91=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20ID=20=E6=98=A0=E5=B0=84=E5=B9=B6=E4=BC=98=E5=8C=96=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E5=85=B3=E8=81=94=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 10244 -> 8196 bytes __pycache__/base.cpython-314.pyc | Bin 8312 -> 8342 bytes __pycache__/builder.cpython-314.pyc | Bin 8201 -> 8206 bytes __pycache__/heic_file.cpython-314.pyc | Bin 27814 -> 28196 bytes __pycache__/heic_types.cpython-314.pyc | Bin 35733 -> 43427 bytes __pycache__/parser.cpython-314.pyc | Bin 3802 -> 3807 bytes .../__pycache__/apple_handler.cpython-314.pyc | Bin 1171 -> 1176 bytes .../__pycache__/base_handler.cpython-314.pyc | Bin 1111 -> 1116 bytes .../samsung_handler.cpython-314.pyc | Bin 1388 -> 1393 bytes heic_file.py | 19 ++- heic_types.py | 142 +++++++++++++----- main.py | 12 +- samsung_apple_compatible.HEIC | Bin 4596996 -> 4596991 bytes samsung_apple_compatible.MOV | Bin 2908726 -> 2908726 bytes 14 files changed, 117 insertions(+), 56 deletions(-) diff --git a/.DS_Store b/.DS_Store index 6928477444bf723231804e9cbfc6bfdc95604052..bcef83591bdea8578196cf00cbafb0dab8809e7f 100644 GIT binary patch delta 124 zcmZn(XmOBWU|?W$DortDU;r^WfEYvza8E20o2aMAD7!IWH$S87WFCRVlluk5Hx~%* zX55@Dtin7wUtDivnF*61Gf+7YNN@uQSCGz)h2NPc^Q#1MFha~@m>kbDb+V(F)?`7k JI*2wyCIAaE8Z!U@ literal 10244 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 Bf4Beu diff --git a/__pycache__/builder.cpython-314.pyc b/__pycache__/builder.cpython-314.pyc index 3110ba9100006f7136d6705fee6e007d50e42ed7..feb6d2948184210a8db4faa12e7fa08a6034980c 100644 GIT binary patch delta 35 pcmeBl=yTxG=HumJ0D`HXH*!s5WHg<;kWqpqIX@+J^A5&9IRK%x3CREe delta 30 kcmeBk=yc%H=HumJ0D`4wH*!s5WHgw(kWpguKE?n!0CbZG6aWAK diff --git a/__pycache__/heic_file.cpython-314.pyc b/__pycache__/heic_file.cpython-314.pyc index 858a4a07b4597893ff6242b7f4170a531958ac60..7e01dd818f7a10c140a713402312635b9e99fe9c 100644 GIT binary patch delta 2386 zcmZ`*3rt(*75@Kg8w?oyeqkHi*tj-0#KZw?4CzP%h4Kh-;VK~(5d|x8vcTOnS(-M> z($Q{R)uv6))KP8HBCXn*PTCq>q-5E&E$y0CRkwvU!GyJHvxlZs+hmWm9m`(l_amXx z_DlD>|KptRoc}zo?su-!7v7~cO*Pe(1jnxRj}H8P}t78Hm!tNmkmZ-b@V3A zqV&z;S`QhQ0K41`v>8rYjcWA~E<}!Sy=p=PHLr%2dV}f^H=re?g47W~1E<|FeYj+C zYjGlIk;24{w8A5wsa0u6Zv(39cP8aPcnQ#G<|*%g#;)ENIKbyMnbPT3oAV zaJMjc=SUaasMGt^r5j)YpgOB89&OB+OOgY-^Sf}R!KT^}`#N~9puEV2e#ufxrEdQ$b&C(0TN7Z_l%k<7D=B6Y&Ps1=@UJYiPl zEu|*sQnNE@@gWpgm8Fw&U~lqMH}o_esd|!WKE>cT{H*D>bRJ#^`pOuo&j(9E2mCP@ zqbrhs({@=jTS@Bbzm<4CaiuYK&C!{0^uO)sUsK4OH8&jn&-7$vL~F`uyjL~e>yG}c zf>hhH1P`++cs$hW%(2_8w8b)QeQ&q*t;ulpG2yhjoQ%|N&Q?kvgbvUL+`f!EeAOLZ zP^<)+Gl8z9K-WUeiY@Ts-ep^4CA{sziEH8Eg`TVS(26~nv4@xJ;g@@s?H#!aQol8; zBaI!;^eh{EIWxH{_E!t~bHx-{)!$ zkQMmPv!ja$Y3v`Yj$(OShHS3`Ico0hrkLT8z9=1oC;A4s85#U*xL#WC%hB?)*ob9( z8Qj2cYVJOd68k$pfbKNI(*s7}Yf`Dtuk<%oebELDQL+5nzGt6L>@qMUfA4q4R1Qw&(WieG`Lg)Pl>BI2d z`#+%9;qlQhotJ(*Ixi23$57)e74zh>Lf1ZrTlqT_lXJ4zyO7$`j7$rAzOjXAiR;YR zMx6}_E$J}1zayN2Yx?^j!$;Fu;3z`2R!mKFa@>=@QLzAnau{&+k1$AA^pB z!}>KmT9u2*$>~-3!P(SIpt5lLc@PqzD&|ok9q+^U65H_BA0|Ge^kZ1EG|-o%TNAga zj$klFicl&}1t=#6=}Ry+`5Ug1!lq6yU6dvsxLe`=bXkk#OsRZBMPGoQ?Ef+f_Z)bd z(qnKf6^VSGdGI3!ml!NDxXj=+26@6iuvsqyMkrP@FhS43qbl~-lg4e9DInr Z4)+}T2)~HY&rYbj%c*6JFwFlD{RceOE;|4K delta 2123 zcmZ`)eN0nV6u6`x;qhX5g?1r_ zS3jCiOTL_YoWdHkN;54QUcq(#1fSczaMqkk&!A+6y>=@dMCp*awJ;t5K}g&0(`%^5 zlu!^7D1!HvYauXSrO?EW;bN{s|JJ)=o$=u@XTeWO(H3#w{aRLKYlygIB?SwvSzB6?Vz@6u!oI?V7*G&Ho46$W@E@6}2} zf;eJqeHMa{pk6SvQBNWcu4)p@7K{P=6xA~kPYhtmH|vf6;gbV(`Tl_%AxFse^%2r} ziVzE#633K?ZX<0pV#1$!vM)iifv}7d)lS$(EP@&N<{@7$o}auuYw*MEcly%r4$}WbQU5JZdXt?UeFZCVhhGc?1fa zsbF?$V5ze_NgF0Eo3zK7%}KjlJv2GSd5gp@Bm<+Xie3hzTclRl?S4N?5e@am)E&`i z&)RTDZ@8yB3T2*|)DCMro0YrJLwpBrd+yKyI6upY>U*>DAk$k$4@kA%#R}_$lGq%B z`JZ|Yd&UYEUUe+G=4iO&Xt-i++|~F%3Fl{5WgRWO=JsE5`^PipKU5G?;RB`Qp0l2o z7ZhGAsQ96v;z0U!v+HQfxY>8z;<;uizGNvLu05N6wWM*}5_p(I-2MmYq+s5@%5k0Z zp_a@jpU}b2#ag-&9v3?oHc;ZNr&0DsedTJ-<0(O# zl34i#=No1ueg-=jw_;tWSFA?KrI7h0c61UUiZeu3=ZrVpUeo8?J-F11YRCHhu9BwkeaGf5SOj;PTsNhyzYRXbV>J>O= z)sx56r-Rb^j5K^lP#ku^3hj(zoFBs_8lV&^X46 zp^nZNzo94G?Mji0FaY;g6{WI-I#^ zCT5j~9c$|75xBDEHlK|8xbcv5bM1np+<(rwsAO)_ri}Ors0i<%L(*t?FQrdl`9`1b zGscgf0V00G;5!B*49+o#6aK=aDh7;DR5Q@S=*B)Z`{qB0fBBzOLDi-$bQI2QdQ9zb Ss;f=2MM;g12tyJ7r^(-g9qPyc diff --git a/__pycache__/heic_types.cpython-314.pyc b/__pycache__/heic_types.cpython-314.pyc index c80a68d22aa994a1f3c872f9ec663c5b56ef2a23..c928ed1617e5d8018d5745fd4834a529782e6085 100644 GIT binary patch delta 16278 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 delta 9834 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 diff --git a/__pycache__/parser.cpython-314.pyc b/__pycache__/parser.cpython-314.pyc index ce7ec7d26f1752c076eea8e6dd400ecf6b220902..d1fbb581ffb88e2daf045102d1d655a8f6005888 100644 GIT binary patch delta 54 zcmca5dta7In~#@^0SKmk-pDnNN!CO^v^ce>SU;~aH?t^T-z7h}G&eP`q*y;WKP7eZ I0VXLP0Ll3g)&Kwi delta 49 zcmcaFdrOu}n~#@^0SF4FZ{(WCB%!Y#TAW%`te;nzn^}~v?~SU;~aH?t^T-z7h}G&eP`q*y;WKP7eZ IZ^ju+0I<;#7ytkO delta 48 zcmbQiIhm77n~#@^0SG+vH*(!%l(5$iElw>e*3YZV%`D2-cgasK%}vcKDc;01g9!jF CF%EeE diff --git a/handlers/__pycache__/base_handler.cpython-314.pyc b/handlers/__pycache__/base_handler.cpython-314.pyc index 95a9e553415652894973c8ddc842125075206e2c..ebcc62d53f34de9a7dc6333f87ff6af6fba6f351 100644 GIT binary patch delta 54 zcmcc4afgFTn~#@^0SKmk-pDnFQPx>Mv^ce>SU;~aH?t^T-z7h}G&eP`q*y;WKP7eZ IKE|0$0K%*iBme*a delta 49 zcmcb^ah-!pn~#@^0SG4MZ{(W8C}F1`TAW%`te;nzn^}~v?~ bytes: class ItemLocation: def __init__(self, item_id): self.item_id = item_id + self.data_reference_index = 0 + self.base_offset = 0 + self.construction_method = 0 + self.extent_indices = [] + self.raw_extents = [] # (relative_offset, length) # extents 存储 (absolute_offset, length) self.extents = [] @@ -81,9 +86,11 @@ class ItemLocationBox(FullBox): loc = ItemLocation(item_id) if (self.version == 1 or self.version == 2) and current_pos + 2 <= len(stream): + loc.construction_method = struct.unpack('>H', stream[current_pos:current_pos+2])[0] current_pos += 2 if current_pos + 2 > len(stream): break + loc.data_reference_index = struct.unpack('>H', stream[current_pos:current_pos+2])[0] current_pos += 2 base_offset = 0 @@ -91,6 +98,7 @@ class ItemLocationBox(FullBox): if current_pos + self.base_offset_size > len(stream): break base_offset = _read_int(stream, current_pos, self.base_offset_size) current_pos += self.base_offset_size + loc.base_offset = base_offset if current_pos + 2 > len(stream): break extent_count = struct.unpack('>H', stream[current_pos : current_pos+2])[0] @@ -99,6 +107,7 @@ class ItemLocationBox(FullBox): for __ in range(extent_count): if (self.version == 1 or self.version == 2) and self.index_size > 0: if current_pos + self.index_size > len(stream): break + loc.extent_indices.append(_read_int(stream, current_pos, self.index_size)) current_pos += self.index_size if current_pos + self.offset_size > len(stream): break @@ -109,6 +118,7 @@ class ItemLocationBox(FullBox): extent_length = _read_int(stream, current_pos, self.length_size) current_pos += self.length_size + loc.raw_extents.append((extent_offset, extent_length)) loc.extents.append((base_offset + extent_offset, extent_length)) self.locations.append(loc) @@ -134,58 +144,81 @@ class ItemLocationBox(FullBox): else: content_stream.write(struct.pack('>I', len(self.locations))) + original_mdat_end_offset = original_mdat_offset + original_mdat_size + original_meta_end_offset = original_meta_offset + original_meta_size + + def _adjust_absolute_offset(original_offset: int) -> int: + if original_offset == 0: + return 0 + if original_mdat_offset <= original_offset < original_mdat_end_offset: + return original_offset + mdat_offset_delta + if original_meta_offset <= original_offset < original_meta_end_offset: + return original_offset + meta_offset_delta + return original_offset + for loc in self.locations: item_id_size = 2 if self.version < 2 else 4 content_stream.write(_write_int(loc.item_id, item_id_size)) if (self.version == 1 or self.version == 2): - content_stream.write(struct.pack('>H', 0)) + content_stream.write(struct.pack('>H', loc.construction_method & 0xFFFF)) - content_stream.write(struct.pack('>H', 0)) + content_stream.write(struct.pack('>H', loc.data_reference_index)) if self.base_offset_size > 0: - content_stream.write(_write_int(0, self.base_offset_size)) - - content_stream.write(struct.pack('>H', len(loc.extents))) + new_base_offset = _adjust_absolute_offset(loc.base_offset) + content_stream.write(_write_int(new_base_offset, self.base_offset_size)) + else: + new_base_offset = 0 - for (original_offset, length) in loc.extents: - if (self.version == 1 or self.version == 2) and self.index_size > 0: - content_stream.write(_write_int(0, self.index_size)) - - # !!! 魔法发生的地方 !!! - new_absolute_offset = original_offset - original_mdat_end_offset = original_mdat_offset + original_mdat_size - original_meta_end_offset = original_meta_offset + original_meta_size - - if original_offset == 0: - new_absolute_offset = 0 # 保持 0 偏移量 - - # 检查偏移量是否落在 *原始* mdat 盒区域内 - elif (original_mdat_offset <= original_offset < original_mdat_end_offset): - # 这是一个指向 mdat 的偏移量,应用 mdat 增量 - new_absolute_offset = original_offset + mdat_offset_delta - - # pyheic_struct_副本/heic_types.py + extents_to_process = loc.raw_extents if loc.raw_extents else [ + (max(absolute_offset - loc.base_offset, 0), length) + for absolute_offset, length in loc.extents + ] + content_stream.write(struct.pack('>H', len(extents_to_process))) - # 检查偏移量是否落在 *原始* meta 盒区域内 - elif (original_meta_offset <= original_offset < original_meta_end_offset): - # 这是一个指向 meta 内部的偏移量 (例如 EXIF) - # (*** 错误修正 ***) - # 它只应该被 *meta 盒之前* 的数据增长所平移。 - # 在我们的 builder.py 逻辑中, 'meta_offset_delta' 正是这个值 (即 ftyp 盒的增长)。 - new_absolute_offset = original_offset + meta_offset_delta + new_extents_absolute = [] + new_extents_relative = [] + new_extent_indices = [] + + for idx, (original_relative_offset, length) in enumerate(extents_to_process): + if (self.version == 1 or self.version == 2) and self.index_size > 0: + extent_index = loc.extent_indices[idx] if idx < len(loc.extent_indices) else 0 + content_stream.write(_write_int(extent_index, self.index_size)) + new_extent_indices.append(extent_index) - # else: - # 这是一个指向其他地方 (如 ftyp) 的偏移量,我们假设它不动 - # new_absolute_offset 保持等于 original_offset + original_absolute_offset = loc.base_offset + original_relative_offset + new_absolute_offset = _adjust_absolute_offset(original_absolute_offset) + + if original_absolute_offset == 0: + new_absolute_offset = 0 # 保持 0 偏移量 # 最后的安全检查,防止打包负数 if new_absolute_offset < 0: print(f" Warning: Calculated a negative offset ({new_absolute_offset}) for item {loc.item_id}. Setting to 0.") new_absolute_offset = 0 + + if self.base_offset_size > 0: + new_relative_offset = new_absolute_offset - new_base_offset + else: + new_relative_offset = new_absolute_offset + + if new_relative_offset < 0: + print(f" Warning: Calculated a negative relative offset ({new_relative_offset}) for item {loc.item_id}. Setting to 0.") + new_relative_offset = 0 + new_absolute_offset = new_base_offset - content_stream.write(_write_int(new_absolute_offset, self.offset_size)) + content_stream.write(_write_int(new_relative_offset, self.offset_size)) content_stream.write(_write_int(length, self.length_size)) + + new_extents_absolute.append((new_absolute_offset, length)) + new_extents_relative.append((new_relative_offset, length)) + + loc.base_offset = new_base_offset + loc.extents = new_extents_absolute + loc.raw_extents = new_extents_relative + if new_extent_indices: + loc.extent_indices = new_extent_indices self.raw_data = content_stream.getvalue() print(" 'iloc' box content successfully rebuilt.") @@ -214,6 +247,7 @@ class ItemInfoEntryBox(FullBox): self.item_name: str = "" # UTF-8 string self.content_type: Optional[str] = None self.content_encoding: Optional[str] = None + self._has_protection_field: bool = True super().__init__(size, box_type, offset, raw_data) def _post_parse_initialization(self): @@ -250,6 +284,7 @@ class ItemInfoEntryBox(FullBox): pos += 4 remaining = len(stream) - pos + self._has_protection_field = False if remaining >= 6: candidate_protection = struct.unpack('>H', stream[pos:pos+2])[0] candidate_type = stream[pos+2:pos+6] @@ -257,17 +292,20 @@ class ItemInfoEntryBox(FullBox): if candidate_protection <= 0x00FF and b'\x00' not in candidate_type: # 标准顺序: 2 字节保护索引 + 4 字节类型 self.item_protection_index = candidate_protection + self._has_protection_field = True pos += 2 type_bytes = candidate_type pos += 4 else: # 三星文件: 直接写入类型 (如 'hvc1'),缺少保护索引 self.item_protection_index = 0 + self._has_protection_field = False type_bytes = stream[pos:pos+4] pos += 4 elif remaining >= 4: # 某些三星文件缺少 2 字节的保护索引字段, 直接紧跟 4 字节类型 self.item_protection_index = 0 + self._has_protection_field = False type_bytes = stream[pos:pos+4] pos += 4 else: @@ -336,7 +374,8 @@ class ItemInfoEntryBox(FullBox): elif self.version == 2: content.write(struct.pack('>I', self.item_id)) - content.write(struct.pack('>H', self.item_protection_index)) + if self._has_protection_field: + content.write(struct.pack('>H', self.item_protection_index)) # item_type 必须是 4 字节的 4CC,若不足则以 NUL 填充 content.write(self.item_type.encode('ascii', errors='ignore')[:4].ljust(4, b'\x00')) content.write(item_name_bytes_to_write) @@ -458,13 +497,25 @@ class ImageSpatialExtentsBox(FullBox): return content.getvalue() # --- ItemPropertyAssociationEntry (DataClass) --- +class ItemPropertyAssociation: + def __init__(self, property_index: int, essential: bool): + self.property_index = property_index + self.essential = essential + + def __repr__(self): + flag = '!' if self.essential else '' + return f"{flag}{self.property_index}" + + class ItemPropertyAssociationEntry: def __init__(self, item_id, association_count): self.item_id = item_id self.association_count = association_count - self.associations = [] + self.associations: List[ItemPropertyAssociation] = [] + def __repr__(self): - return f"" + return (f"") # --- ItemPropertyAssociationBox --- # ('ipma') @@ -500,10 +551,14 @@ class ItemPropertyAssociationBox(FullBox): prop_size = 2 if is_large_property_index else 1 if pos + prop_size > len(stream): break assoc_value = _read_int(stream, pos, prop_size) + essential_flag = 0x8000 if prop_size == 2 else 0x80 property_index = assoc_value & (0x7FFF if prop_size == 2 else 0x7F) + is_essential = (assoc_value & essential_flag) != 0 pos += prop_size if property_index > 0: - entry.associations.append(property_index) + entry.associations.append( + ItemPropertyAssociation(property_index, is_essential) + ) self.entries[item_id] = entry except struct.error: print("Warning: Failed to parse 'ipma' box. Content may be truncated.") @@ -521,9 +576,14 @@ class ItemPropertyAssociationBox(FullBox): content.write(_write_int(item_id, item_id_size)) content.write(struct.pack('>B', len(entry.associations))) - for assoc_index in entry.associations: + for assoc in entry.associations: prop_size = 2 if is_large_property_index else 1 - content.write(_write_int(assoc_index, prop_size)) + mask = 0x7FFF if prop_size == 2 else 0x7F + essential_flag = 0x8000 if prop_size == 2 else 0x80 + assoc_value = assoc.property_index & mask + if assoc.essential: + assoc_value |= essential_flag + content.write(_write_int(assoc_value, prop_size)) return content.getvalue() @@ -620,4 +680,4 @@ class ItemReferenceBox(FullBox): children_data = super(FullBox, self).build_content() # --- END FIX 2 --- - return header.getvalue() + children_data \ No newline at end of file + return header.getvalue() + children_data diff --git a/main.py b/main.py index 25dc30d..b660a17 100644 --- a/main.py +++ b/main.py @@ -132,19 +132,13 @@ def convert_samsung_to_apple(samsung_file_path: str): shifted_id_map = {} if iinf_children_to_fix: - print(f" Found {len(iinf_children_to_fix)} shifted 'infe' boxes. Fixing them...") + print(f" Found {len(iinf_children_to_fix)} shifted 'infe' boxes. Mapping IDs for reference...") for infe_box in iinf_children_to_fix: unshifted_id = infe_box.item_id >> 16 # 检查 unshifted_id 是否真的在 correct_ids 中,以防万一 if unshifted_id in correct_ids: shifted_id_map[infe_box.item_id] = unshifted_id # 存映射 - print(f" - Fixing 'infe' ID {infe_box.item_id} -> {unshifted_id}") - infe_box.item_id = unshifted_id - - # 同时修复 iinf_box.entries 中的缓存 - for entry in flat_heic_file._iinf_box.entries: - if entry.item_id in shifted_id_map: - entry.item_id = shifted_id_map[entry.item_id] + print(f" - Mapping 'infe' ID {infe_box.item_id} -> {unshifted_id}") else: print(" 'infe' boxes seem correct. No shift detected.") @@ -230,4 +224,4 @@ def main(): convert_samsung_to_apple(samsung_file) if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/samsung_apple_compatible.HEIC b/samsung_apple_compatible.HEIC index 3be4b0db259fe09f9d21afb283b11b4d5838643c..e5853e471ae204a36d2064363c85bbec9b34f2f5 100644 GIT binary patch delta 536 zcmX}mNiPIJ7{>AH&A#vZ*!MQZ^z>-!=;`SbH&+s2COXlGh`5O$uG}O(fr|qNS63W; z3?G7jjhU(Bmr6ZV?_2Nn=Y#tD@u1#CmDK(0#)WYz6d_moX_MOfsG@Eidhuj%#_Q?fP4; z>)XENyGi-JwNR(5yKqfu#kX_BYBYEdT%j delta 524 zcmYk$yE6k(6vy$iFXH_OAztw&SlLZBVZH4m6`e+DOpFv!8Y%@dT1Jynt5Hz+3lu2* z8U6^qD-3t$Q=H#D_niCrQdKWrtLjxo39qf~GZ9flj8pONwnU|hjw1g3vxv4MS}ll@ zha`O>`d{*t6t(g}eOoRc9en4}?J`B_XOyyUiyR(1uI+n8$1|-U8=6iKESj$8x@Ok3 z>_R?Q^!>mKqX9iXZ~2p`WoCvaQJnr4Yn77hRmwNEl8FDdM?HFN)#I-6uEi8p(?!>e zbH})J37QA%mUP&iO;)x(f2JPzMjH9I?DI7 zKFLeqc+%D9P=?CY(pN?);~Uqg;2w)dEdCQrGQ~7A%reJ33oNq4GApdI#yT5pvc)z# j?6Su`2OM(5F(;hT;*4`HXmiOG*W7T+9rvGD9B$ViXVp&+ delta 229 zcmWl|Hx9xu06*g0f!uM%n7HQaZZa1F1g~G8*aJ#L}Guv`~Xm