I am investigating car navigation software which runs on QNX and want to replace the startup animation with my own. I have found the files in the firmware which have the extension .canim which likely stands for compressed animation.

The files are zlib compressed and after deflating the files start with HEX 41 4E 49 4D 31 20 20 20 20 03 00 00 E0 01 00 00(ANIM1). My question is what file format is this? (possible match: Amiga ANIM)

I know that the screen resolution for the device is 800x480 so after DWORD 3&4 are resolution (20 03 00 00 -> 80 and E0 01 00 00 -> 480

I've uploaded the files here, bin files are deflated versions of the .canim files.

EDIT: some additional info: I found startup pictures in the same folder and they are zlib compressed and are simple RGB pairs with a padding 00 to align at DWORD, eg : 04 02 04 00 04 02 04 00 04 02 04 00 04 02 04 00

EDIT2: This site has video's for each of the possible startup animations. And these are the startup pictures I have extracted: startup_generic.raw2



  • The Amiga match is not correct, that is a RIFF format. If googling turned up nothing, it may well be a proprietary format. Are its contents compressed as well? Can you put some samples on a public server?
    – Jongware
    Mar 16, 2015 at 9:18
  • @Jongware files uploaded, see edit
    – Remko
    Mar 16, 2015 at 10:41
  • Are you able to post a photo of one of the opening frames or, even better, a video of the animation ?
    – Ian Cook
    Mar 18, 2015 at 6:06
  • @IanCook edited post with link to video's
    – Remko
    Mar 18, 2015 at 7:07

1 Answer 1


The image data is stored as raw RGBA quads, with width/height/start defined in a block near the beginning.

You can extract the image data from the uncompressed bins using this python script:

import struct
import sys
import os
from PIL import Image

if len(sys.argv) != 3:
  print 'usage: process.py <filename> <outdir>'

out_dir = sys.argv[2]
if not os.path.exists(out_dir):

data = open(sys.argv[1],'rb').read()
offset = 0

(magic,) = struct.unpack_from('<8s', data, offset)
offset = offset + 8

if magic != 'ANIM1   ':
  print 'incorrect magic!'

(stage_width, stage_height, cmdblock_len, unk) = struct.unpack_from('<LLLL', data, offset)
offset = offset + 16

print "stage_width: %d\nstage_height: %d\ncmdblock_len: %d\n" %(stage_width, stage_height, cmdblock_len)

(cmd_code, img_num, img_width, img_height, bytes_per_pixel, data_start) = struct.unpack_from('<LLLLLL', data, offset)

while cmd_code == 0x11:
  print 'generating img_%d' % (img_num)
  im = Image.frombuffer('RGBA', (img_width, img_height), data[0x20+cmdblock_len+data_start:], 'raw', 'RGBA', 0, 1)
  im.save(os.path.join(out_dir, 'img_%d.png'%img_num))
  offset = offset + 0x20
  (cmd_code, img_num, img_width, img_height, bytes_per_pixel, data_start) = struct.unpack_from('<LLLLLL', data, offset)

The other data in that initial block must be used composite them into the actual animation.

You may be able to inject your own images of the same dimensions/format to replace elements of the animations. It doesn't give you full control, but it should give you some basic capability to customise the animations.

  • Thanks a lot, will have a look at this in the next couple of days...
    – Remko
    Mar 18, 2015 at 22:09
  • Is the firmware package publicly available somewhere online?
    – booto
    Mar 26, 2015 at 7:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.