Iris image format library. Supports encode/decode.
- Go 100%
| codec_test.go | ||
| decode.go | ||
| encode.go | ||
| errors.go | ||
| format.go | ||
| format_test.go | ||
| go.mod | ||
| header.go | ||
| header_test.go | ||
| image.go | ||
| integration_test.go | ||
| iris.go | ||
| license | ||
| lz4.go | ||
| lz4_test.go | ||
| metadata.go | ||
| metadata_test.go | ||
| raw.go | ||
| readme.md | ||
| technical.md | ||
Iris Image Format - Go Implementation
A fast, minimal image format optimized for game engines and real-time applications.
Features
- Simple: Fixed 20-byte header, predictable layout
- Fast: Custom LZ4 decompression at 2+ GB/s
- Compact: Better compression than raw, faster than PNG
- No dependencies: Custom LZ4 implementation, no external packages
- Flexible: Two APIs - standard
image.Imageand fast byte-level access
Installation
go get git.sharkk.net/go/iris
Quick Start
Standard API (image.Image compatible)
package main
import (
"image"
_ "git.sharkk.net/go/iris" // Register format
"os"
)
func main() {
// Decode
f, _ := os.Open("image.iris")
img, format, _ := image.Decode(f)
f.Close()
// img is now an image.Image
// format is "iris"
}
Encoding
package main
import (
"git.sharkk.net/go/iris"
"os"
)
func main() {
// Create new image
img := iris.NewImage(1024, 768, iris.FormatRGBA, iris.BitDepth8)
// Fill with pixel data...
// img.Pix() returns []byte for direct access
// Encode with default options (LZ4 compression)
f, _ := os.Create("output.iris")
iris.Encode(f, img)
f.Close()
}
With Metadata
opts := &iris.EncodeOptions{
Compression: iris.CompressionLZ4,
Metadata: iris.Metadata{
"sdf_range": "4.0",
"dpi": "96",
"tool": "myapp/1.0",
},
}
iris.EncodeWithOptions(f, img, opts)
Fast API (Zero-Copy)
For performance-critical applications like game engines:
// Decode - returns raw pixel bytes
pixels, width, height, format, _ := iris.DecodeFast(reader)
// Upload directly to GPU
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height,
0, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
// Encode
iris.EncodeFast(writer, pixels, width, height,
iris.FormatRGBA, iris.BitDepth8, iris.CompressionLZ4)
Supported Formats
| Format | Channels | Description |
|---|---|---|
| L | 1 | Grayscale |
| LA | 2 | Grayscale + Alpha |
| RGB | 3 | Red, Green, Blue |
| RGBA | 4 | Red, Green, Blue, Alpha |
- Bit Depth: 8 or 16 bits per channel
- Compression: Raw (uncompressed) or LZ4
- Byte Order: Little-endian for 16-bit
Performance
Typical performance on modern hardware:
- LZ4 Decompression: >1 GB/s
- LZ4 Compression: >500 MB/s
- Decode Overhead: <10% vs raw memcpy
Perfect for:
- SDF textures (smooth distance fields compress well)
- Game texture assets
- UI sprites and icons
- Real-time texture streaming
- Embedded systems (simple decoder)
API Reference
Core Types
type Image struct {
// Implements image.Image interface
}
type Format uint8 // L, LA, RGB, RGBA
type Compression uint8 // Raw, LZ4
type BitDepth uint8 // 8, 16
type Metadata map[string]string
Encoding
// Standard encoding with default options (LZ4)
func Encode(w io.Writer, img image.Image) error
// Encoding with custom options
func EncodeWithOptions(w io.Writer, img image.Image, opts *EncodeOptions) error
// Fast byte-level encoding
func EncodeFast(w io.Writer, pixels []byte, width, height int,
format Format, bitDepth BitDepth, compression Compression) error
Decoding
// Standard decoding (returns image.Image)
func Decode(r io.Reader) (image.Image, error)
// Decode just the config (dimensions, color model)
func DecodeConfig(r io.Reader) (image.Config, error)
// Fast byte-level decoding
func DecodeFast(r io.Reader) (pixels []byte, width, height int,
format Format, err error)
Creating Images
// Create new Iris image
func NewImage(width, height int, format Format, bitDepth BitDepth) *Image
// Access methods
img.Pix() // []byte - raw pixel data
img.Header() // Header - image properties
img.Metadata() // Metadata - key-value pairs
img.SetMetadata(key, value)
Metadata Keys
Common metadata keys (from specification):
sdf_range- Distance field range for SDF textures (e.g., "4.0")dpi- Dots per inch (e.g., "72", "96")origin- Coordinate origin ("top-left", "bottom-left")created- Creation timestamptool- Creation tool/version
Unknown keys are preserved for forward compatibility.
Format Details
File Structure
[Header: 20 bytes]
[Metadata: variable, optional]
[Image Data: variable]
Header (20 bytes, little-endian)
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | magic | "IRIS" (0x49 0x52 0x49 0x53) |
| 4 | 1 | version | Format version (1) |
| 5 | 1 | format | Pixel format (0-3) |
| 6 | 1 | compression | Compression mode (0-1) |
| 7 | 1 | bit_depth | Bits per channel (8 or 16) |
| 8 | 4 | width | Image width in pixels |
| 12 | 4 | height | Image height in pixels |
| 16 | 4 | meta_size | Metadata block size (0 if none) |
Pixel Data
- Raw Mode: Uncompressed pixels in row-major order
- LZ4 Mode: 4-byte compressed size + LZ4 block data
- No padding: Pixels are tightly packed
- 16-bit: Little-endian byte order
Implementation Notes
- Custom LZ4 implementation (~300 lines, no external dependencies)
- Safe bounds checking throughout
- Size limits: 64K pixels per dimension, 1GB uncompressed max
- Non-premultiplied alpha (NRGBA color model)
Examples
See the spec.md file for the complete format specification and additional examples.
License
This implementation follows the Sharkk Medium License as specified in spec.md.
Key points:
- Give credit to original authors
- Share-Alike with same license
- Non-commercial use only
- No warranty or liability
- Source code must be shared
See spec.md for full license text.
Contributing
This is a reference implementation of the Iris specification. See spec.md for format details.