Task 492: .OTB File Format

Task 492: .OTB File Format

File Format Specifications for the .OTB File Format

The .OTB file format is the OTA Bitmap format, a simple monochrome (black and white) image format developed by Nokia for mobile phones. It is designed for over-the-air transmission via SMS. The format is uncompressed, 1 bit per pixel, with a maximum size of 255x255 pixels. The file structure consists of a 4-byte header followed by the pixel data. Pixel data is packed into bytes with no padding between rows—the bits are continuous across the entire image. Each pixel is 0 (white) or 1 (black), with the most significant bit of each byte representing the leftmost pixel. Rows are encoded from top to bottom, left to right.

  1. List of all the properties of this file format intrinsic to its file system.
  • Infofield: The first byte, always 0x00, indicating the basic format (uncompressed bi-level image).
  • Width: The second byte, an unsigned integer representing the image width in pixels (1-255).
  • Height: The third byte, an unsigned integer representing the image height in pixels (1-255).
  • Number of colours: The fourth byte, always 0x01, indicating monochrome (black and white).
  • Pixel data: The remaining bytes, containing the bit-packed image data. The length is ceil((width * height) / 8) bytes. Bits are packed with MSB as the leftmost pixel, and the bit stream is continuous without row alignment padding.
  1. Two direct download links for files of format .OTB.
  1. Ghost blog embedded html javascript that allows a user to drag n drop a file of format .OTB and it will dump to screen all these properties.
OTB File Parser
Drag and drop .OTB file here
  1. Python class that can open any file of format .OTB and decode read and write and print to console all the properties from the above list.
import math

class OTBFile:
    def __init__(self, filepath=None):
        self.infofield = 0x00
        self.width = 0
        self.height = 0
        self.colours = 0x01
        self.pixel_data = b''
        if filepath:
            self.read(filepath)

    def read(self, filepath):
        with open(filepath, 'rb') as f:
            data = f.read()
        self.infofield = data[0]
        self.width = data[1]
        self.height = data[2]
        self.colours = data[3]
        expected_length = math.ceil((self.width * self.height) / 8)
        self.pixel_data = data[4:4 + expected_length]
        self.print_properties()

    def write(self, filepath):
        header = bytes([self.infofield, self.width, self.height, self.colours])
        with open(filepath, 'wb') as f:
            f.write(header + self.pixel_data)

    def print_properties(self):
        print(f"Infofield: 0x{self.infofield:02x}")
        print(f"Width: {self.width}")
        print(f"Height: {self.height}")
        print(f"Number of colours: 0x{self.colours:02x}")
        pixel_hex = ' '.join(f"{b:02x}" for b in self.pixel_data)
        print(f"Pixel data (hex): {pixel_hex}")

# Example usage
# otb = OTBFile('sample.otb')
# otb.write('output.otb')
  1. Java class that can open any file of format .OTB and decode read and write and print to console all the properties from the above list.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class OTBFile {
    private int infofield = 0x00;
    private int width = 0;
    private int height = 0;
    private int colours = 0x01;
    private byte[] pixelData = new byte[0];

    public OTBFile(String filepath) throws IOException {
        read(filepath);
    }

    public OTBFile() {}

    public void read(String filepath) throws IOException {
        try (FileInputStream fis = new FileInputStream(filepath)) {
            byte[] data = new byte[fis.available()];
            fis.read(data);
            infofield = data[0] & 0xFF;
            width = data[1] & 0xFF;
            height = data[2] & 0xFF;
            colours = data[3] & 0xFF;
            int expectedLength = (int) Math.ceil((width * height) / 8.0);
            pixelData = new byte[expectedLength];
            System.arraycopy(data, 4, pixelData, 0, expectedLength);
        }
        printProperties();
    }

    public void write(String filepath) throws IOException {
        try (FileOutputStream fos = new FileOutputStream(filepath)) {
            fos.write(infofield);
            fos.write(width);
            fos.write(height);
            fos.write(colours);
            fos.write(pixelData);
        }
    }

    public void printProperties() {
        System.out.println("Infofield: 0x" + Integer.toHexString(infofield).toUpperCase());
        System.out.println("Width: " + width);
        System.out.println("Height: " + height);
        System.out.println("Number of colours: 0x" + Integer.toHexString(colours).toUpperCase());
        System.out.print("Pixel data (hex): ");
        for (byte b : pixelData) {
            System.out.print(Integer.toHexString(b & 0xFF).toUpperCase() + " ");
        }
        System.out.println();
    }

    // Example usage
    // public static void main(String[] args) throws IOException {
    //     OTBFile otb = new OTBFile("sample.otb");
    //     otb.write("output.otb");
    // }
}
  1. Javascript class that can open any file of format .OTB and decode read and write and print to console all the properties from the above list.
class OTBFile {
  constructor(filepath = null) {
    this.infofield = 0x00;
    this.width = 0;
    this.height = 0;
    this.colours = 0x01;
    this.pixelData = new Uint8Array(0);
    if (filepath) {
      this.read(filepath);
    }
  }

  async read(filepath) {
    const response = await fetch(filepath);
    const arrayBuffer = await response.arrayBuffer();
    const dataView = new DataView(arrayBuffer);
    this.infofield = dataView.getUint8(0);
    this.width = dataView.getUint8(1);
    this.height = dataView.getUint8(2);
    this.colours = dataView.getUint8(3);
    const expectedLength = Math.ceil((this.width * this.height) / 8);
    this.pixelData = new Uint8Array(arrayBuffer.slice(4, 4 + expectedLength));
    this.printProperties();
  }

  async write(filepath) {
    const header = new Uint8Array([this.infofield, this.width, this.height, this.colours]);
    const fullBuffer = new Uint8Array(header.length + this.pixelData.length);
    fullBuffer.set(header, 0);
    fullBuffer.set(this.pixelData, header.length);
    // For node.js, use fs.writeFileSync(filepath, fullBuffer);
    console.log('Write to file not implemented in browser; use Node.js for file writing.');
  }

  printProperties() {
    console.log(`Infofield: 0x${this.infofield.toString(16).padStart(2, '0')}`);
    console.log(`Width: ${this.width}`);
    console.log(`Height: ${this.height}`);
    console.log(`Number of colours: 0x${this.colours.toString(16).padStart(2, '0')}`);
    const pixelHex = Array.from(this.pixelData).map(b => b.toString(16).padStart(2, '0')).join(' ');
    console.log(`Pixel data (hex): ${pixelHex}`);
  }
}

// Example usage in browser or Node
// const otb = new OTBFile('sample.otb');
// otb.write('output.otb');
  1. C class that can open any file of format .OTB and decode read and write and print to console all the properties from the above list.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

typedef struct {
    unsigned char infofield;
    unsigned char width;
    unsigned char height;
    unsigned char colours;
    unsigned char *pixel_data;
    size_t data_length;
} OTBFile;

void otb_read(OTBFile *otb, const char *filepath) {
    FILE *f = fopen(filepath, "rb");
    if (!f) {
        perror("File opening failed");
        return;
    }
    fseek(f, 0, SEEK_END);
    long length = ftell(f);
    fseek(f, 0, SEEK_SET);
    unsigned char *data = malloc(length);
    fread(data, 1, length, f);
    fclose(f);
    otb->infofield = data[0];
    otb->width = data[1];
    otb->height = data[2];
    otb->colours = data[3];
    otb->data_length = (size_t)ceil((otb->width * otb->height) / 8.0);
    otb->pixel_data = malloc(otb->data_length);
    memcpy(otb->pixel_data, data + 4, otb->data_length);
    free(data);
    otb_print(otb);
}

void otb_write(const OTBFile *otb, const char *filepath) {
    FILE *f = fopen(filepath, "wb");
    if (!f) {
        perror("File opening failed");
        return;
    }
    fwrite(&otb->infofield, 1, 1, f);
    fwrite(&otb->width, 1, 1, f);
    fwrite(&otb->height, 1, 1, f);
    fwrite(&otb->colours, 1, 1, f);
    fwrite(otb->pixel_data, 1, otb->data_length, f);
    fclose(f);
}

void otb_print(const OTBFile *otb) {
    printf("Infofield: 0x%02x\n", otb->infofield);
    printf("Width: %u\n", otb->width);
    printf("Height: %u\n", otb->height);
    printf("Number of colours: 0x%02x\n", otb->colours);
    printf("Pixel data (hex): ");
    for (size_t i = 0; i < otb->data_length; i++) {
        printf("%02x ", otb->pixel_data[i]);
    }
    printf("\n");
}

void otb_free(OTBFile *otb) {
    free(otb->pixel_data);
}

// Example usage
// int main() {
//     OTBFile otb = {.infofield = 0x00, .colours = 0x01};
//     otb_read(&otb, "sample.otb");
//     otb_write(&otb, "output.otb");
//     otb_free(&otb);
//     return 0;
// }