mirror of
https://github.com/quantum5/win2xcur.git
synced 2025-04-24 10:11:57 -04:00
Support more versions of *.ani files
This commit is contained in:
parent
d887ea0ca6
commit
3c043bc518
|
@ -35,14 +35,21 @@ class ANIParser(BaseParser):
|
||||||
def _unpack(self, struct_cls: struct.Struct, offset: int) -> Tuple[Any, ...]:
|
def _unpack(self, struct_cls: struct.Struct, offset: int) -> Tuple[Any, ...]:
|
||||||
return struct_cls.unpack(self.blob[offset:offset + struct_cls.size])
|
return struct_cls.unpack(self.blob[offset:offset + struct_cls.size])
|
||||||
|
|
||||||
def _read_chunk(self, offset: int, expected: Iterable[bytes]) -> Tuple[int, int]:
|
def _read_chunk(self, offset: int, expected: Iterable[bytes]) -> Tuple[bytes, int, int]:
|
||||||
|
found = []
|
||||||
|
while True:
|
||||||
name, size = self._unpack(self.CHUNK_HEADER, offset)
|
name, size = self._unpack(self.CHUNK_HEADER, offset)
|
||||||
if name not in expected:
|
offset += self.CHUNK_HEADER.size
|
||||||
raise ValueError('Expected chunk %r, found %r' % (expected, name))
|
if name in expected:
|
||||||
return size, offset + self.CHUNK_HEADER.size
|
break
|
||||||
|
found += [name]
|
||||||
|
offset += size
|
||||||
|
if offset >= len(self.blob):
|
||||||
|
raise ValueError('Expected chunk %r, found %r' % (expected, found))
|
||||||
|
return name, size, offset
|
||||||
|
|
||||||
def _parse(self, offset: int) -> List[CursorFrame]:
|
def _parse(self, offset: int) -> List[CursorFrame]:
|
||||||
size, offset = self._read_chunk(offset, expected=[b'anih'])
|
_, size, offset = self._read_chunk(offset, expected=[b'anih'])
|
||||||
|
|
||||||
if size != self.ANIH_HEADER.size:
|
if size != self.ANIH_HEADER.size:
|
||||||
raise ValueError('Unexpected anih header size %d, expected %d' % (size, self.ANIH_HEADER.size))
|
raise ValueError('Unexpected anih header size %d, expected %d' % (size, self.ANIH_HEADER.size))
|
||||||
|
@ -54,38 +61,42 @@ class ANIParser(BaseParser):
|
||||||
raise NotImplementedError('Raw BMP images not supported.')
|
raise NotImplementedError('Raw BMP images not supported.')
|
||||||
|
|
||||||
offset += self.ANIH_HEADER.size
|
offset += self.ANIH_HEADER.size
|
||||||
list_size, offset = self._read_chunk(offset, expected=[b'LIST'])
|
|
||||||
list_end = list_size + offset
|
|
||||||
|
|
||||||
|
frames = []
|
||||||
|
order = list(range(frame_count))
|
||||||
|
delays = [display_rate for _ in range(step_count)]
|
||||||
|
|
||||||
|
while offset < len(self.blob):
|
||||||
|
name, size, offset = self._read_chunk(offset, expected=[b'LIST', b'seq ', b'rate'])
|
||||||
|
if name == b'LIST':
|
||||||
|
list_end = offset + size
|
||||||
if self.blob[offset:offset + 4] != self.FRAME_TYPE:
|
if self.blob[offset:offset + 4] != self.FRAME_TYPE:
|
||||||
raise ValueError('Unexpected RIFF list type: %r, expected %r' %
|
raise ValueError('Unexpected RIFF list type: %r, expected %r' %
|
||||||
(self.blob[offset:offset + 4], self.FRAME_TYPE))
|
(self.blob[offset:offset + 4], self.FRAME_TYPE))
|
||||||
offset += 4
|
offset += 4
|
||||||
|
|
||||||
frames = []
|
|
||||||
for i in range(frame_count):
|
for i in range(frame_count):
|
||||||
size, offset = self._read_chunk(offset, expected=[b'icon'])
|
_, size, offset = self._read_chunk(offset, expected=[b'icon'])
|
||||||
frames.append(CURParser(self.blob[offset:offset + size]).frames[0])
|
frames.append(CURParser(self.blob[offset:offset + size]).frames[0])
|
||||||
offset += size
|
offset += size
|
||||||
|
|
||||||
if offset != list_end:
|
if offset != list_end:
|
||||||
raise ValueError('Wrong RIFF list size: %r, expected %r' % (offset, list_end))
|
raise ValueError('Wrong RIFF list size: %r, expected %r' % (offset, list_end))
|
||||||
|
elif name == b'seq ':
|
||||||
sequence = frames
|
order = [i for i, in self.UNSIGNED.iter_unpack(self.blob[offset:offset + size])]
|
||||||
if flags & self.SEQUENCE_FLAG:
|
if len(order) != step_count:
|
||||||
size, offset = self._read_chunk(offset, expected=[b'seq '])
|
raise ValueError('Wrong animation sequence size: %r, expected %r' % (len(order), step_count))
|
||||||
sequence = [copy(frames[i]) for i, in self.UNSIGNED.iter_unpack(self.blob[offset:offset + size])]
|
offset += size
|
||||||
if len(sequence) != step_count:
|
elif name == b'rate':
|
||||||
raise ValueError('Wrong animation sequence size: %r, expected %r' % (len(sequence), step_count))
|
delays = [i for i, in self.UNSIGNED.iter_unpack(self.blob[offset:offset + size])]
|
||||||
|
if len(delays) != step_count:
|
||||||
|
raise ValueError('Wrong animation rate size: %r, expected %r' % (len(delays), step_count))
|
||||||
offset += size
|
offset += size
|
||||||
|
|
||||||
delays = [display_rate for _ in range(step_count)]
|
if len(order) != step_count:
|
||||||
if offset < len(self.blob):
|
raise ValueError('Required chunk "seq " not found.')
|
||||||
size, offset = self._read_chunk(offset, expected=[b'rate'])
|
|
||||||
delays = [i for i, in self.UNSIGNED.iter_unpack(self.blob[offset:offset + size])]
|
|
||||||
if len(sequence) != step_count:
|
|
||||||
raise ValueError('Wrong animation rate size: %r, expected %r' % (len(delays), step_count))
|
|
||||||
|
|
||||||
|
sequence = [copy(frames[i]) for i in order]
|
||||||
for frame, delay in zip(sequence, delays):
|
for frame, delay in zip(sequence, delays):
|
||||||
frame.delay = delay / 60
|
frame.delay = delay / 60
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue