Task 100: .COL File Format
Task 100: .COL File Format
File Format Specifications for the .COL File Format
The .COL file format refers to the Autodesk Animator Color Palette format, used to store RGB values for color palettes in Autodesk Animator and Animator Pro software. The format has two variants: the original Animator version and the Animator Pro version. The specifications are as follows, based on documented sources.
1. List of All Properties of This File Format Intrinsic to Its File System
The properties intrinsic to the .COL file format are the structural elements that define its content and validation. These include:
- Variant Type: Original Animator (fixed size, no header) or Animator Pro (variable size, with header).
- File Size: Exactly 768 bytes for the original variant; variable for the Pro variant, calculated as 8 + (3 × number of palette entries).
- Header (Pro variant only):
- File Size Field (4 bytes, dword): The total size of the file, including the header.
- ID Field (2 bytes, word): Fixed value 0B123h to identify the Pro variant.
- Version Field (2 bytes, word): Currently 0.
- Palette Data: A sequence of RGB triplets, each consisting of 3 bytes (1 byte for red, 1 byte for green, 1 byte for blue), with values ranging from 0 to 255.
- Number of Palette Entries: Fixed at 256 for the original variant; calculated as (file size - 8) / 3 for the Pro variant (must be an integer; otherwise, the file is invalid).
- Color Component Range: Each R, G, B component is an 8-bit unsigned integer (0-255).
- Data Order: RGB values are stored in "rgbrgb..." order without padding or additional control information in the original variant.
- Validation Rules: For the Pro variant, the calculated number of entries must be an integer multiple of 3; the file size must match the header value. For both variants, the file is typically associated with 256 entries, but the Pro variant allows flexibility.
These properties ensure the file's integrity and compatibility with the software.
2. Two Direct Download Links for Files of Format .COL
After a thorough search using available tools, no direct download links for .COL files were identified. The format is legacy and rarely hosted for direct download. However, .COL files can be generated using the Autodesk Animator software, available for download from archives such as Internet Archive (e.g., https://archive.org/details/autodesk-animator-studio). For the purpose of this task, the subsequent code examples assume access to such files or can be tested with generated data.
3. Ghost Blog Embedded HTML JavaScript for Drag and Drop .COL File Dump
The following is an embeddable HTML snippet with JavaScript that can be placed in a Ghost blog post. It allows users to drag and drop a .COL file, parses it, and displays the properties on the screen. It handles both variants and validates the file.
This snippet creates a drop zone and outputs the properties in an unordered list.
4. Python Class for .COL File Handling
The following Python class can open, decode, read, write, and print all properties of a .COL file to the console. It supports both variants.
import struct
import sys
class ColFile:
def __init__(self, filepath=None):
self.variant = None
self.file_size = None
self.id = None
self.version = None
self.num_entries = None
self.palette = [] # List of (r, g, b) tuples
if filepath:
self.read(filepath)
def read(self, filepath):
with open(filepath, 'rb') as f:
data = f.read()
self.file_size = len(data)
if self.file_size == 768:
self.variant = 'Original'
self.num_entries = 256
self.palette = [struct.unpack('BBB', data[i:i+3]) for i in range(0, 768, 3)]
else:
self.variant = 'Pro'
self.file_size_field, self.id, self.version = struct.unpack('<IHH', data[:8])
self.num_entries = (self.file_size - 8) / 3
if not self.num_entries.is_integer() or self.id != 0xB123 or self.file_size_field != self.file_size:
raise ValueError("Invalid .COL file")
self.num_entries = int(self.num_entries)
self.palette = [struct.unpack('BBB', data[8 + i:8 + i+3]) for i in range(0, 3 * self.num_entries, 3)]
def print_properties(self):
print(f"Variant: {self.variant}")
print(f"File Size: {self.file_size} bytes")
if self.variant == 'Pro':
print(f"Header ID: 0x{self.id:04X}")
print(f"Header Version: {self.version}")
print(f"Number of Palette Entries: {self.num_entries}")
print("Palette Data (first 5 entries):")
for i, (r, g, b) in enumerate(self.palette[:5]):
print(f"Entry {i+1}: R={r}, G={g}, B={b}")
def write(self, filepath):
with open(filepath, 'wb') as f:
if self.variant == 'Pro':
file_size = 8 + 3 * len(self.palette)
f.write(struct.pack('<IHH', file_size, 0xB123, 0))
for r, g, b in self.palette:
f.write(struct.pack('BBB', r, g, b))
# Example usage
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python col_handler.py <filepath>")
else:
col = ColFile(sys.argv[1])
col.print_properties()
This class reads the file, decodes the header and palette, prints the properties, and can write a new file.
5. Java Class for .COL File Handling
The following Java class can open, decode, read, write, and print all properties of a .COL file to the console. It supports both variants.
import java.io.*;
import java.nio.*;
import java.nio.file.*;
public class ColFile {
private String variant;
private long fileSize;
private int id;
private int version;
private int numEntries;
private byte[][] palette; // Array of [r, g, b]
public ColFile(String filepath) throws IOException {
read(filepath);
}
private void read(String filepath) throws IOException {
byte[] data = Files.readAllBytes(Paths.get(filepath));
fileSize = data.length;
if (fileSize == 768) {
variant = "Original";
numEntries = 256;
palette = new byte[256][3];
for (int i = 0; i < 256; i++) {
palette[i][0] = data[i * 3];
palette[i][1] = data[i * 3 + 1];
palette[i][2] = data[i * 3 + 2];
}
} else {
variant = "Pro";
ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
int sizeField = buffer.getInt(0);
id = buffer.getShort(4) & 0xFFFF;
version = buffer.getShort(6) & 0xFFFF;
int calcEntries = (int) (fileSize - 8) / 3;
if (calcEntries * 3 + 8 != fileSize || id != 0xB123 || sizeField != fileSize) {
throw new IOException("Invalid .COL file");
}
numEntries = calcEntries;
palette = new byte[numEntries][3];
for (int i = 0; i < numEntries; i++) {
palette[i][0] = data[8 + i * 3];
palette[i][1] = data[8 + i * 3 + 1];
palette[i][2] = data[8 + i * 3 + 2];
}
}
}
public void printProperties() {
System.out.println("Variant: " + variant);
System.out.println("File Size: " + fileSize + " bytes");
if (variant.equals("Pro")) {
System.out.println("Header ID: 0x" + Integer.toHexString(id).toUpperCase());
System.out.println("Header Version: " + version);
}
System.out.println("Number of Palette Entries: " + numEntries);
System.out.println("Palette Data (first 5 entries):");
for (int i = 0; i < Math.min(5, numEntries); i++) {
System.out.println("Entry " + (i + 1) + ": R=" + (palette[i][0] & 0xFF) + ", G=" + (palette[i][1] & 0xFF) + ", B=" + (palette[i][2] & 0xFF));
}
}
public void write(String filepath) throws IOException {
try (FileOutputStream fos = new FileOutputStream(filepath)) {
if (variant.equals("Pro")) {
int calcSize = 8 + 3 * numEntries;
ByteBuffer buffer = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(calcSize);
buffer.putShort((short) 0xB123);
buffer.putShort((short) 0);
fos.write(buffer.array());
}
for (byte[] rgb : palette) {
fos.write(rgb);
}
}
}
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.out.println("Usage: java ColFile <filepath>");
} else {
ColFile col = new ColFile(args[0]);
col.printProperties();
}
}
}
This class handles reading, printing, and writing, with validation.
6. JavaScript Class for .COL File Handling
The following JavaScript class can open, decode, read, write, and print all properties of a .COL file to the console. It uses Node.js for file I/O.
const fs = require('fs');
class ColFile {
constructor(filepath = null) {
this.variant = null;
this.fileSize = null;
this.id = null;
this.version = null;
this.numEntries = null;
this.palette = []; // Array of {r, g, b}
if (filepath) {
this.read(filepath);
}
}
read(filepath) {
const data = fs.readFileSync(filepath);
this.fileSize = data.length;
if (this.fileSize === 768) {
this.variant = 'Original';
this.numEntries = 256;
for (let i = 0; i < 768; i += 3) {
this.palette.push({ r: data[i], g: data[i + 1], b: data[i + 2] });
}
} else {
this.variant = 'Pro';
const dv = new DataView(data.buffer);
const sizeField = dv.getUint32(0, true);
this.id = dv.getUint16(4, true);
this.version = dv.getUint16(6, true);
this.numEntries = (this.fileSize - 8) / 3;
if (!Number.isInteger(this.numEntries) || this.id !== 0xB123 || sizeField !== this.fileSize) {
throw new Error('Invalid .COL file');
}
for (let i = 8; i < this.fileSize; i += 3) {
this.palette.push({ r: data[i], g: data[i + 1], b: data[i + 2] });
}
}
}
printProperties() {
console.log(`Variant: ${this.variant}`);
console.log(`File Size: ${this.fileSize} bytes`);
if (this.variant === 'Pro') {
console.log(`Header ID: 0x${this.id.toString(16).toUpperCase()}`);
console.log(`Header Version: ${this.version}`);
}
console.log(`Number of Palette Entries: ${this.numEntries}`);
console.log('Palette Data (first 5 entries):');
for (let i = 0; i < Math.min(5, this.palette.length); i++) {
const { r, g, b } = this.palette[i];
console.log(`Entry ${i + 1}: R=${r}, G=${g}, B=${b}`);
}
}
write(filepath) {
let buffer;
if (this.variant === 'Pro') {
const fileSize = 8 + 3 * this.palette.length;
buffer = Buffer.alloc(fileSize);
buffer.writeUint32LE(fileSize, 0);
buffer.writeUint16LE(0xB123, 4);
buffer.writeUint16LE(0, 6);
let offset = 8;
for (const { r, g, b } of this.palette) {
buffer[offset++] = r;
buffer[offset++] = g;
buffer[offset++] = b;
}
} else {
buffer = Buffer.alloc(768);
let offset = 0;
for (const { r, g, b } of this.palette) {
buffer[offset++] = r;
buffer[offset++] = g;
buffer[offset++] = b;
}
}
fs.writeFileSync(filepath, buffer);
}
}
// Example usage
if (process.argv.length > 2) {
const col = new ColFile(process.argv[2]);
col.printProperties();
} else {
console.log('Usage: node col_handler.js <filepath>');
}
This class uses Node.js for file operations and handles reading, printing, and writing.
7. C "Class" for .COL File Handling
C does not have classes, so the following is a struct with associated functions to open, decode, read, write, and print all properties of a .COL file to the console. It supports both variants.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct {
char *variant;
size_t file_size;
uint16_t id;
uint16_t version;
int num_entries;
uint8_t *palette; // Raw RGB data
} ColFile;
ColFile *col_new() {
ColFile *col = malloc(sizeof(ColFile));
col->variant = NULL;
col->file_size = 0;
col->id = 0;
col->version = 0;
col->num_entries = 0;
col->palette = NULL;
return col;
}
void col_read(ColFile *col, const char *filepath) {
FILE *f = fopen(filepath, "rb");
if (!f) {
fprintf(stderr, "Cannot open file\n");
return;
}
fseek(f, 0, SEEK_END);
col->file_size = ftell(f);
fseek(f, 0, SEEK_SET);
uint8_t *data = malloc(col->file_size);
fread(data, 1, col->file_size, f);
fclose(f);
if (col->file_size == 768) {
col->variant = "Original";
col->num_entries = 256;
col->palette = data;
} else {
col->variant = "Pro";
uint32_t size_field = *(uint32_t *)(data);
col->id = *(uint16_t *)(data + 4);
col->version = *(uint16_t *)(data + 6);
int calc_entries = (col->file_size - 8) / 3;
if ((col->file_size - 8) % 3 != 0 || col->id != 0xB123 || size_field != col->file_size) {
free(data);
fprintf(stderr, "Invalid .COL file\n");
return;
}
col->num_entries = calc_entries;
col->palette = malloc(3 * col->num_entries);
memcpy(col->palette, data + 8, 3 * col->num_entries);
free(data);
}
}
void col_print_properties(const ColFile *col) {
printf("Variant: %s\n", col->variant);
printf("File Size: %zu bytes\n", col->file_size);
if (strcmp(col->variant, "Pro") == 0) {
printf("Header ID: 0x%04X\n", col->id);
printf("Header Version: %u\n", col->version);
}
printf("Number of Palette Entries: %d\n", col->num_entries);
printf("Palette Data (first 5 entries):\n");
for (int i = 0; i < 5 && i < col->num_entries; i++) {
uint8_t r = col->palette[i * 3];
uint8_t g = col->palette[i * 3 + 1];
uint8_t b = col->palette[i * 3 + 2];
printf("Entry %d: R=%u, G=%u, B=%u\n", i + 1, r, g, b);
}
}
void col_write(const ColFile *col, const char *filepath) {
FILE *f = fopen(filepath, "wb");
if (!f) {
fprintf(stderr, "Cannot open file for writing\n");
return;
}
if (strcmp(col->variant, "Pro") == 0) {
uint32_t calc_size = 8 + 3 * col->num_entries;
fwrite(&calc_size, sizeof(uint32_t), 1, f);
uint16_t temp_id = 0xB123;
fwrite(&temp_id, sizeof(uint16_t), 1, f);
uint16_t temp_version = 0;
fwrite(&temp_version, sizeof(uint16_t), 1, f);
}
fwrite(col->palette, 1, 3 * col->num_entries, f);
fclose(f);
}
void col_free(ColFile *col) {
free(col->palette);
free(col);
}
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: %s <filepath>\n", argv[0]);
return 1;
}
ColFile *col = col_new();
col_read(col, argv[1]);
col_print_properties(col);
col_free(col);
return 0;
}
This implementation uses a struct and functions to mimic a class, handling reading, printing, and writing with validation.