malina

command module
v0.0.0-...-d397474 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

README

Copyright 2025-2026 Ardan Labs

hello@ardanlabs.com

Malina

This project lets you use Go for hardware accelerated local image generation with stable-diffusion.cpp directly integrated into your applications. Malina provides a high-level API that mirrors stable-diffusion.h 1-to-1 plus pure-Go PNG/JPEG I/O and Motion-JPEG AVI muxing so you can hand any prompt to a Stable Diffusion model and get an image (or a short video) back.

Malina is the image-generation sibling of ardanlabs/bucky (which binds whisper.cpp) and hybridgroup/yzma (which binds llama.cpp). The end goal is to give Kronk a native, OpenAI-compatible POST /v1/images/generations endpoint without the CGo toolchain.

Malina is the Russian word for "raspberry" — a small, dense, fast-growing fruit. Naming a stable-diffusion binding after a fast little thing that sprouts colorful pictures is just good taste.

To install malina, fetch the stable-diffusion.cpp shared libraries, and generate the bundled cat sample:

$ go install github.com/ardanlabs/malina@latest

$ malina install -lib ./lib
$ export MALINA_LIB=$(pwd)/lib

$ malina model pull sd-1.5
$ export MALINA_TEST_MODEL=$HOME/models/sd-1.5/v1-5-pruned-emaonly.safetensors
$ go run ./examples/hello "a lovely cat"

Project Status

Go Reference Go Report Card go.mod Go version stable-diffusion.cpp Release

Linux macOS Windows

Sometimes there are breaking changes to stable-diffusion.cpp that require an update to malina. Here are the known compatible versions:

stable-diffusion.cpp malina
master-656-0e4ee04 0.1.x

The core FFI binding (context init, generate_image, image I/O, log/progress callbacks, GGML backend introspection), pure-Go PNG/JPEG decode + Motion-JPEG AVI mux, CLI (install, system, info, model list|pull), and examples (hello, system, sd-encode, flux2) have all landed. Kronk integration (an OpenAI-compatible POST /v1/images/generations endpoint) lives in the kronk repo.

Owner Information

Name:     Bill Kennedy
Company:  Ardan Labs
Title:    Managing Partner
Email:    bill@ardanlabs.com
BlueSky:  https://bsky.app/profile/goinggo.net
LinkedIn: www.linkedin.com/in/william-kennedy-5b318778/
Twitter:  https://x.com/goinggodotnet

Install Malina

The fastest way to install on any supported platform is with Go:

$ go install github.com/ardanlabs/malina@latest

$ malina --help

Then fetch the stable-diffusion.cpp shared library bundle (dylib on darwin, DLLs on windows, .tar.gz on linux — all sourced from the upstream leejet/stable-diffusion.cpp releases):

$ malina install -lib ./lib
$ export MALINA_LIB=$(pwd)/lib
$ malina system

And pull a model bundle from the bundled catalog:

$ malina model list
$ malina model pull sd-1.5
$ malina model info -m ~/models/sd-1.5/v1-5-pruned-emaonly.safetensors

Issues/Features

Here is the existing Issues/Features for the project and the things being worked on or things that would be nice to have.

If you are interested in helping in any way, please send an email to Bill Kennedy.

Architecture

The architecture of malina mirrors bucky and yzma file-for-file so anyone who knows either can drop straight in. There is no CGo: every C call goes through purego + JupiterRider/ffi.

┌─────────────────────────────────────────────────────────────┐
│  cmd/         malina CLI (install, system, model, sd)       │
├─────────────────────────────────────────────────────────────┤
│  pkg/sd       1-to-1 mirror of stable-diffusion.h           │
│               (context, gen_params, generate, video,        │
│                image I/O, log, system)                      │
│  pkg/download go-getter-driven release-archive resolver +   │
│               bundle catalog (sd-1.5, sdxl, flux2)          │
│  pkg/loader   MALINA_LIB-aware purego library loader        │
│  pkg/utils    cross-platform Go ↔ C string helpers          │
└─────────────────────────────────────────────────────────────┘
                          │
                          ▼
            libstable-diffusion.{dylib|so|dll}
              (stable-diffusion.cpp master-656)

Models

Malina works with any model stable-diffusion.cpp accepts: .safetensors and .gguf checkpoints for SD 1.x / SD 2.x / SDXL, plus the multi-file FLUX and SD3 layouts (separate diffusion model + VAE + text-encoder files). Recommended hosts are stable-diffusion-v1-5/stable-diffusion-v1-5 and the GGUF quants under city96.

Malina ships a small bundled catalog so you can malina model pull sd-1.5 instead of pasting URLs:

$ malina model list
$ malina model pull sd-1.5
$ malina model pull sdxl-base-1.0
$ malina model pull flux2-klein-9b   # license-gated; export HF_TOKEN first

Each bundle drops every required file into $HOME/models/<bundle>/ along with a manifest.json the examples use to resolve paths.

Support

Malina uses the prebuilt stable-diffusion.cpp release artifacts from leejet/stable-diffusion.cpp directly — there is no companion builder repo. The pinned version is captured in pkg/download/install.go as DefaultSDVersion.

OS CPU GPU Source
Linux amd64 CPU (avx2) sd-master-…-linux-avx2-x64.tar.gz (upstream)
macOS arm64 Metal sd-master-…-bin-MacOS-arm64.tar.gz (upstream)
Windows amd64 CPU, CUDA 12 sd-master-…-bin-win-avx2-x64.zip / -cuda12-… (upstream)

Whenever there is a new release of stable-diffusion.cpp, the FFI struct mirrors in pkg/sd and the version constant in pkg/download may need a refresh. Bump DefaultSDVersion, regenerate any struct-size assertions in pkg/sd/*_test.go, and let CI verify.

API Examples

There are examples in the examples/ directory. Each one expects MALINA_LIB and (for the model-loading examples) MALINA_TEST_MODEL to be set:

$ export MALINA_LIB=$(pwd)/lib
$ export MALINA_TEST_MODEL=$HOME/models/sd-1.5/v1-5-pruned-emaonly.safetensors

SYSTEM — the smallest possible malina program: load libstable-diffusion and print the library version, system info, and GGML backend device count. No model required.

$ make example-system

HELLO — load a stable-diffusion model, generate one image from a text prompt, and save it as hello.png.

$ make example-hello

IMG2IMG — image-to-image: load a source PNG or JPEG, hand it to stable-diffusion as the starting latent, and let the prompt repaint it. The default chain consumes hello.png written by the previous example.

$ make example-hello       # writes hello.png
$ make example-img2img     # writes img2img.png in oil-painting style

FLUX2 — multi-file FLUX.2 [klein] 9B pipeline using a quantized diffusion model + VAE + Qwen3 LLM text encoder. The example reads the bundle's manifest.json to resolve each file's on-disk path.

$ export HF_TOKEN=hf_...              # FLUX.2 license must be accepted
$ malina model pull flux2-klein-9b    # one-time
$ make example-flux2

SD-ENCODE — mux a directory of PNG / JPEG frames into a Motion-JPEG AVI. No model is loaded; this is the pure-Go encoder built on top of pkg/sd's SaveAVI helper.

$ make example-sd-encode

Sample API Program — Hello Example

// hello is the smallest possible malina example: load a stable-diffusion
// model, generate one image from a text prompt, and save it as PNG.
package main

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/ardanlabs/malina/pkg/sd"
)

func main() {
	prompt := "a lovely cat"
	if len(os.Args) >= 2 {
		prompt = os.Args[1]
	}

	libPath := os.Getenv("MALINA_LIB")
	if libPath == "" {
		log.Fatal("MALINA_LIB must point to the directory containing libstable-diffusion")
	}

	modelPath := os.Getenv("MALINA_TEST_MODEL")
	if modelPath == "" {
		log.Fatal("MALINA_TEST_MODEL must point to a stable-diffusion model file (.gguf or .safetensors)")
	}

	if err := sd.Load(libPath); err != nil {
		log.Fatalf("sd.Load: %v", err)
	}
	if err := sd.Init(libPath); err != nil {
		log.Fatalf("sd.Init: %v", err)
	}

	cparams := sd.ContextParamsInit()
	cparams.ModelPath = modelPath

	fmt.Println("loading model from", modelPath, "...")
	ctx, err := sd.NewContext(cparams)
	if err != nil {
		log.Fatalf("sd.NewContext: %v", err)
	}
	defer sd.FreeContext(ctx)

	params := sd.ImgGenParamsInit()
	params.Prompt = prompt

	fmt.Println("generating image for prompt:", prompt)
	start := time.Now()
	img, err := sd.GenerateImage(ctx, params)
	if err != nil {
		log.Fatalf("sd.GenerateImage: %v", err)
	}
	elapsed := time.Since(start)

	const outPath = "hello.png"
	if err := img.SavePNG(outPath); err != nil {
		log.Fatalf("SavePNG: %v", err)
	}
	fmt.Printf("wrote %s (%dx%d, %d channels) in %s\n", outPath, img.Width, img.Height, img.Channel, elapsed.Round(time.Millisecond))
}

This example produces the following output:

$ make example-hello
go run ./examples/hello "a lovely cat"
loading model from /Users/bill/models/sd-1.5/v1-5-pruned-emaonly.safetensors ...
generating image for prompt: a lovely cat
wrote hello.png (512x512, 3 channels) in 6.842s

License

Apache-2.0 — see LICENSE.

Documentation

Overview

malina lets you write Go applications that directly integrate stable-diffusion.cpp (https://github.com/leejet/stable-diffusion.cpp) for fully local text-to-image and image editing using hardware acceleration.

malina is the text-to-image sibling of bucky (https://github.com/ardanlabs/bucky), which provides the same kind of FFI bindings for whisper.cpp.

Directories

Path Synopsis
Package cmd implements the malina CLI subcommands (install, system, model, sd, info) wired into urfave/cli.
Package cmd implements the malina CLI subcommands (install, system, model, sd, info) wired into urfave/cli.
examples
flux2 command
flux2 mirrors gosd's flagship example: a multi-file FLUX.2 [klein] 9B pipeline using a quantized diffusion model + VAE + Qwen3 LLM text encoder.
flux2 mirrors gosd's flagship example: a multi-file FLUX.2 [klein] 9B pipeline using a quantized diffusion model + VAE + Qwen3 LLM text encoder.
hello command
hello is the smallest possible malina example: load a stable-diffusion model, generate one image from a text prompt, and save it as PNG.
hello is the smallest possible malina example: load a stable-diffusion model, generate one image from a text prompt, and save it as PNG.
img2img command
img2img demonstrates image-to-image generation: load a stable-diffusion model, encode a source image (PNG or JPEG) as the starting latent, then denoise it using the supplied text prompt and save the result as PNG.
img2img demonstrates image-to-image generation: load a stable-diffusion model, encode a source image (PNG or JPEG) as the starting latent, then denoise it using the supplied text prompt and save the result as PNG.
sd-encode command
sd-encode is the smallest possible "images to video" example: read a collection of PNG and/or JPEG frames from a directory and mux them into a single Motion-JPEG AVI.
sd-encode is the smallest possible "images to video" example: read a collection of PNG and/or JPEG frames from a directory and mux them into a single Motion-JPEG AVI.
system command
system is the smallest possible malina example: load libstable-diffusion and print the library version and system info.
system is the smallest possible malina example: load libstable-diffusion and print the library version and system info.
pkg
download
Package download provides utilities for downloading curated stable-diffusion model bundles.
Package download provides utilities for downloading curated stable-diffusion model bundles.
loader
Package loader provides functions for loading the shared stable-diffusion.cpp libraries.
Package loader provides functions for loading the shared stable-diffusion.cpp libraries.
sd
Package sd provides Go FFI bindings to stable-diffusion.cpp using purego and jupiterrider/ffi.
Package sd provides Go FFI bindings to stable-diffusion.cpp using purego and jupiterrider/ffi.
utils
Package utils provides small string conversion helpers used by the malina FFI bindings.
Package utils provides small string conversion helpers used by the malina FFI bindings.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL