creek

The AI Image Editor of 2030
commit 3408e8a25e3388446b3abd86573bbf0afb6140f0
parent 98e4272df49c3d08bf48a717559d5c6bf52113e6
Author: maydayv7 <maydayv7@gmail.com>
Date:   Thu,  4 Dec 2025 01:47:45 +0530

Update README and stylesheet page

Diffstat:
M.github/workflows/release.yml | 22++++++++++------------
MREADME.md | 51+++++++++++++++++++++++++++------------------------
Mandroid/.gitignore | 4++--
Mandroid/app/build.gradle.kts | 2+-
Dandroid/key.properties | 4----
Mflask/README.md | 61++++++++++++++++++-------------------------------------------
Mflask/requirements.txt | 1-
Mlib/ui/pages/stylesheet_page.dart | 45++++++++++++++++++++++++++++++++++++---------
8 files changed, 94 insertions(+), 96 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml @@ -14,25 +14,25 @@ jobs: runs-on: ubuntu-latest steps: - # 1. Checkout Code (with LFS for your ONNX models) + # 1. Checkout Code (with LFS) - name: Checkout code uses: actions/checkout@v4 with: - lfs: true + lfs: true # 2. Setup Java (Required for Android Build) - name: Setup Java uses: actions/setup-java@v4 with: - distribution: 'temurin' - java-version: '17' + distribution: "temurin" + java-version: "17" # 3. Setup Flutter - name: Setup Flutter uses: subosito/flutter-action@v2 with: - channel: 'stable' - flutter-version: '3.38.x' + channel: "stable" + flutter-version: "3.38.x" # 4. Create .env file from Secrets - name: Create .env file @@ -42,25 +42,23 @@ jobs: - name: Decode Keystore run: | echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > android/app/upload-keystore.jks - + echo "storePassword=${{ secrets.KEYSTORE_PASSWORD }}" >> android/key.properties echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/key.properties echo "keyAlias=${{ secrets.KEY_ALIAS }}" >> android/key.properties echo "storeFile=upload-keystore.jks" >> android/key.properties - # 6. Setup Python 3.11 (Matches your local version) + # 6. Setup Python 3.8 - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: "3.8" # 7. Install Dependencies - name: Install dependencies run: flutter pub get # 8. Build APK - # split-per-abi is optional, but --release is mandatory. - # Removing split-per-abi creates one "fat" APK compatible with all devices. - name: Build Release APK run: flutter build apk --release @@ -71,4 +69,4 @@ jobs: with: files: build/app/outputs/flutter-apk/app-release.apk generate_release_notes: false - body: "Inter IIT Adobe P.S. by IITG." + body: "adobe" diff --git a/README.md b/README.md @@ -4,32 +4,32 @@ A Flutter project with AI-based image analysis ## Prerequisites -- Flutter SDK -- Python 3.8 -- Kotlin + Gradle -- JDK -- Android SDK +- `git` & `git-lfs` +- Flutter SDK **>=3.7** +- Python **3.8** +- Gradle **8.9.1** +- Java/JDK **17** & Kotlin +- Android SDK & NDK + - Platform Level **>=34** + - Build Tools **>=34.0.0** + - NDK Version **27.0.12077973** + - CMake **3.22.1** + +Ensure that all these programs with the correct versions are installed on your system before using this repository ## Setup -### 1. Setup Python +### 1. Clone Repository -#### A) Install Python 3.8 - -**macOS:** +Clone using `git lfs clone` to ensure all models are correctly pulled -```bash -brew install python@3.8 -``` +### 2. Setup Python -**Linux:** +The Android app compiles Python code using [Chaquopy](https://chaquo.com/chaquopy/), which requires the following setup, mandatorily using Python Version 3.8: -```bash -sudo apt-get install python3.8 python3.8-venv -``` +#### A) Install Python 3.8 -**Windows:** -Download from [python.org](https://www.python.org/downloads/) +Download from [python.org](https://www.python.org/downloads/release/python-3810/) #### B) Set up Virtual Environment @@ -37,13 +37,16 @@ Download from [python.org](https://www.python.org/downloads/) python -m venv python_env ``` -### 3. AI Models - -Download the models from [here](https://mega.nz/folder/WghwgRYA#byC4igRSImx0LRd9KW40hw) and place them under `assets` - -### 4. Build the APK +### 3. Build the APK ```bash flutter clean -flutter build apk --release +flutter pub get +flutter build apk ``` + +If you have `adb` properly installed, you can use `flutter run` + +## Backend + +Read [flask/README.md](flask/README.md) to run the server diff --git a/android/.gitignore b/android/.gitignore @@ -7,8 +7,8 @@ gradle-wrapper.jar GeneratedPluginRegistrant.java .cxx/ -# Remember to never publicly share your keystore. +# Remember to never publicly share your keystore # See https://flutter.dev/to/reference-keystore -# key.properties +key.properties **/*.keystore **/*.jks diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts @@ -71,7 +71,7 @@ android { buildTypes { release { - // Signing with the relsease keys, so `flutter run --release` works. + // Signing with the release keys, so `flutter run --release` works. signingConfig = signingConfigs.getByName("release") // Optional: Enable shrinking for smaller APKs (recommended for release) diff --git a/android/key.properties b/android/key.properties @@ -1,4 +0,0 @@ -storePassword=interiit -keyPassword=interiit -keyAlias=upload -storeFile=upload-keystore.jks diff --git a/flask/README.md b/flask/README.md @@ -1,57 +1,32 @@ -# AI Image Generator Backend +# Backend -This project sets up a local Flask server that uses the Stable Diffusion v1.5 model to generate images from text prompts. -Prerequisites -Before you begin, ensure you have the following installed: -Python 3.10 or 3.11 (Recommended for compatibility) +This project provides a unified AI backend for image generation, inpainting, background removal, and captioning. It supports two modes of operation: -### Prerequisites +## 1. Local Server (`index.py`) -- NVIDIA GPU (Recommended) - You need a GPU with at least 4GB VRAM - Ensure you have the latest NVIDIA drivers installed - Check CUDA availability: Open terminal and run `nvidia-smi` +Runs purely on your local machine -## Installation & Setup +> [!IMPORTANT] +> Requires Cuda-enabled NVIDIA GPU -### A. Install Standard Packages +To run backend locally, run the following commands: -``` -pip install flask flask-cors diffusers transformers accelerate safetensors -``` - -### B. Install PyTorch & xFormers (GPU Acceleration) - -This step differs slightly depending on your OS and GPU - -#### Windows (NVIDIA GPU) - -To ensure you get the version compatible with your GPU, run: - -``` -pip install torch torchvision xformers --index-url https://download.pytorch.org/whl/cu118 -``` - -If you have a very new GPU, you can try `cu121` instead of `cu118` - -#### Mac (M1/M2/M3 Silicon) - -Macs use "MPS" (Metal Performance Shaders) instead of CUDA - -``` -pip install torch torchvision torchaudio +```shell +pip install -r requirements.txt +python ./index.py ``` -### C. Models +## 2. Cloud Server (`modal_app.py`) -Download the requisite models from [here](https://github.com/adobeinter/Adobe-Models/tree/main) +Deploys to [Modal.com](https://modal.com) for serverless GPU inference -## Running the Server +To deploy, run the following commands: ```shell -python index.py +pip install modal +modal setup +modal deploy modal_app.py ``` -# Server Deployment - -To deploy to [Modal](https://modal.com/) server, simply modify `modal_app.py` according to your requirements and run `modal deploy modal_app.py` +> [!NOTE] +> You must update the root `.env` file for the app to recognize the deployed backend diff --git a/flask/requirements.txt b/flask/requirements.txt @@ -6,7 +6,6 @@ fal-client flask flask-cors kornia -modal numpy opencv-python pillow diff --git a/lib/ui/pages/stylesheet_page.dart b/lib/ui/pages/stylesheet_page.dart @@ -28,6 +28,8 @@ class StylesheetPage extends StatefulWidget { class _StylesheetPageState extends State<StylesheetPage> { late int _currentProjectId; bool _isLoading = false; + // State to toggle hex code visibility + bool _showHexCodes = false; StylesheetData? _stylesheetData; String? _rawJsonString; @@ -80,7 +82,6 @@ class _StylesheetPageState extends State<StylesheetPage> { super.initState(); _currentProjectId = widget.projectId; if (widget.autoGenerate) { - // Generate stylesheet automatically after a short delay to ensure page is built WidgetsBinding.instance.addPostFrameCallback((_) { _generateStylesheet(); }); @@ -129,7 +130,6 @@ class _StylesheetPageState extends State<StylesheetPage> { StylesheetData? data; if (rawJson != null && rawJson.isNotEmpty) { - // Use the service to parse data = _stylesheetService.parse(rawJson); } @@ -194,7 +194,6 @@ class _StylesheetPageState extends State<StylesheetPage> { }), onSettingsPressed: () {}, ), - // Only show content once full stylesheet is parsed atleast once body: _isLoading ? const Center(child: CircularProgressIndicator(color: Variables.textPrimary)) : (_stylesheetData == null && _rawJsonString == null) @@ -281,7 +280,8 @@ class _StylesheetPageState extends State<StylesheetPage> { ); } - Widget _buildSectionHeader(String title, {bool showArrow = true}) { + // Modified to support a custom trailing widget (e.g. Eye Icon) + Widget _buildSectionHeader(String title, {bool showArrow = true, Widget? trailing}) { return Padding( padding: const EdgeInsets.only(bottom: 12), child: Row( @@ -299,7 +299,9 @@ class _StylesheetPageState extends State<StylesheetPage> { ), ), ), - if (showArrow) + if (trailing != null) + trailing + else if (showArrow) Transform.rotate( angle: 3.14159, child: SvgPicture.asset( @@ -329,10 +331,8 @@ class _StylesheetPageState extends State<StylesheetPage> { } Widget _buildLogosSection(dynamic data) { - // Use manually uploaded logos List<String> logoPaths = List.from(_logoPaths); - // Also add any logos from data if present if (data is List) { for (var item in data) { if (item is Map && item.containsKey('path')) logoPaths.add(item['path'].toString()); @@ -352,7 +352,6 @@ class _StylesheetPageState extends State<StylesheetPage> { separatorBuilder: (_, __) => const SizedBox(width: 8), itemBuilder: (context, index) { if (index == logoPaths.length) { - // Add button return GestureDetector( onTap: _pickLogo, child: Container( @@ -506,7 +505,19 @@ class _StylesheetPageState extends State<StylesheetPage> { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildSectionHeader("Colors", showArrow: false), + // Using custom trailing widget for the Eye Icon toggle + _buildSectionHeader( + "Colors", + showArrow: false, + trailing: GestureDetector( + onTap: () => setState(() => _showHexCodes = !_showHexCodes), + child: Icon( + _showHexCodes ? Icons.visibility : Icons.visibility_outlined, + color: Variables.textPrimary, + size: 20, + ), + ), + ), Wrap( spacing: 8, runSpacing: 8, children: colors.take(5).map((color) => _buildColorSwatch(color)).toList(), @@ -517,9 +528,25 @@ class _StylesheetPageState extends State<StylesheetPage> { } Widget _buildColorSwatch(Color color) { + final String hexCode = '#${color.value.toRadixString(16).padLeft(8, '0').substring(2).toUpperCase()}'; + final Color textColor = color.computeLuminance() > 0.5 ? Colors.black : Colors.white; + return Container( width: 104, height: 52, decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(8)), + alignment: Alignment.center, + // Only show text if _showHexCodes is true + child: _showHexCodes + ? Text( + hexCode, + style: TextStyle( + fontFamily: 'GeneralSans', + fontSize: 13, + fontWeight: FontWeight.w500, + color: textColor, + ), + ) + : null, ); }