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.
- 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.
- Two direct download links for files of format .OTB.
- https://www.codeproject.com/KB/mobile/16128/OTA.zip (zip archive containing sample .otb file)
- https://otland.net/attachments/pure-items-otb (sample .otb file from OpenTibia community, note: may require login for download)
- 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.
Drag and drop .OTB file here
- 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')
- 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");
// }
}
- 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');
- 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;
// }