Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ Canny Edge Detection: Extract structural outlines from any image to guide Contro
#### Canny Preprocessed
![cannyImage2](https://github.com/l8bloom/gosd/blob/main/examples/system/canny/canny_output.png)
#### ControlNet Output
With `A futuristic office with neon lights` prompt.
![cannyImage3](https://github.com/l8bloom/gosd/blob/main/examples/system/canny/image_from_canny_output.png)

(See `examples/system/canny/preprocess_canny.go` for a full implementation.)
Expand Down
Binary file modified examples/system/canny/image_from_canny_output.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/system/canny/preprocess_canny.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// example on how to use gosd for Canny processing
// 1st step: generate image
// 2nd step: apply canny algorithm
// 3rd step: pass the canny-processed image to a ControlNet

package main

Expand Down
2 changes: 2 additions & 0 deletions pkg/gosd/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ func newCacheParams() *cacheParams {
return cp
}

// CacheParamsInit creates a set of default cache values for inference.
// The cache values can be used for both video and image generation.
func CacheParamsInit() CacheParams {
cp := newCacheParams()

Expand Down
5 changes: 4 additions & 1 deletion pkg/gosd/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func loadCallbacks(lib ffi.Lib) error {
return nil
}

// Type used for SetPreviewCallback representing generated data
// Type used for SetPreviewCallback representing generated data.
type PreviewFrames interface {
Image | Video
}
Expand Down Expand Up @@ -81,6 +81,7 @@ type LogCallback func(level LogLevel, text string, data unsafe.Pointer)
var logCallback unsafe.Pointer
var sizeOfClosure = unsafe.Sizeof(ffi.Closure{})

// SetLogCallback sets custom logging for inference.
func SetLogCallback(callback LogCallback, data unsafe.Pointer) {
if callback == nil {
panic("Can't set nil as a callback")
Expand Down Expand Up @@ -134,6 +135,7 @@ type ProgressCallback func(step int32, steps int32, time float32, data unsafe.Po

var progressCallback unsafe.Pointer

// SetProgressCallback sets custom callback used after each inference iteration step.
func SetProgressCallback(callback ProgressCallback, data unsafe.Pointer) {
if callback == nil {
panic("Can't set nil as a callback")
Expand Down Expand Up @@ -189,6 +191,7 @@ type PreviewCallback[T PreviewFrames] func(step int32, frames T, isNoisy bool, d

var previewCallback unsafe.Pointer // keep in global due to GC

// SetPreviewCallback sets custom callback to preview images as they are generated during the inference loop.
// previewMode: mode in which to do the preview
// interval: iteration step slider
// denoised: should preview denoised images?
Expand Down
7 changes: 6 additions & 1 deletion pkg/gosd/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,14 +381,15 @@ func (e *Embedding) toC() *embedding {
}
}

// Creates default context params
// ContextParamsInit creates default context params.
func ContextParamsInit() ContextParams {
cp := newContextParams()

contextParamsInit.Call(nil, unsafe.Pointer(&cp))
return *cp.toGo()
}

// NewContext creates new inference context.
func NewContext(ctxParams ContextParams) Context {
var context Context

Expand All @@ -398,10 +399,12 @@ func NewContext(ctxParams ContextParams) Context {
return context
}

// FreeCtx deallocates memory used during the inference.
func FreeCtx(ctx Context) {
freeCtx.Call(nil, unsafe.Pointer(&ctx))
}

// CtxParamsToStr strigifies context structure.
func CtxParamsToStr(ctxParams ContextParams) string {
str := utilsGetNulString()

Expand All @@ -411,6 +414,7 @@ func CtxParamsToStr(ctxParams ContextParams) string {
return charToString(str)
}

// CtxSupportsImageGeneration checks if the context can be used for image generation.
func CtxSupportsImageGeneration(ctx Context) bool {
var res uint8

Expand All @@ -419,6 +423,7 @@ func CtxSupportsImageGeneration(ctx Context) bool {
return byteToBool(res)
}

// CtxSupportsVideoGeneration checks if the context can be used for video generation.
func CtxSupportsVideoGeneration(ctx Context) bool {
var res uint8

Expand Down
2 changes: 1 addition & 1 deletion pkg/gosd/gosd.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func getLibraryFilename(path, lib string) string {
}
}

// Load loads the stable-diffusion.cpp shared library at runtime and all dependent libs
// Load loads the stable-diffusion.cpp shared library at runtime and all dependent libs.
func Load() error {
lib, err := loadLibrary("stable-diffusion")
if err != nil {
Expand Down
13 changes: 9 additions & 4 deletions pkg/gosd/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ func (i *ImageParams) toC() *imageParams {
}
}

// GenerateImage starts the inference loop for image generation.
func GenerateImage(ctx Context, ip ImageParams) Image {
var image *image

Expand All @@ -583,13 +584,15 @@ func newImageParams() *imageParams {
return ip
}

// ImageGenParamsInit creates a set of default values for image generation.
func ImageGenParamsInit() ImageParams {
ip := newImageParams()

imageGenParamsInit.Call(nil, unsafe.Pointer(&ip))
return *ip.toGo()
}

// ImageGenParamsToStr stringifies structure encapsulating image generation parameters.
func ImageGenParamsToStr(ip ImageParams) string {
str := utilsGetNulString()

Expand All @@ -599,11 +602,12 @@ func ImageGenParamsToStr(ip ImageParams) string {
return charToString(str)
}

// this is not a core feature of the library,
// SavePNG saves generated images as .png to the local disk.
// NOTE: This is not a core feature of the library,
// just an example of what can be done with
// the generated image from the stable diffusion
// the generated image from the stable diffusion.
func (img Image) SavePNG(filename string) error {
pix := img.Pixelize()
pix := img.pixelize()

f, err := os.Create(filename)
if err != nil {
Expand All @@ -619,7 +623,7 @@ func (img Image) SavePNG(filename string) error {
return png.Encode(f, &pix)
}

func (img Image) Pixelize() imgPckg.RGBA {
func (img Image) pixelize() imgPckg.RGBA {
if len(img.Data) == 0 {
panic("Image with 0 length.")
}
Expand Down Expand Up @@ -651,6 +655,7 @@ func (img Image) Pixelize() imgPckg.RGBA {
return *rgba
}

// HiresParamsInit initializes default values for high-resolution upscaling.
func HiresParamsInit() HiresParams {
hp := newHiresParams()

Expand Down
4 changes: 4 additions & 0 deletions pkg/gosd/sampler.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ func newSampleParams() *sampleParamsType {
return &sampleParamsType{}
}

// SampleParamsInit initializes default values for the inference sampler.
func SampleParamsInit() SampleParamsType {
sp := newSampleParams()

Expand All @@ -136,6 +137,7 @@ func SampleParamsInit() SampleParamsType {
return *sp.toGo()
}

// SampleParamsToStr stringifies structure encapsulating sampler parameters.
func SampleParamsToStr(params SampleParamsType) string {
sp := params.toC()
str := utilsGetNulString()
Expand All @@ -145,6 +147,7 @@ func SampleParamsToStr(params SampleParamsType) string {
return charToString(str)
}

// GetDefaultSampleMethod returns default sampler method from a context.
func GetDefaultSampleMethod(ctx Context) SampleMethodType {
var sampleType SampleMethodType

Expand All @@ -153,6 +156,7 @@ func GetDefaultSampleMethod(ctx Context) SampleMethodType {
return sampleType
}

// GetDefaultScheduler returns default scheduler type from a context.
func GetDefaultScheduler(ctx Context, sampler SampleMethodType) SchedulerType {
var schedulerType SchedulerType

Expand Down
29 changes: 27 additions & 2 deletions pkg/gosd/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ func loadSystemRoutines(lib ffi.Lib) error {
return nil
}

// GetSystemInfo returns a formatted string containing the CPU instruction sets
// supported by the current hardware (e.g., AVX, AVX2, FMA). This is used
// to verify which hardware acceleration features are active for GGML operations.
func GetSystemInfo() string {
var systemInfo *byte

Expand All @@ -178,6 +181,7 @@ func GetSystemInfo() string {
return charToString(systemInfo)
}

// Commit returns stable-diffusion.cpp commit hash.
func Commit() string {
var commitInfo *byte

Expand All @@ -189,6 +193,7 @@ func Commit() string {
return charToString(commitInfo)
}

// Version returns stable-diffusion.cpp release version.
func Version() string {
var versionInfo *byte

Expand All @@ -200,20 +205,23 @@ func Version() string {
return charToString(versionInfo)
}

// GetNumPhysicalCores returns number of physical cores in the system.
func GetNumPhysicalCores() int {
var count int

getNumPhysicalCores.Call(unsafe.Pointer(&count))
return count
}

// TypeName stringifies SDType
func TypeName(sdType SDType) string {
res := utilsGetNulString()

typeName.Call(unsafe.Pointer(&res), unsafe.Pointer(&sdType))
return charToString(res)
}

// StrToSDType converts SDType name to its enumeration.
func StrToSDType(typeName string) SDType {
var sdType SDType
name := utilsStrToNulString(typeName)
Expand All @@ -222,13 +230,15 @@ func StrToSDType(typeName string) SDType {
return sdType
}

// RNGTypeName stringifies RNGType.
func RNGTypeName(rngType RNGType) string {
res := utilsGetNulString()

rngTypeName.Call(unsafe.Pointer(&res), unsafe.Pointer(&rngType))
return charToString(res)
}

// StrToRNGType converts RNGType name to its enumeration.
func StrToRNGType(typeName string) RNGType {
var rngType RNGType
name := utilsStrToNulString(typeName)
Expand All @@ -237,13 +247,15 @@ func StrToRNGType(typeName string) RNGType {
return rngType
}

// SampleMethodName stringifies SampleMethodType.
func SampleMethodName(sampleMethod SampleMethodType) string {
res := utilsGetNulString()

sampleMethodName.Call(unsafe.Pointer(&res), unsafe.Pointer(&sampleMethod))
return charToString(res)
}

// StrToSampleMethod converts SampleMethodType name to its enumeration.
func StrToSampleMethod(typeName string) SampleMethodType {
var sampleMethodType SampleMethodType
name := utilsStrToNulString(typeName)
Expand All @@ -252,13 +264,15 @@ func StrToSampleMethod(typeName string) SampleMethodType {
return sampleMethodType
}

// SchedulerName stringifies SchedulerType.
func SchedulerName(schedulerType SchedulerType) string {
res := utilsGetNulString()

schedulerName.Call(unsafe.Pointer(&res), unsafe.Pointer(&schedulerType))
return charToString(res)
}

// StrToScheduler converts SchedulerType name to its enumeration.
func StrToScheduler(typeName string) SchedulerType {
var schedulerType SchedulerType
name := utilsStrToNulString(typeName)
Expand All @@ -267,13 +281,15 @@ func StrToScheduler(typeName string) SchedulerType {
return schedulerType
}

// PredictionName stringifies PredictionType.
func PredictionName(predictionType PredictionType) string {
res := utilsGetNulString()

predictionName.Call(unsafe.Pointer(&res), unsafe.Pointer(&predictionType))
return charToString(res)
}

// StrToPrediction converts PredictionType name to its enumeration.
func StrToPrediction(typeName string) PredictionType {
var predictionType PredictionType
name := utilsStrToNulString(typeName)
Expand All @@ -282,13 +298,15 @@ func StrToPrediction(typeName string) PredictionType {
return predictionType
}

// PreviewName stringifies PreviewMode
func PreviewName(previewType PreviewMode) string {
res := utilsGetNulString()

previewName.Call(unsafe.Pointer(&res), unsafe.Pointer(&previewType))
return charToString(res)
}

// StrToPreview converts PreviewMode name to its enumeration.
func StrToPreview(typeName string) PreviewMode {
var previewMode PreviewMode
name := utilsStrToNulString(typeName)
Expand All @@ -297,13 +315,15 @@ func StrToPreview(typeName string) PreviewMode {
return previewMode
}

// LoraApplyModeName stringifies LoraApplyModeType.
func LoraApplyModeName(loraMode LoraApplyModeType) string {
res := utilsGetNulString()

loraApplyModeName.Call(unsafe.Pointer(&res), unsafe.Pointer(&loraMode))
return charToString(res)
}

// StrToLoraApplyMode converts LoraApplyModeType to its enumeration.
func StrToLoraApplyMode(typeName string) LoraApplyModeType {
var loraMode LoraApplyModeType
name := utilsStrToNulString(typeName)
Expand All @@ -312,13 +332,15 @@ func StrToLoraApplyMode(typeName string) LoraApplyModeType {
return loraMode
}

// HiresUpscalerName stringifies HiresUpscalerType.
func HiresUpscalerName(hiresMode HiresUpscalerType) string {
res := utilsGetNulString()

hiresUpscalerName.Call(unsafe.Pointer(&res), unsafe.Pointer(&hiresMode))
return charToString(res)
}

// StrToHiresUpscaler converts HiresUpscalerType to its enumeration.
func StrToHiresUpscaler(typeName string) HiresUpscalerType {
var hiresMode HiresUpscalerType
name := utilsStrToNulString(typeName)
Expand All @@ -327,7 +349,9 @@ func StrToHiresUpscaler(typeName string) HiresUpscalerType {
return hiresMode
}

// CPU-bound API
// Convert converts model to safetensor/gguf format.
// If VAE model is provided it will be merged with the diffusion model.
// CPU-bound API.
func Convert(modelPath string, vaePath string, outputPath string, outputType SDType, tensorTypeRules string, convertName bool) bool {
mp := stringToChar(modelPath)
vp := stringToChar(vaePath)
Expand All @@ -349,8 +373,9 @@ func Convert(modelPath string, vaePath string, outputPath string, outputType SDT
return byteToBool(res)
}

// PreprocessCanny applies Canny algorithm for edge detection in an image.
// CPU-bound API.
func PreprocessCanny(image Image, highThreshold float32, lowThreshold float32, weak float32, strong float32, inverse bool) bool {

img := *image.toC()
inv := boolToByte(inverse)

Expand Down
Loading
Loading