CDR (CorelDRAW drawing) format specification for Kaitai Struct
Formal specifications for the CorelDRAW .cdr
format in Kaitai Struct YAML (.ksy
), a declarative language for describing binary formats.
If you are interested in...
- what graphic objects (paths, polygons, rectangles, ellipses, embedded images) the CDR document contains,
- how do they look like (i.e. the geometry data associated with them: path points, rectangle side lengths and so on),
- what fill and outline styles the objects use (solid colors, gradients),
- what transformation matrix is applied on each object,
... and more, Kaitai Struct can make all this data accessible to you given the .ksy
specifications from this repository.
Use the bin/cdr-unpk
Bash script to preprocess the .cdr
file so that you can read all CDR versions (especially the new ones) without having to worry about what version of the CDR format the .cdr
file in front of you is using. The usage is the following:
bin/cdr-unpk example.cdr
It creates example.cdr.unpk
in the same directory where example.cdr
is. The example.cdr.unpk
file needs to be interpreted by cdr_unpk.ksy
(which imports coreldraw_cdr.ksy
and file_streams.ksy
under the hood).
To understand why applying the coreldraw_cdr.ksy
Kaitai Struct specification to real-world .cdr
files is complicated, you need to have a basic overview of CDR format versions:
- X3 (13.0) and older: directly the RIFF-based chunk structure that
coreldraw_cdr.ksy
understands; - X4 (14.0) and X5 (15.0): a ZIP archive, the
coreldraw_cdr.ksy
spec can only recognize thecontent/riffData.cdr
file inside it; - X6 (16.0) or later: also a ZIP archive, but the entrypoint is
content/root.dat
which needs to read external chunk payloads fromcontent/data/*.dat
files.
The need for accessing external streams in CDR X6+ files was a problem, because to be able to use visualizers available for Kaitai Struct (e.g. ksv, Web IDE), the entire parsed byte stream needs to be contained in a single file and the top-level type in the main .ksy
spec must not have any parameters. That's why the bin/cdr-unpk
script was created - it extracts the necessary streams from the given .cdr
file and dumps them into a .unpk
file in a custom auxiliary format described in cdr_unpk.ksy
.
There is a branch unpack-zip-yourself
available when you want to use the Kaitai Struct parser generated from coreldraw_cdr.ksy
in your application. It makes the integration easier, because it provides you a top-level parameter where you pass a list of KaitaiStream
objects for each external data stream in X6+ files (in the order specified in content/dataFileList.dat
file of X6+ .cdr
ZIP archives):
params:
- id: streams
type: io[]
For pre-X6 .cdr
files, just pass an empty list.
You should be able to understand how to find the data streams in the ZIP archive by looking into bin/cdr-unpk
, or you can look into libcdr.
By default, the coreldraw_cdr.ksy
spec is expected to be imported from cdr_unpk.ksy
and not used by itself. However, if you don't want to preprocess .cdr
files by bin/cdr-unpk
, you can manually edit coreldraw_cdr.ksy
to disable support for external streams (comment out sections /meta/imports
, /params
and /types/chunk_wrapper/instances/body_external
).
Such a coreldraw_cdr.ksy
specification can be used directly on the .cdr
file for pre-X4 files (will work great), or on content/riffData.cdr
if it's inside the ZIP archive of CDR X4/X5 files. For X6 and later it's technically possible to use it on content/root.dat
itself too, but you won't get too deep into the file because it uses external streams for most chunks (so it probably won't be very useful).