diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-20 08:01:01 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-20 08:01:01 +0300 |
| commit | af2aa5e5efa82d3bc7cf5530e0a1eee72ba99244 (patch) | |
| tree | 609634b874bd4a82e5df7d9b56d8505cac14fdd6 /internal/comic/image_validation.go | |
| parent | a35ca6f40de73e93372ade6f2d74c231389799e2 (diff) | |
Fix task 25 follow-up: stop PNG prompt leaks and keep comics consistent
Diffstat (limited to 'internal/comic/image_validation.go')
| -rw-r--r-- | internal/comic/image_validation.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/internal/comic/image_validation.go b/internal/comic/image_validation.go new file mode 100644 index 0000000..475cb96 --- /dev/null +++ b/internal/comic/image_validation.go @@ -0,0 +1,68 @@ +package comic + +import ( + "bytes" + "context" + "fmt" + "os/exec" + "strings" +) + +var imageLeakMarkers = []string{ + "mandatory language rule", + "this is a bulgarian comic book", + "bulgarian comic book", + "mandatory panel layout", + "mandatory speech bubbles", + "ultra-realistic rendering", + "final lock", + "photorealism", + "character & setting reference", + "this is a text-free character gallery page", + "story page", + "gallery page", + "back cover", + "cover lines", + "story teaser", + "story ending hint", + "art style:", + "no panel grid", + "no speech bubbles", + "no text of any kind", +} + +var validateImagePromptLeakageFn = validateImagePromptLeakage + +func validateImagePromptLeakage(ctx context.Context, outputFile, label string) error { + if ctx == nil { + ctx = context.Background() + } + + tesseractPath, err := exec.LookPath("tesseract") + if err != nil { + return nil + } + + cmd := exec.CommandContext(ctx, tesseractPath, outputFile, "stdout", "-l", "eng", "--psm", "11") + var out bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &bytes.Buffer{} + if err := cmd.Run(); err != nil { + return fmt.Errorf("%s OCR failed: %w", label, err) + } + + ocr := strings.ToLower(out.String()) + if marker, ok := findImageLeakMarker(ocr); ok { + return fmt.Errorf("%s contains prompt leakage marker %q", label, marker) + } + return nil +} + +func findImageLeakMarker(text string) (string, bool) { + for _, marker := range imageLeakMarkers { + if strings.Contains(text, marker) { + return marker, true + } + } + return "", false +} |
