commit d601ad746c8825abbe47fedcd6b3a4274bb9f26d
parent 3b4a61633cd4d6a6a9a0af74dd1906a5076b7bc5
Author: maydayv7 <maydayv7@gmail.com>
Date: Wed, 3 Dec 2025 03:54:13 +0530
Revert stylesheet to prompt generation
Diffstat:
1 file changed, 14 insertions(+), 302 deletions(-)
diff --git a/lib/services/flask_service.dart b/lib/services/flask_service.dart
@@ -22,7 +22,6 @@ class FlaskService {
static String get _urlAsset => dotenv.env['URL_ASSET'] ?? '';
static String get _urlDescribe => dotenv.env['URL_DESCRIBE'] ?? '';
-
static const Map<String, String> _headers = {
'Content-Type': 'application/json',
};
@@ -80,271 +79,13 @@ class FlaskService {
}
// ===========================================================================
- // 1.5. STYLE PROMPT GENERATION (From Stylesheet - New Feature)
- // ===========================================================================
-
- /// Generates a style prompt from a stylesheet JSON following the notebook logic.
- /// Returns a formatted style instruction string or a default fallback.
- String generateStylePromptFromStylesheet(String? stylesheetJson) {
- if (stylesheetJson == null || stylesheetJson.isEmpty) {
- return "high quality, realistic";
- }
-
- try {
- // Parse the JSON
- Map<String, dynamic> sheet = jsonDecode(stylesheetJson);
-
- // Normalize: extract from "results" if present
- Map<String, dynamic> results =
- sheet.containsKey('results') ? sheet['results'] as Map<String, dynamic> : sheet;
-
- // Normalize the sheet structure
- Map<String, Map<String, dynamic>> normalized = _normalizeStylesheet(results);
-
- // Extract style phrases
- List<String> stylePhrases = _pickStylePhrases(normalized);
-
- // Extract top colors
- List<String> topColors = _extractTopColors(results);
-
- // Build style instruction
- String styleInstruction = "";
- if (stylePhrases.isNotEmpty) {
- styleInstruction =
- "User prefers these style cues (use as inspiration): ${stylePhrases.join('; ')}";
- }
- if (topColors.isNotEmpty) {
- String colorStr = topColors.join(", ");
- if (styleInstruction.isNotEmpty) {
- styleInstruction += "; color palette: $colorStr";
- } else {
- styleInstruction = "color palette: $colorStr";
- }
- }
-
- // Get tone hint from primary style
- String primaryStyle = "";
- if (normalized.containsKey('Style')) {
- dynamic primary = normalized['Style']!['Primary'];
- primaryStyle =
- primary is String ? primary : (primary is List && primary.isNotEmpty ? primary[0] : "");
- }
- String toneHint = _styleToTone(primaryStyle);
-
- // Combine everything
- List<String> parts = [];
- if (styleInstruction.isNotEmpty) {
- parts.add(styleInstruction);
- }
- parts.add("Tone: $toneHint");
-
- return parts.join(". ");
- } catch (e) {
- debugPrint("❌ Error generating style prompt: $e");
- return "high quality, realistic";
- }
- }
-
- /// Normalizes the stylesheet structure into a consistent format
- Map<String, Map<String, dynamic>> _normalizeStylesheet(Map<String, dynamic> results) {
- Map<String, Map<String, dynamic>> normalized = {};
-
- // Categories to extract
- List<String> categories = [
- "Style",
- "Background/Texture",
- "Lighting",
- "Composition",
- "Era/Cultural Reference",
- "Material Look",
- "Typography",
- ];
-
- // Also check for variations
- Map<String, List<String>> categoryAliases = {
- "Style": ["style", "Style"],
- "Background/Texture": [
- "Background/Texture",
- "background/texture",
- "Texture",
- "texture",
- "Background",
- "background"
- ],
- "Lighting": ["Lighting", "lighting"],
- "Composition": ["Composition", "composition", "Compositions", "compositions"],
- "Era/Cultural Reference": ["Era/Cultural Reference", "era / reference", "Era", "era"],
- "Material Look": ["Material Look", "material look", "Material look"],
- "Typography": ["Typography", "typography", "Fonts", "fonts"],
- };
-
- for (String category in categories) {
- List<String> labels = [];
- List<String> aliases = categoryAliases[category] ?? [category];
-
- // Find the category in results
- dynamic categoryData;
- for (String alias in aliases) {
- if (results.containsKey(alias)) {
- categoryData = results[alias];
- break;
- }
- }
-
- if (categoryData == null) continue;
-
- // Extract labels from the category data
- List<dynamic> items = [];
- if (categoryData is List) {
- items = categoryData;
- } else if (categoryData is Map && categoryData.containsKey('scores')) {
- items = categoryData['scores'] is List ? categoryData['scores'] : [];
- }
-
- // Sort by score if available
- try {
- items.sort((a, b) {
- double scoreA = 0.0, scoreB = 0.0;
- if (a is Map) scoreA = (a['score'] ?? 0.0).toDouble();
- if (b is Map) scoreB = (b['score'] ?? 0.0).toDouble();
- return scoreB.compareTo(scoreA);
- });
- } catch (_) {}
-
- // Extract labels
- for (var item in items) {
- String? label;
- if (item is Map) {
- label = item['label']?.toString();
- } else if (item is String) {
- label = item;
- }
- if (label != null && label.isNotEmpty) {
- labels.add(label.trim());
- }
- }
-
- if (labels.isNotEmpty) {
- normalized[category] = {
- 'Primary': labels.first,
- 'Secondary': labels.length > 1 ? labels.sublist(1) : [],
- };
- }
- }
-
- return normalized;
- }
-
- /// Picks style phrases from normalized stylesheet (following notebook logic)
- List<String> _pickStylePhrases(Map<String, Map<String, dynamic>> normalized,
- {int maxSecondaries = 3}) {
- Map<String, String> keyMap = {
- "Style": "style",
- "Background/Texture": "background/texture",
- "Lighting": "lighting",
- "Composition": "composition",
- "Era/Cultural Reference": "era / reference",
- "Material Look": "material look",
- "Typography": "typography",
- };
-
- List<String> phrases = [];
-
- for (String category in normalized.keys) {
- Map<String, dynamic>? entry = normalized[category];
- if (entry == null) continue;
-
- dynamic primaryValue = entry['Primary'];
- List<String> primary =
- primaryValue is String ? [primaryValue] : (primaryValue is List ? List<String>.from(primaryValue) : []);
- List<String> secondary = entry['Secondary'] ?? [];
-
- List<String> chosen = [];
- if (primary.isNotEmpty) {
- chosen.addAll(primary);
- }
- for (String s in secondary) {
- if (chosen.length < (1 + maxSecondaries)) {
- chosen.add(s);
- }
- }
-
- if (chosen.isNotEmpty) {
- String key = keyMap[category] ?? category.toLowerCase();
- phrases.add("$key: ${chosen.join(', ')}");
- }
- }
-
- return phrases;
- }
-
- /// Extracts top colors from stylesheet
- List<String> _extractTopColors(Map<String, dynamic> results, {int maxColors = 5}) {
- dynamic palette = results['Color Palette'] ??
- results['Colour Palette'] ??
- results['colors'] ??
- results['Colors'];
-
- if (palette == null) return [];
-
- List<dynamic> paletteList = [];
- if (palette is List) {
- paletteList = palette;
- } else if (palette is Map && palette.containsKey('scores')) {
- paletteList = palette['scores'] is List ? palette['scores'] : [];
- }
-
- // Sort by score
- try {
- paletteList.sort((a, b) {
- double scoreA = 0.0, scoreB = 0.0;
- if (a is Map) scoreA = (a['score'] ?? 0.0).toDouble();
- if (b is Map) scoreB = (b['score'] ?? 0.0).toDouble();
- return scoreB.compareTo(scoreA);
- });
- } catch (_) {}
-
- List<String> colors = [];
- for (var item in paletteList) {
- String? label;
- if (item is Map) {
- label = item['label']?.toString();
- } else if (item is String) {
- label = item;
- }
- if (label != null && label.isNotEmpty) {
- colors.add(label.trim());
- if (colors.length >= maxColors) break;
- }
- }
-
- return colors;
- }
-
- /// Determines tone hint from primary style
- String _styleToTone(String primary) {
- String s = primary.toLowerCase();
- if (s.contains("retro") ||
- s.contains("collage") ||
- s.contains("poster") ||
- s.contains("pop-art") ||
- s.contains("surreal")) {
- return "illustrative, textured, poster-like";
- }
- if (s.contains("photoreal") || s.contains("realistic") || s.contains("film")) {
- return "photorealistic, high-detail";
- }
- return "high detail, sharp focus";
- }
-
- // ===========================================================================
// 2. GENERATION SERVICES (Returns File Path)
// ===========================================================================
/// [Text-to-Image]
Future<String?> generateAndSaveImage(String prompt) async {
return _performImageOperation(
- endpoint: '/generate',
+ fullUrl: _urlGenerate,
logPrefix: '🎨 Text-to-Image',
body: {'prompt': prompt},
filenamePrefix: prompt,
@@ -363,7 +104,7 @@ class FlaskService {
if (base64Image == null || base64Mask == null) return null;
return _performImageOperation(
- endpoint: '/inpainting',
+ fullUrl: _urlInpainting,
logPrefix: '🖌️ Inpainting',
body: {
'prompt': prompt,
@@ -445,15 +186,8 @@ class FlaskService {
// This returns the path to the no-background version
return generateAsset(imagePath: generatedImagePath);
-
-
-
-
-
}
-
-
/// [Background Removal]
Future<String?> generateAsset({required String imagePath}) async {
// 1. Prepare and Upload
@@ -461,7 +195,7 @@ class FlaskService {
if (base64Image == null) return null;
final String? generatedAssetPath = await _performImageOperation(
- endpoint: '/asset',
+ fullUrl: _urlAsset,
logPrefix: '✂️ Asset Gen',
body: {'image': base64Image},
filenamePrefix: 'asset',
@@ -525,6 +259,8 @@ class FlaskService {
required String imagePath,
String prompt = '<MORE_DETAILED_CAPTION>',
}) async {
+ debugPrint("👁️ [Describe] Preparing request...");
+
final String? base64Image = await _encodeFile(imagePath);
if (base64Image == null) return null;
@@ -550,47 +286,22 @@ class FlaskService {
// ===========================================================================
Future<String?> _performImageOperation({
- String? endpoint,
- String? fullUrl,
+ required String fullUrl,
required String logPrefix,
required Map<String, dynamic> body,
required String filenamePrefix,
}) async {
- String url;
- if (fullUrl != null) {
- url = fullUrl;
- } else if (endpoint != null) {
- // Map endpoints to their corresponding URL getters
- switch (endpoint) {
- case '/generate':
- url = _urlGenerate;
- break;
- case '/inpainting':
- url = _urlInpainting;
- break;
- case '/asset':
- url = _urlAsset;
- break;
- case '/describe':
- url = _urlDescribe;
- break;
- default:
- url = '';
- }
- } else {
- return null;
- }
+ debugPrint("$logPrefix Sending request to $fullUrl...");
- if (url.isEmpty) {
- return null;
- }
-
- final response = await _postRequest(fullUrl: url, body: body);
+ final response = await _postRequest(fullUrl: fullUrl, body: body);
if (response != null && response.statusCode == 200) {
return _saveImageFromResponse(response, filenamePrefix);
}
+ debugPrint(
+ "❌ $logPrefix Failed: ${response?.statusCode ?? 'No Connection'}",
+ );
return null;
}
@@ -600,6 +311,7 @@ class FlaskService {
}) async {
try {
if (fullUrl.isEmpty) {
+ debugPrint("❌ Config Error: URL is missing in .env");
return null;
}
return await http.post(
@@ -608,6 +320,7 @@ class FlaskService {
body: jsonEncode(body),
);
} catch (e) {
+ debugPrint("❌ Network Error ($fullUrl): $e");
return null;
}
}
@@ -660,4 +373,4 @@ class FlaskService {
return null;
}
}
-}
-\ No newline at end of file
+}