The CZ# Image Formats
June 28, 2024
This page is also available as a PDF document
This isn’t a real specification
The CZ# image formats (CZ0, CZ1, CZ2, CZ3, CZ4, and CZ5) are used in the LUCA System visual novel engine developed by Prototype Ltd.
These image formats are capable of storing lossless compressed and uncompressed pixel data over a wide range of bit depths and with accompanying metadata useful for a visual novel. All the bytes in CZ# files are stored in little-endian format.
Common
Header
All CZ# files start with a variable-length header block. The header contains information about basic parameters of the image, such as the image dimensions. The common part of the header is as follows:
CommonHeader {
magic: [char; 4], // magic bytes “CZ0\0“
header_length: u8, // header length in bytes
width: u16, // image width in pixels
height: u16, // image height in pixels
bit_depth: u16, // bit depth (BPP)
unknown: u8, // unknown purpose
}
This common header is optionally followed by an optional
extended header, which contains metadata such as cropping
parameters and positioning on the screen. The optional part
of the header exists if the header_length value is greater
than 15, with the exception of the CZ2 format. The extended
header is as follows:
ExtendedHeader {
unknown: [u8; 5],
crop_width: u16, // width of image crop
crop_height: u16, // height of image crop
bounds_width: u16, // width of crop bounds
bounds_height: u16, // height of crop bounds
}
The extended header is then optionally followed by image offset information, used for positioning the image. This information only exists if the header_length value is greater than 28.
OffsetHeader {
offset_width: u16,
offset_height: u16,
unknown: [u8; 4],
}
Indexed Color
The header is followed by a palette block containing the information required to properly decode an image which is encoded in indexed color.
This section only exists if the bit-depth of the image (as described in the header) is 8 bits or 4 bits.
The palette is an ordered list of colors, with the color in the first position corresponding to a value of 0 in the image, the second corresponding to a value of 1, and so on. These colors are stored in 8 bit RGBA format.
These colors are stored in a list of colors corresponding to the bit depth of the image. For 4 bits the color list is 16 colors long, and for 8 bits the color list is 256 colors long. There is no extra information in this list.
Color {
red: u8,
green: u8,
blue: u8,
alpha: u8,
}
ColorPalette {
colors: Vec<Color>
}
Compression Info
All CZ# formats except for CZ0 (which is uncompressed) contain a block immediately following the color information which contains information about the size of chunks in the following compressed image data. The compression block starts with the number of compressed blocks, followed by a list of the sizes of the compressed data and original data.
ChunkInfo {
compressed_size: u32, // compressed size, bytes
original_size: u32, // original size, bytes
}
CompressionInfo {
chunk_number: u32, // the number of chunks
chunks: ChunkInfo,
}
Types of CZ Files
CZ0
CZ0 files are uncompressed, storing raw RGBA pixel data in a linear bitmap.
This format is most often used to store character sprites, UI elements, and various other game assets. Use of CZ0 has decreased in more recent LUCA System games.
The encoding used in these files is a simple bitmap of RGBA pixels. Decoding CZ0 is as simple as reading the header to determine the width and height of the image in pixels, and then reading the image data as 4 byte RGBA chunks, which correspond directly to pixels.
CZ1
CZ1 files are compressed, storing raw RGBA pixel data using a LZW compression scheme.
This format is used to store text bitmaps in older LUCA System games, along with UI elements and other small image assets in more recent games. It is most often encountered with 8 bit indexed color, but 32 bit RGBA is also relatively common.
CZ2
CZ2 files are compressed, storing raw RGBA pixel data using an LZW compression scheme. This method of compression is different from CZ1.
This format is primarily used for storing text bitmaps in newer LUCA System games. Its use outside of text bitmaps is limited.
CZ3
CZ3 files are compressed, storing modified RGBA pixel data using an LZW compression scheme. This compression scheme is the same as CZ1.
This format is primarily used for storing backgrounds, but is also used for sprites, character graphics, and general files. It appears to be the most general form of more highly compressed CZ# files. The compression ratios achieved by CZ3 are similar or slightly worse than PNG files with a compression level of 5.
CZ4
CZ4 files are compressed, storing modified RGBA pixel data using an LZW compression scheme. This compression scheme is the same as CZ1.
This format only appears in newer LUCA System games, and is primarily used for storing sprites, character graphics, and backgrounds. It seems to have replaced the use of CZ3 files and CZ0 files in many places in the engine, but not entirely. The compression ratios achieved by CZ4 are similar or better than PNG files with a compression level of 9.
CZ5
Little is known about the CZ5 format, as it has not been encountered in any released games so far. The only information about it has come from decompiling recent games which use the LUCA System engine, where it is referenced as part of the decoder for CZ# files.