summaryrefslogtreecommitdiff
path: root/internal/comic/artist.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/comic/artist.go')
-rw-r--r--internal/comic/artist.go97
1 files changed, 65 insertions, 32 deletions
diff --git a/internal/comic/artist.go b/internal/comic/artist.go
index aa1dd5f..a54c01a 100644
--- a/internal/comic/artist.go
+++ b/internal/comic/artist.go
@@ -14,41 +14,57 @@ import (
// ArtistConfig configures comic page generation.
type ArtistConfig struct {
- ImageProvider provider.ImageProvider
- TextProvider provider.TextProvider
- Prompts PromptRenderer
- OutputDir string
- Style string
- Theme string
- Language string
- Script string
- UltraRealistic bool
- StoryPages int
- GalleryPages int
- PanelsPerPage int
+ ImageProvider provider.ImageProvider
+ TextProvider provider.TextProvider
+ Prompts PromptRenderer
+ OutputDir string
+ Style string
+ ComicStyles []string
+ RealisticStyles []string
+ Theme string
+ AspectRatio string
+ Language string
+ Script string
+ UltraRealistic bool
+ StoryPages int
+ GalleryPages int
+ PanelsPerPage int
+ PromptMaxChars int
+ PageMaxRetries int
+ PageRetryBase time.Duration
}
// Artist generates comic-book pages.
type Artist struct {
- imageProvider provider.ImageProvider
- textProvider provider.TextProvider
- prompts PromptRenderer
- outputDir string
- style string
- theme string
- language string
- script string
- ultraRealistic bool
- storyPages int
- galleryPages int
- panelsPerPage int
- initErr error
+ imageProvider provider.ImageProvider
+ textProvider provider.TextProvider
+ prompts PromptRenderer
+ outputDir string
+ style string
+ comicStyles []string
+ realisticStyles []string
+ theme string
+ aspectRatio string
+ language string
+ script string
+ ultraRealistic bool
+ storyPages int
+ galleryPages int
+ panelsPerPage int
+ promptMaxChars int
+ pageMaxRetries int
+ pageRetryBase time.Duration
+ initErr error
}
type referenceImageGenerator interface {
GenerateImageWithReferences(context.Context, string, string, [][]byte) error
}
+type referenceAspectRatioImageGenerator interface {
+ GenerateImageWithReferencesAndAspectRatio(context.Context, string, string, [][]byte, string) error
+}
+
var sleep = time.Sleep
// NewArtist creates an Artist.
@@ -72,7 +88,10 @@ func NewArtist(cfg *ArtistConfig) *Artist {
a.prompts = cfg.Prompts
a.outputDir = orDefault(cfg.OutputDir, a.outputDir)
a.style = cfg.Style
+ a.comicStyles = append([]string(nil), cfg.ComicStyles...)
+ a.realisticStyles = append([]string(nil), cfg.RealisticStyles...)
a.theme = cfg.Theme
+ a.aspectRatio = orDefault(cfg.AspectRatio, comicPageAspectRatio)
a.language = orDefault(cfg.Language, a.language)
a.script = orDefault(cfg.Script, a.script)
a.ultraRealistic = cfg.UltraRealistic
@@ -85,6 +104,13 @@ func NewArtist(cfg *ArtistConfig) *Artist {
if cfg.PanelsPerPage > 0 {
a.panelsPerPage = cfg.PanelsPerPage
}
+ a.promptMaxChars = normalizePositive(cfg.PromptMaxChars, comicPromptMaxChars)
+ a.pageMaxRetries = normalizePositive(cfg.PageMaxRetries, pageMaxRetries)
+ if cfg.PageRetryBase > 0 {
+ a.pageRetryBase = cfg.PageRetryBase
+ } else {
+ a.pageRetryBase = pageRetryBase
+ }
if a.imageProvider == nil {
a.initErr = fmt.Errorf("%w: image provider", ErrMissingProvider)
@@ -102,7 +128,7 @@ func (a *Artist) DrawComicPages(ctx context.Context, storyText, bible, titleSlug
}
style := a.style
if style == "" {
- style = pickStyle(nil, a.ultraRealistic)
+ style = pickStyle(a.comicStyles, a.realisticStyles, a.ultraRealistic)
}
fmt.Printf(" Comic style: %s\n", style)
@@ -184,7 +210,7 @@ func (a *Artist) renderPage(ctx context.Context, fileName, templateName string,
}
func (a *Artist) generateWithRetry(ctx context.Context, prompt, outputFile, label string, refs [][]byte) error {
- attempts := pageMaxRetries
+ attempts := a.pageMaxRetries
for attempt := 1; attempt <= attempts; attempt++ {
callCtx, cancel := withTimeout(ctx, helperTimeout)
err := a.generateImage(callCtx, prompt, outputFile, refs)
@@ -199,7 +225,7 @@ func (a *Artist) generateWithRetry(ctx context.Context, prompt, outputFile, labe
return nil
}
if attempt < attempts {
- pause := pageRetryBase * time.Duration(attempt)
+ pause := a.pageRetryBase * time.Duration(attempt)
fmt.Printf(" Warning: %s attempt %d/%d failed (%v), retrying in %s...\n", label, attempt, attempts, err, pause)
sleep(pause)
continue
@@ -210,11 +236,17 @@ func (a *Artist) generateWithRetry(ctx context.Context, prompt, outputFile, labe
}
func (a *Artist) generateImage(ctx context.Context, prompt, outputFile string, refs [][]byte) error {
+ if withRefs, ok := a.imageProvider.(referenceAspectRatioImageGenerator); ok {
+ return withRefs.GenerateImageWithReferencesAndAspectRatio(ctx, prompt, outputFile, refs, a.aspectRatio)
+ }
if len(refs) > 0 {
if withRefs, ok := a.imageProvider.(referenceImageGenerator); ok {
return withRefs.GenerateImageWithReferences(ctx, prompt, outputFile, refs)
}
}
+ if withAspectRatio, ok := a.imageProvider.(provider.AspectRatioImageProvider); ok {
+ return withAspectRatio.GenerateImageWithAspectRatio(ctx, prompt, outputFile, a.aspectRatio)
+ }
return a.imageProvider.GenerateImage(ctx, prompt, outputFile)
}
@@ -299,7 +331,7 @@ func (a *Artist) storyPagePromptData(section string, pageNum int, style, bible s
"RequiredDialoguePanels": requiredDialoguePanels(a.panelsPerPage),
"TotalPanels": a.storyPages * a.panelsPerPage,
"PanelLabelsText": panelLabelsText(a.panelsPerPage),
- "PanelLayout": buildPanelLayout(section, pageScriptForPage(panelScript, pageNum-1), a.panelsPerPage),
+ "PanelLayout": buildPanelLayout(section, pageScriptForPage(panelScript, pageNum-1), a.panelsPerPage, a.promptMaxChars),
"RenderingRequirement": a.renderingRequirement(),
"RenderingRequirementEnd": a.renderingRequirementEnd(),
}
@@ -362,7 +394,7 @@ func pageScriptForPage(panelScript [][]string, idx int) []string {
return panelScript[idx]
}
-func buildPanelLayout(section string, pagePanels []string, panelCount int) string {
+func buildPanelLayout(section string, pagePanels []string, panelCount, promptMaxChars int) string {
panelCount = normalizePositive(panelCount, defaultStoryPanelsPerPage)
if len(pagePanels) == panelCount && allPanelsPresent(pagePanels) {
var sb strings.Builder
@@ -378,8 +410,9 @@ func buildPanelLayout(section string, pagePanels []string, panelCount int) strin
}
excerpt := strings.TrimSpace(section)
- if utf8.RuneCountInString(excerpt) > comicPromptMaxChars {
- excerpt = string([]rune(excerpt)[:comicPromptMaxChars])
+ promptMaxChars = normalizePositive(promptMaxChars, comicPromptMaxChars)
+ if utf8.RuneCountInString(excerpt) > promptMaxChars {
+ excerpt = string([]rune(excerpt)[:promptMaxChars])
if idx := strings.LastIndex(excerpt, " "); idx > 0 {
excerpt = excerpt[:idx]
}